7 #include "packager/media/base/aes_decryptor.h"
9 #include <openssl/aes.h>
11 #include "packager/base/logging.h"
16 bool IsKeySizeValidForAes(
size_t key_size) {
17 return key_size == 16 || key_size == 24 || key_size == 32;
29 ConstantIvFlag constant_iv_flag)
30 :
AesCryptor(constant_iv_flag), padding_scheme_(padding_scheme) {
31 if (padding_scheme_ != kNoPadding) {
32 CHECK_EQ(constant_iv_flag, kUseConstantIv)
33 <<
"non-constant iv (cipher block chain across calls) only makes sense "
34 "if the padding_scheme is kNoPadding.";
38 AesCbcDecryptor::~AesCbcDecryptor() {}
41 const std::vector<uint8_t>& iv) {
42 if (!IsKeySizeValidForAes(key.size())) {
43 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
47 CHECK_EQ(AES_set_decrypt_key(key.data(), key.size() * 8, mutable_aes_key()),
52 bool AesCbcDecryptor::CryptInternal(
const uint8_t* ciphertext,
53 size_t ciphertext_size,
55 size_t* plaintext_size) {
56 DCHECK(plaintext_size);
61 if (*plaintext_size < ciphertext_size) {
62 LOG(ERROR) <<
"Expecting output size of at least " << ciphertext_size
66 *plaintext_size = ciphertext_size;
68 if (ciphertext_size == 0) {
69 if (padding_scheme_ == kPkcs5Padding) {
70 LOG(ERROR) <<
"Expected ciphertext to be at least " << AES_BLOCK_SIZE
71 <<
" bytes with Pkcs5 padding.";
78 const size_t residual_block_size = ciphertext_size % AES_BLOCK_SIZE;
79 const size_t cbc_size = ciphertext_size - residual_block_size;
80 if (residual_block_size == 0) {
81 AES_cbc_encrypt(ciphertext, plaintext, ciphertext_size, aes_key(),
82 internal_iv_.data(), AES_DECRYPT);
83 if (padding_scheme_ != kPkcs5Padding)
87 const uint8_t num_padding_bytes = plaintext[ciphertext_size - 1];
88 if (num_padding_bytes > AES_BLOCK_SIZE) {
89 LOG(ERROR) <<
"Padding length is too large : "
90 <<
static_cast<int>(num_padding_bytes);
93 *plaintext_size -= num_padding_bytes;
95 }
else if (padding_scheme_ == kNoPadding) {
96 AES_cbc_encrypt(ciphertext, plaintext, cbc_size, aes_key(),
97 internal_iv_.data(), AES_DECRYPT);
100 memcpy(plaintext + cbc_size, ciphertext + cbc_size, residual_block_size);
102 }
else if (padding_scheme_ != kCtsPadding) {
103 LOG(ERROR) <<
"Expecting cipher text size to be multiple of "
104 << AES_BLOCK_SIZE <<
", got " << ciphertext_size;
108 DCHECK_EQ(padding_scheme_, kCtsPadding);
109 if (ciphertext_size < AES_BLOCK_SIZE) {
111 memcpy(plaintext, ciphertext, ciphertext_size);
116 if (cbc_size > AES_BLOCK_SIZE) {
117 AES_cbc_encrypt(ciphertext, plaintext, cbc_size - AES_BLOCK_SIZE, aes_key(),
118 internal_iv_.data(), AES_DECRYPT);
121 const uint8_t* next_to_last_ciphertext_block =
122 ciphertext + ciphertext_size - residual_block_size - AES_BLOCK_SIZE;
123 uint8_t* next_to_last_plaintext_block =
124 plaintext + ciphertext_size - residual_block_size - AES_BLOCK_SIZE;
128 std::vector<uint8_t> last_iv(
129 ciphertext + ciphertext_size - residual_block_size,
130 ciphertext + ciphertext_size);
131 last_iv.resize(AES_BLOCK_SIZE, 0);
135 AES_cbc_encrypt(next_to_last_ciphertext_block, next_to_last_plaintext_block,
136 AES_BLOCK_SIZE, aes_key(), last_iv.data(), AES_DECRYPT);
139 if (plaintext == ciphertext) {
140 std::swap_ranges(next_to_last_plaintext_block,
141 next_to_last_plaintext_block + residual_block_size,
142 next_to_last_plaintext_block + AES_BLOCK_SIZE);
144 memcpy(next_to_last_plaintext_block + AES_BLOCK_SIZE,
145 next_to_last_plaintext_block, residual_block_size);
146 memcpy(next_to_last_plaintext_block,
147 next_to_last_ciphertext_block + AES_BLOCK_SIZE, residual_block_size);
151 AES_cbc_encrypt(next_to_last_plaintext_block, next_to_last_plaintext_block,
152 AES_BLOCK_SIZE, aes_key(), internal_iv_.data(), AES_DECRYPT);
156 void AesCbcDecryptor::SetIvInternal() {
158 internal_iv_.resize(AES_BLOCK_SIZE, 0);
All the methods that are virtual are virtual for mocking.