From c6445b749c727b506da1f753b068ae371657cba1 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Wed, 13 Apr 2016 16:43:55 -0700 Subject: [PATCH] Change AesCbcEncryptor/AesCbcDecryptor kNoPadding behavior Leave unaligned residual block in clear in stead of rejecting it. Change-Id: Id5452f32f6147e26ac68d9cddb948e8b4f77d107 --- packager/media/base/aes_cryptor_unittest.cc | 3 +++ packager/media/base/aes_decryptor.cc | 11 ++++++++++- packager/media/base/aes_encryptor.cc | 12 ++++++------ packager/media/base/aes_encryptor.h | 4 ++++ packager/media/formats/mp4/encrypting_fragmenter.cc | 7 +------ 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/packager/media/base/aes_cryptor_unittest.cc b/packager/media/base/aes_cryptor_unittest.cc index 5328f3f9c7..de4b8d6596 100644 --- a/packager/media/base/aes_cryptor_unittest.cc +++ b/packager/media/base/aes_cryptor_unittest.cc @@ -553,6 +553,9 @@ const CbcTestCase kCbcTestCases[] = { {kNoPadding, "6bc1bee22e409f96e93d7e117393172a6bc1bee22e409f96e93d7e117393172a", "77cde91fe6df9cbc5d0c98f96efd590bbddde439526f100c9545c274d4f7fd3f"}, + {kNoPadding, + "6bc1bee22e409f96e93d7e117393172a6bc1bee22e409f96e93d7e117393172a1234", + "77cde91fe6df9cbc5d0c98f96efd590bbddde439526f100c9545c274d4f7fd3f1234"}, // Pkcs5 padding with zero bytes. {kPkcs5Padding, "", "f6a3569dea3cda208eb3d5792942612b"}, // Cts Padding with zero bytes. diff --git a/packager/media/base/aes_decryptor.cc b/packager/media/base/aes_decryptor.cc index 58a8945c78..969219b907 100644 --- a/packager/media/base/aes_decryptor.cc +++ b/packager/media/base/aes_decryptor.cc @@ -84,6 +84,7 @@ bool AesCbcDecryptor::CryptInternal(const uint8_t* ciphertext, std::vector local_iv(iv()); const size_t residual_block_size = ciphertext_size % AES_BLOCK_SIZE; + const size_t cbc_size = ciphertext_size - residual_block_size; if (residual_block_size == 0) { AES_cbc_encrypt(ciphertext, plaintext, ciphertext_size, aes_key(), local_iv.data(), AES_DECRYPT); @@ -101,6 +102,15 @@ bool AesCbcDecryptor::CryptInternal(const uint8_t* ciphertext, } *plaintext_size -= num_padding_bytes; return true; + } else if (padding_scheme_ == kNoPadding) { + AES_cbc_encrypt(ciphertext, plaintext, cbc_size, aes_key(), local_iv.data(), + AES_DECRYPT); + if (chain_across_calls_) + set_iv(local_iv); + + // The residual block is not encrypted. + memcpy(plaintext + cbc_size, ciphertext + cbc_size, residual_block_size); + return true; } else if (padding_scheme_ != kCtsPadding) { LOG(ERROR) << "Expecting cipher text size to be multiple of " << AES_BLOCK_SIZE << ", got " << ciphertext_size; @@ -116,7 +126,6 @@ bool AesCbcDecryptor::CryptInternal(const uint8_t* ciphertext, } // AES-CBC decrypt everything up to the next-to-last full block. - const size_t cbc_size = ciphertext_size - residual_block_size; if (cbc_size > AES_BLOCK_SIZE) { AES_cbc_encrypt(ciphertext, plaintext, cbc_size - AES_BLOCK_SIZE, aes_key(), local_iv.data(), AES_DECRYPT); diff --git a/packager/media/base/aes_encryptor.cc b/packager/media/base/aes_encryptor.cc index 53b20f4bc4..4cce506d13 100644 --- a/packager/media/base/aes_encryptor.cc +++ b/packager/media/base/aes_encryptor.cc @@ -171,12 +171,6 @@ bool AesCbcEncryptor::CryptInternal(const uint8_t* plaintext, DCHECK(aes_key()); const size_t residual_block_size = plaintext_size % AES_BLOCK_SIZE; - if (padding_scheme_ == kNoPadding && residual_block_size != 0) { - LOG(ERROR) << "Expecting input size to be multiple of " << AES_BLOCK_SIZE - << ", got " << plaintext_size; - return false; - } - const size_t num_padding_bytes = NumPaddingBytes(plaintext_size); const size_t required_ciphertext_size = plaintext_size + num_padding_bytes; if (*ciphertext_size < required_ciphertext_size) { @@ -205,6 +199,12 @@ bool AesCbcEncryptor::CryptInternal(const uint8_t* plaintext, } DCHECK(!chain_across_calls_); + if (padding_scheme_ == kNoPadding) { + // The residual block is left unencrypted. + memcpy(ciphertext + cbc_size, plaintext + cbc_size, residual_block_size); + return true; + } + std::vector residual_block(plaintext + cbc_size, plaintext + plaintext_size); DCHECK_EQ(residual_block.size(), residual_block_size); diff --git a/packager/media/base/aes_encryptor.h b/packager/media/base/aes_encryptor.h index ceea48a4c0..0b58b2a505 100644 --- a/packager/media/base/aes_encryptor.h +++ b/packager/media/base/aes_encryptor.h @@ -71,8 +71,12 @@ class AesCtrEncryptor : public AesEncryptor { }; enum CbcPaddingScheme { + // Residual block is left unencrypted. kNoPadding, + // Residual block is padded with pkcs5 and encrypted. kPkcs5Padding, + // Residual block and the next-to-last block are encrypted using ciphertext + // stealing method. kCtsPadding, }; diff --git a/packager/media/formats/mp4/encrypting_fragmenter.cc b/packager/media/formats/mp4/encrypting_fragmenter.cc index c6b7817eae..27fdb9be5e 100644 --- a/packager/media/formats/mp4/encrypting_fragmenter.cc +++ b/packager/media/formats/mp4/encrypting_fragmenter.cc @@ -330,12 +330,7 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr sample) { traf()->auxiliary_size.sample_info_sizes.push_back( sample_encryption_entry.ComputeSize()); } else { - uint64_t encryption_data_size = sample->data_size(); - // AES-CBC mode requires all encrypted cipher blocks to be 16 bytes. The - // partial blocks are left unencrypted. - if (protection_scheme_ == FOURCC_cbc1) - encryption_data_size -= encryption_data_size % kCencBlockSize; - EncryptBytes(data, encryption_data_size); + EncryptBytes(data, sample->data_size()); } traf()->sample_encryption.sample_encryption_entries.push_back(