From 4c6e5f4fa644cd6e10a9841119062ab795ea852f Mon Sep 17 00:00:00 2001 From: Kongqun Yang Date: Thu, 13 Oct 2016 14:29:15 -0700 Subject: [PATCH] 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 --- packager/media/base/aes_pattern_cryptor.cc | 19 ++-------- packager/media/base/aes_pattern_cryptor.h | 2 +- .../base/aes_pattern_cryptor_unittest.cc | 30 ---------------- .../media/formats/mp4/track_run_iterator.cc | 36 +++++++++++-------- 4 files changed, 25 insertions(+), 62 deletions(-) diff --git a/packager/media/base/aes_pattern_cryptor.cc b/packager/media/base/aes_pattern_cryptor.cc index 987e8fa25c..3849d66fb2 100644 --- a/packager/media/base/aes_pattern_cryptor.cc +++ b/packager/media/base/aes_pattern_cryptor.cc @@ -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)) { diff --git a/packager/media/base/aes_pattern_cryptor.h b/packager/media/base/aes_pattern_cryptor.h index d3b5bbe78d..f65f71e5c0 100644 --- a/packager/media/base/aes_pattern_cryptor.h +++ b/packager/media/base/aes_pattern_cryptor.h @@ -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 cryptor_; diff --git a/packager/media/base/aes_pattern_cryptor_unittest.cc b/packager/media/base/aes_pattern_cryptor_unittest.cc index c42f99975d..0b73a2c46e 100644 --- a/packager/media/base/aes_pattern_cryptor_unittest.cc +++ b/packager/media/base/aes_pattern_cryptor_unittest.cc @@ -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(mock_cryptor)); - - std::vector 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 diff --git a/packager/media/formats/mp4/track_run_iterator.cc b/packager/media/formats/mp4/track_run_iterator.cc index 87551d7084..d6546ab1f3 100644 --- a/packager/media/formats/mp4/track_run_iterator.cc +++ b/packager/media/formats/mp4/track_run_iterator.cc @@ -589,24 +589,30 @@ const TrackEncryption& TrackRunIterator::track_encryption() const { } std::unique_ptr TrackRunIterator::GetDecryptConfig() { - size_t sample_idx = sample_itr_ - run_itr_->samples.begin(); - DCHECK_LT(sample_idx, run_itr_->sample_encryption_entries.size()); - const SampleEncryptionEntry& sample_encryption_entry = - run_itr_->sample_encryption_entries[sample_idx]; - DCHECK(is_encrypted()); - DCHECK(!AuxInfoNeedsToBeCached()); + std::vector iv; + std::vector subsamples; - const size_t total_size_of_subsamples = - sample_encryption_entry.GetTotalSizeOfSubsamples(); - if (total_size_of_subsamples != 0 && - total_size_of_subsamples != static_cast(sample_size())) { - LOG(ERROR) << "Incorrect CENC subsample size."; - return std::unique_ptr(); + size_t sample_idx = sample_itr_ - run_itr_->samples.begin(); + if (sample_idx < run_itr_->sample_encryption_entries.size()) { + const SampleEncryptionEntry& sample_encryption_entry = + run_itr_->sample_encryption_entries[sample_idx]; + DCHECK(is_encrypted()); + DCHECK(!AuxInfoNeedsToBeCached()); + + const size_t total_size_of_subsamples = + sample_encryption_entry.GetTotalSizeOfSubsamples(); + if (total_size_of_subsamples != 0 && + total_size_of_subsamples != static_cast(sample_size())) { + LOG(ERROR) << "Incorrect CENC subsample size."; + return std::unique_ptr(); + } + + 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 iv = sample_encryption_entry.initialization_vector; if (iv.empty()) { if (protection_scheme != FOURCC_cbcs) { LOG(WARNING) @@ -619,8 +625,8 @@ std::unique_ptr TrackRunIterator::GetDecryptConfig() { } } return std::unique_ptr(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)); }