Improve support for decryption of full sample encrypted cbcs
1. Allow encryption pattern of 0:0, which is treated as 1:0; 2. Remove the special handling of pattern 1:0 in pattern cryptor which may not always be correct; 3. Allow senc/saio/saiz boxes to be absent. Change-Id: I372e61182ec577107e39cb601c3aed80616b036d
This commit is contained in:
parent
e7393fcc22
commit
4c6e5f4fa6
|
@ -23,11 +23,9 @@ AesPatternCryptor::AesPatternCryptor(uint8_t crypt_byte_block,
|
||||||
skip_byte_block_(skip_byte_block),
|
skip_byte_block_(skip_byte_block),
|
||||||
encryption_mode_(encryption_mode),
|
encryption_mode_(encryption_mode),
|
||||||
cryptor_(std::move(cryptor)) {
|
cryptor_(std::move(cryptor)) {
|
||||||
// |crypt_byte_block_| should never be 0. |skip_byte_block_| can be 0 to allow
|
// Treat pattern 0:0 as 1:0.
|
||||||
// a special pattern of 1:0, which is the pattern for the case of pattern
|
if (crypt_byte_block_ == 0 && skip_byte_block_ == 0)
|
||||||
// encryption when applied to non video tracks.
|
crypt_byte_block_ = 1;
|
||||||
DCHECK_NE(crypt_byte_block_, 0u);
|
|
||||||
DCHECK(skip_byte_block_ != 0 || crypt_byte_block_ == 1);
|
|
||||||
DCHECK(cryptor_);
|
DCHECK(cryptor_);
|
||||||
DCHECK(!cryptor_->use_constant_iv());
|
DCHECK(!cryptor_->use_constant_iv());
|
||||||
}
|
}
|
||||||
|
@ -51,17 +49,6 @@ bool AesPatternCryptor::CryptInternal(const uint8_t* text,
|
||||||
}
|
}
|
||||||
*crypt_text_size = text_size;
|
*crypt_text_size = text_size;
|
||||||
|
|
||||||
// Handle the special pattern 1:0.
|
|
||||||
if (skip_byte_block_ == 0) {
|
|
||||||
DCHECK_EQ(crypt_byte_block_, 1u);
|
|
||||||
const size_t crypt_byte_size = text_size / AES_BLOCK_SIZE * AES_BLOCK_SIZE;
|
|
||||||
if (!cryptor_->Crypt(text, crypt_byte_size, crypt_text))
|
|
||||||
return false;
|
|
||||||
memcpy(crypt_text + crypt_byte_size, text + crypt_byte_size,
|
|
||||||
text_size - crypt_byte_size);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (text_size > 0) {
|
while (text_size > 0) {
|
||||||
const size_t crypt_byte_size = crypt_byte_block_ * AES_BLOCK_SIZE;
|
const size_t crypt_byte_size = crypt_byte_block_ * AES_BLOCK_SIZE;
|
||||||
if (NeedEncrypt(text_size, crypt_byte_size)) {
|
if (NeedEncrypt(text_size, crypt_byte_size)) {
|
||||||
|
|
|
@ -72,7 +72,7 @@ class AesPatternCryptor : public AesCryptor {
|
||||||
|
|
||||||
bool NeedEncrypt(size_t input_size, size_t target_data_size);
|
bool NeedEncrypt(size_t input_size, size_t target_data_size);
|
||||||
|
|
||||||
const uint8_t crypt_byte_block_;
|
uint8_t crypt_byte_block_;
|
||||||
const uint8_t skip_byte_block_;
|
const uint8_t skip_byte_block_;
|
||||||
const PatternEncryptionMode encryption_mode_;
|
const PatternEncryptionMode encryption_mode_;
|
||||||
std::unique_ptr<AesCryptor> cryptor_;
|
std::unique_ptr<AesCryptor> cryptor_;
|
||||||
|
|
|
@ -219,35 +219,5 @@ TEST(SampleAesPatternCryptor, MoreThan16Bytes) {
|
||||||
ASSERT_TRUE(pattern_cryptor.Crypt("0123456789abcdef012", &crypt_text));
|
ASSERT_TRUE(pattern_cryptor.Crypt("0123456789abcdef012", &crypt_text));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FullSampleSpecialPatternTest, Test) {
|
|
||||||
MockAesCryptor* mock_cryptor = new MockAesCryptor();
|
|
||||||
EXPECT_CALL(*mock_cryptor, CryptInternal(_, 96u, _, _))
|
|
||||||
.WillOnce(Invoke([](const uint8_t* text, size_t text_size,
|
|
||||||
uint8_t* crypt_text, size_t* crypt_text_size) {
|
|
||||||
*crypt_text_size = text_size;
|
|
||||||
for (size_t i = 0; i < text_size; ++i)
|
|
||||||
*crypt_text++ = 'e';
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
const uint8_t kFulLSampleCryptBlock = 1;
|
|
||||||
const uint8_t kFullSampleSkipBlock = 0;
|
|
||||||
AesPatternCryptor pattern_cryptor(
|
|
||||||
kFulLSampleCryptBlock, kFullSampleSkipBlock,
|
|
||||||
AesPatternCryptor::kSkipIfCryptByteBlockRemaining,
|
|
||||||
AesPatternCryptor::kUseConstantIv,
|
|
||||||
std::unique_ptr<MockAesCryptor>(mock_cryptor));
|
|
||||||
|
|
||||||
std::vector<uint8_t> iv(8, 'i');
|
|
||||||
// SetIv will be called only once by AesPatternCryptor::SetIv.
|
|
||||||
EXPECT_TRUE(pattern_cryptor.SetIv(iv));
|
|
||||||
|
|
||||||
std::string input_text(100, 'c');
|
|
||||||
std::string crypt_text;
|
|
||||||
// More than 16 bytes so mock's CryptInternal should be called.
|
|
||||||
ASSERT_TRUE(pattern_cryptor.Crypt(input_text, &crypt_text));
|
|
||||||
EXPECT_EQ(std::string(96, 'e') + std::string(4, 'c'), crypt_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
|
@ -589,8 +589,11 @@ const TrackEncryption& TrackRunIterator::track_encryption() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
|
std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
|
||||||
|
std::vector<uint8_t> iv;
|
||||||
|
std::vector<SubsampleEntry> subsamples;
|
||||||
|
|
||||||
size_t sample_idx = sample_itr_ - run_itr_->samples.begin();
|
size_t sample_idx = sample_itr_ - run_itr_->samples.begin();
|
||||||
DCHECK_LT(sample_idx, run_itr_->sample_encryption_entries.size());
|
if (sample_idx < run_itr_->sample_encryption_entries.size()) {
|
||||||
const SampleEncryptionEntry& sample_encryption_entry =
|
const SampleEncryptionEntry& sample_encryption_entry =
|
||||||
run_itr_->sample_encryption_entries[sample_idx];
|
run_itr_->sample_encryption_entries[sample_idx];
|
||||||
DCHECK(is_encrypted());
|
DCHECK(is_encrypted());
|
||||||
|
@ -604,9 +607,12 @@ std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
|
||||||
return std::unique_ptr<DecryptConfig>();
|
return std::unique_ptr<DecryptConfig>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iv = sample_encryption_entry.initialization_vector;
|
||||||
|
subsamples = sample_encryption_entry.subsamples;
|
||||||
|
}
|
||||||
|
|
||||||
FourCC protection_scheme = is_audio() ? audio_description().sinf.type.type
|
FourCC protection_scheme = is_audio() ? audio_description().sinf.type.type
|
||||||
: video_description().sinf.type.type;
|
: video_description().sinf.type.type;
|
||||||
std::vector<uint8_t> iv = sample_encryption_entry.initialization_vector;
|
|
||||||
if (iv.empty()) {
|
if (iv.empty()) {
|
||||||
if (protection_scheme != FOURCC_cbcs) {
|
if (protection_scheme != FOURCC_cbcs) {
|
||||||
LOG(WARNING)
|
LOG(WARNING)
|
||||||
|
@ -619,8 +625,8 @@ std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::unique_ptr<DecryptConfig>(new DecryptConfig(
|
return std::unique_ptr<DecryptConfig>(new DecryptConfig(
|
||||||
track_encryption().default_kid, iv, sample_encryption_entry.subsamples,
|
track_encryption().default_kid, iv, subsamples, protection_scheme,
|
||||||
protection_scheme, track_encryption().default_crypt_byte_block,
|
track_encryption().default_crypt_byte_block,
|
||||||
track_encryption().default_skip_byte_block));
|
track_encryption().default_skip_byte_block));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue