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;
22 namespace edash_packager {
26 bool chain_across_calls)
27 : padding_scheme_(padding_scheme),
28 chain_across_calls_(chain_across_calls) {
29 if (padding_scheme_ != kNoPadding) {
30 CHECK(!chain_across_calls) <<
"cipher block chain across calls only makes "
31 "sense if the padding_scheme is kNoPadding.";
35 AesCbcDecryptor::~AesCbcDecryptor() {}
38 const std::vector<uint8_t>& iv) {
39 if (!IsKeySizeValidForAes(key.size())) {
40 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
44 CHECK_EQ(AES_set_decrypt_key(key.data(), key.size() * 8, mutable_aes_key()),
50 if (iv.size() != AES_BLOCK_SIZE) {
51 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
59 bool AesCbcDecryptor::CryptInternal(
const uint8_t* ciphertext,
60 size_t ciphertext_size,
62 size_t* plaintext_size) {
63 DCHECK(plaintext_size);
68 if (*plaintext_size < ciphertext_size) {
69 LOG(ERROR) <<
"Expecting output size of at least " << ciphertext_size
73 *plaintext_size = ciphertext_size;
75 if (ciphertext_size == 0) {
76 if (padding_scheme_ == kPkcs5Padding) {
77 LOG(ERROR) <<
"Expected ciphertext to be at least " << AES_BLOCK_SIZE
78 <<
" bytes with Pkcs5 padding.";
85 std::vector<uint8_t> local_iv(
iv());
86 const size_t residual_block_size = ciphertext_size % AES_BLOCK_SIZE;
87 const size_t cbc_size = ciphertext_size - residual_block_size;
88 if (residual_block_size == 0) {
89 AES_cbc_encrypt(ciphertext, plaintext, ciphertext_size, aes_key(),
90 local_iv.data(), AES_DECRYPT);
91 if (chain_across_calls_)
93 if (padding_scheme_ != kPkcs5Padding)
97 const uint8_t num_padding_bytes = plaintext[ciphertext_size - 1];
98 if (num_padding_bytes > AES_BLOCK_SIZE) {
99 LOG(ERROR) <<
"Padding length is too large : "
100 <<
static_cast<int>(num_padding_bytes);
103 *plaintext_size -= num_padding_bytes;
105 }
else if (padding_scheme_ == kNoPadding) {
106 AES_cbc_encrypt(ciphertext, plaintext, cbc_size, aes_key(), local_iv.data(),
108 if (chain_across_calls_)
112 memcpy(plaintext + cbc_size, ciphertext + cbc_size, residual_block_size);
114 }
else if (padding_scheme_ != kCtsPadding) {
115 LOG(ERROR) <<
"Expecting cipher text size to be multiple of "
116 << AES_BLOCK_SIZE <<
", got " << ciphertext_size;
120 DCHECK(!chain_across_calls_);
121 DCHECK_EQ(padding_scheme_, kCtsPadding);
122 if (ciphertext_size < AES_BLOCK_SIZE) {
124 memcpy(plaintext, ciphertext, ciphertext_size);
129 if (cbc_size > AES_BLOCK_SIZE) {
130 AES_cbc_encrypt(ciphertext, plaintext, cbc_size - AES_BLOCK_SIZE, aes_key(),
131 local_iv.data(), AES_DECRYPT);
134 const uint8_t* next_to_last_ciphertext_block =
135 ciphertext + ciphertext_size - residual_block_size - AES_BLOCK_SIZE;
136 uint8_t* next_to_last_plaintext_block =
137 plaintext + ciphertext_size - residual_block_size - AES_BLOCK_SIZE;
141 std::vector<uint8_t> last_iv(
142 ciphertext + ciphertext_size - residual_block_size,
143 ciphertext + ciphertext_size);
144 last_iv.resize(AES_BLOCK_SIZE, 0);
148 AES_cbc_encrypt(next_to_last_ciphertext_block, next_to_last_plaintext_block,
149 AES_BLOCK_SIZE, aes_key(), last_iv.data(), AES_DECRYPT);
152 if (plaintext == ciphertext) {
153 std::swap_ranges(next_to_last_plaintext_block,
154 next_to_last_plaintext_block + residual_block_size,
155 next_to_last_plaintext_block + AES_BLOCK_SIZE);
157 memcpy(next_to_last_plaintext_block + AES_BLOCK_SIZE,
158 next_to_last_plaintext_block, residual_block_size);
159 memcpy(next_to_last_plaintext_block,
160 next_to_last_ciphertext_block + AES_BLOCK_SIZE, residual_block_size);
164 AES_cbc_encrypt(next_to_last_plaintext_block, next_to_last_plaintext_block,
165 AES_BLOCK_SIZE, aes_key(), local_iv.data(), AES_DECRYPT);