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:
Kongqun Yang 2016-10-13 14:29:15 -07:00 committed by KongQun Yang
parent e7393fcc22
commit 4c6e5f4fa6
4 changed files with 25 additions and 62 deletions

View File

@ -23,11 +23,9 @@ AesPatternCryptor::AesPatternCryptor(uint8_t crypt_byte_block,
skip_byte_block_(skip_byte_block),
encryption_mode_(encryption_mode),
cryptor_(std::move(cryptor)) {
// |crypt_byte_block_| should never be 0. |skip_byte_block_| can be 0 to allow
// a special pattern of 1:0, which is the pattern for the case of pattern
// encryption when applied to non video tracks.
DCHECK_NE(crypt_byte_block_, 0u);
DCHECK(skip_byte_block_ != 0 || crypt_byte_block_ == 1);
// Treat pattern 0:0 as 1:0.
if (crypt_byte_block_ == 0 && skip_byte_block_ == 0)
crypt_byte_block_ = 1;
DCHECK(cryptor_);
DCHECK(!cryptor_->use_constant_iv());
}
@ -51,17 +49,6 @@ bool AesPatternCryptor::CryptInternal(const uint8_t* text,
}
*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) {
const size_t crypt_byte_size = crypt_byte_block_ * AES_BLOCK_SIZE;
if (NeedEncrypt(text_size, crypt_byte_size)) {

View File

@ -72,7 +72,7 @@ class AesPatternCryptor : public AesCryptor {
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 PatternEncryptionMode encryption_mode_;
std::unique_ptr<AesCryptor> cryptor_;

View File

@ -219,35 +219,5 @@ TEST(SampleAesPatternCryptor, MoreThan16Bytes) {
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 shaka

View File

@ -589,8 +589,11 @@ const TrackEncryption& TrackRunIterator::track_encryption() const {
}
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();
DCHECK_LT(sample_idx, run_itr_->sample_encryption_entries.size());
if (sample_idx < run_itr_->sample_encryption_entries.size()) {
const SampleEncryptionEntry& sample_encryption_entry =
run_itr_->sample_encryption_entries[sample_idx];
DCHECK(is_encrypted());
@ -604,9 +607,12 @@ std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
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
: video_description().sinf.type.type;
std::vector<uint8_t> iv = sample_encryption_entry.initialization_vector;
if (iv.empty()) {
if (protection_scheme != FOURCC_cbcs) {
LOG(WARNING)
@ -619,8 +625,8 @@ std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
}
}
return std::unique_ptr<DecryptConfig>(new DecryptConfig(
track_encryption().default_kid, iv, sample_encryption_entry.subsamples,
protection_scheme, track_encryption().default_crypt_byte_block,
track_encryption().default_kid, iv, subsamples, protection_scheme,
track_encryption().default_crypt_byte_block,
track_encryption().default_skip_byte_block));
}