Fix pattern encryption when applying to patterns other than 1:9

We used to skip all the remaining bytes if the size is less than
|crypt_byte_block| blocks.

This interpretation is incorrect. We should only leave the last partial
16-byte block un-encrypted.

Change-Id: I4f09600efa52e2fdf4d0b661dfc418dcb675f9f6
This commit is contained in:
KongQun Yang 2018-08-28 16:28:26 -07:00
parent 60df64705b
commit 86b10b6316
3 changed files with 41 additions and 31 deletions

View File

@ -51,14 +51,31 @@ bool AesPatternCryptor::CryptInternal(const uint8_t* text,
while (text_size > 0) {
const size_t crypt_byte_size = crypt_byte_block_ * AES_BLOCK_SIZE;
if (NeedEncrypt(text_size, crypt_byte_size)) {
if (!cryptor_->Crypt(text, crypt_byte_size, crypt_text))
return false;
} else {
// If there is not enough data, just keep it in clear.
if (text_size <= crypt_byte_size) {
const bool need_encrypt =
encryption_mode_ == kSkipIfCryptByteBlockRemaining
? (text_size > crypt_byte_size)
: (text_size >= AES_BLOCK_SIZE);
if (need_encrypt) {
// The partial pattern SHALL be followed with the partial 16-byte block
// remains unencrypted.
const size_t aligned_crypt_byte_size =
text_size / AES_BLOCK_SIZE * AES_BLOCK_SIZE;
if (!cryptor_->Crypt(text, aligned_crypt_byte_size, crypt_text))
return false;
text += aligned_crypt_byte_size;
text_size -= aligned_crypt_byte_size;
crypt_text += aligned_crypt_byte_size;
}
// The remaining bytes are not encrypted.
memcpy(crypt_text, text, text_size);
return true;
}
if (!cryptor_->Crypt(text, crypt_byte_size, crypt_text))
return false;
text += crypt_byte_size;
text_size -= crypt_byte_size;
crypt_text += crypt_byte_size;
@ -77,12 +94,5 @@ void AesPatternCryptor::SetIvInternal() {
CHECK(cryptor_->SetIv(iv()));
}
bool AesPatternCryptor::NeedEncrypt(size_t input_size,
size_t target_data_size) {
if (encryption_mode_ == kSkipIfCryptByteBlockRemaining)
return input_size > target_data_size;
return input_size >= target_data_size;
}
} // namespace media
} // namespace shaka

View File

@ -19,18 +19,16 @@ class AesPatternCryptor : public AesCryptor {
/// Enumerator for controling encrytion/decryption mode for the last
/// encryption/decrytion block(s).
enum PatternEncryptionMode {
/// Use kEncryptIfCryptByteBlockRemaining if the last blocks is exactly the
/// same as the number of remaining bytes. IOW
/// if (remaining_bytes == encryption_block_bytes)
/// encrypt(remaining_data)
/// Use kEncryptIfCryptByteBlockRemaining to encrypt all the full 16-byte
/// blocks even if the remaining bytes are less than encryption_block_bytes.
/// IOW:
/// if (remaining_bytes <= encryption_block_bytes)
/// encrypt(block_aligned_remaining_data)
kEncryptIfCryptByteBlockRemaining,
/// Use kSkipIfCryptByteBlockRemaining to not encrypt/decrypt the last
/// clocks if it is exactly the same as the number of remaining bytes.
/// if (remaining_bytes > encryption_block_bytes) {
/// // Since this is the last blocks, this is effectively the same
/// // condition as remaining_bytes != encryption_block_bytes.
/// Use kSkipIfCryptByteBlockRemaining to not encrypt/decrypt the remaining
/// bytes if it is less than or equal to encryption_block_bytes.
/// if (remaining_bytes > encryption_block_bytes)
/// encrypt().
/// }
/// Use this mode for HLS SAMPLE-AES.
kSkipIfCryptByteBlockRemaining,
};
@ -70,8 +68,6 @@ class AesPatternCryptor : public AesCryptor {
size_t* crypt_text_size) override;
void SetIvInternal() override;
bool NeedEncrypt(size_t input_size, size_t target_data_size);
uint8_t crypt_byte_block_;
const uint8_t skip_byte_block_;
const PatternEncryptionMode encryption_mode_;

View File

@ -103,11 +103,15 @@ const PatternTestCase kPatternTestCases[] = {
{"", ""},
// One partial block (not encrypted).
{"010203", "010203"},
// One block (not encrypted).
{"01020304050607080910111213141516", "01020304050607080910111213141516"},
// One block + partial block (not encrypted).
{"010203040506070809101112131415161718",
"010203040506070809101112131415161718"},
// One block (encrypted).
{"01020304050607080910111213141516", "11121314151617181920212223242526"},
// One block + partial block.
{// One block encrypted.
"01020304050607080910111213141516"
// Partial block unencrypted.
"1718",
"11121314151617181920212223242526"
"1718"},
// Two blocks (encrypted) - the mock encryptor adds every byte by 0x10.
{"0102030405060708091011121314151617181920212223242526272829303132",
"1112131415161718192021222324252627282930313233343536373839404142"},
@ -125,13 +129,13 @@ const PatternTestCase kPatternTestCases[] = {
"4950515253545556575859606162636465666768697071727374757677787980"
// kSkipByteBlock (1) block not encrypted.
"81828384858687888990919293949596"
// Less than kCryptByteBlock blocks remaining, so not encrypted.
// One full block remaining, encrypted.
"97989900010203040506070809101112",
"1112131415161718192021222324252627282930313233343536373839404142"
"33343536373839404142434445464748"
"5960616263646566676869707172737475767778798081828384858687888990"
"81828384858687888990919293949596"
"97989900010203040506070809101112"},
"a7a8a910111213141516171819202122"},
};
} // namespace