7 #include "packager/media/base/aes_decryptor.h"
9 #include <openssl/aes.h>
10 #include <openssl/err.h>
11 #include <openssl/rand.h>
13 #include "packager/base/logging.h"
18 bool IsKeySizeValidForAes(
size_t key_size) {
19 return key_size == 16 || key_size == 24 || key_size == 32;
24 namespace edash_packager {
27 AesDecryptor::AesDecryptor() {}
28 AesDecryptor::~AesDecryptor() {}
30 bool AesDecryptor::Decrypt(
const std::vector<uint8_t>& ciphertext,
31 std::vector<uint8_t>* plaintext) {
33 plaintext->resize(ciphertext.size());
34 size_t plaintext_size;
35 if (!
DecryptInternal(ciphertext.data(), ciphertext.size(), plaintext->data(),
38 plaintext->resize(plaintext_size);
42 bool AesDecryptor::Decrypt(
const std::string& ciphertext,
43 std::string* plaintext) {
45 plaintext->resize(ciphertext.size());
46 size_t plaintext_size;
47 if (!
DecryptInternal(reinterpret_cast<const uint8_t*>(ciphertext.data()),
49 reinterpret_cast<uint8_t*
>(string_as_array(plaintext)),
52 plaintext->resize(plaintext_size);
56 AesCtrDecryptor::AesCtrDecryptor() {}
58 AesCtrDecryptor::~AesCtrDecryptor() {}
61 const std::vector<uint8_t>& iv) {
63 return encryptor_->InitializeWithIv(key, iv);
68 return encryptor_->SetIv(iv);
72 size_t ciphertext_size,
74 size_t* plaintext_size) {
76 *plaintext_size = ciphertext_size;
78 return encryptor_->Encrypt(ciphertext, ciphertext_size, plaintext);
82 bool chain_across_calls)
83 : padding_scheme_(padding_scheme),
84 chain_across_calls_(chain_across_calls) {
85 if (padding_scheme_ != kNoPadding) {
86 CHECK(!chain_across_calls) <<
"cipher block chain across calls only makes "
87 "sense if the padding_scheme is kNoPadding.";
90 AesCbcDecryptor::~AesCbcDecryptor() {}
93 const std::vector<uint8_t>& iv) {
94 if (!IsKeySizeValidForAes(key.size())) {
95 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
99 aes_key_.reset(
new AES_KEY());
100 CHECK_EQ(AES_set_decrypt_key(key.data(), key.size() * 8, aes_key_.get()), 0);
106 if (iv.size() != AES_BLOCK_SIZE) {
107 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
116 size_t ciphertext_size,
118 size_t* plaintext_size) {
119 DCHECK(plaintext_size);
123 *plaintext_size = ciphertext_size;
124 if (ciphertext_size == 0) {
125 if (padding_scheme_ == kPkcs5Padding) {
126 LOG(ERROR) <<
"Expected ciphertext to be at least " << AES_BLOCK_SIZE
127 <<
" bytes with Pkcs5 padding";
134 std::vector<uint8_t> local_iv(iv_);
135 const size_t residual_block_size = ciphertext_size % AES_BLOCK_SIZE;
136 if (residual_block_size == 0) {
137 AES_cbc_encrypt(ciphertext, plaintext, ciphertext_size, aes_key_.get(),
138 local_iv.data(), AES_DECRYPT);
139 if (chain_across_calls_)
141 if (padding_scheme_ != kPkcs5Padding)
145 const uint8_t num_padding_bytes = plaintext[ciphertext_size - 1];
146 if (num_padding_bytes > AES_BLOCK_SIZE) {
147 LOG(ERROR) <<
"Padding length is too large : "
148 <<
static_cast<int>(num_padding_bytes);
151 *plaintext_size -= num_padding_bytes;
153 }
else if (padding_scheme_ != kCtsPadding) {
154 LOG(ERROR) <<
"Expecting cipher text size to be multiple of "
155 << AES_BLOCK_SIZE <<
", got " << ciphertext_size;
159 DCHECK(!chain_across_calls_);
160 DCHECK_EQ(padding_scheme_, kCtsPadding);
161 if (ciphertext_size < AES_BLOCK_SIZE) {
163 memcpy(plaintext, ciphertext, ciphertext_size);
168 const size_t cbc_size = ciphertext_size - residual_block_size;
169 if (cbc_size > AES_BLOCK_SIZE) {
170 AES_cbc_encrypt(ciphertext, plaintext, cbc_size - AES_BLOCK_SIZE,
171 aes_key_.get(), local_iv.data(), AES_DECRYPT);
174 const uint8_t* next_to_last_ciphertext_block =
175 ciphertext + ciphertext_size - residual_block_size - AES_BLOCK_SIZE;
176 uint8_t* next_to_last_plaintext_block =
177 plaintext + ciphertext_size - residual_block_size - AES_BLOCK_SIZE;
181 std::vector<uint8_t> last_iv(
182 ciphertext + ciphertext_size - residual_block_size,
183 ciphertext + ciphertext_size);
184 last_iv.resize(AES_BLOCK_SIZE, 0);
188 AES_cbc_encrypt(next_to_last_ciphertext_block, next_to_last_plaintext_block,
189 AES_BLOCK_SIZE, aes_key_.get(), last_iv.data(), AES_DECRYPT);
192 if (plaintext == ciphertext) {
193 std::swap_ranges(next_to_last_plaintext_block,
194 next_to_last_plaintext_block + residual_block_size,
195 next_to_last_plaintext_block + AES_BLOCK_SIZE);
197 memcpy(next_to_last_plaintext_block + AES_BLOCK_SIZE,
198 next_to_last_plaintext_block, residual_block_size);
199 memcpy(next_to_last_plaintext_block,
200 next_to_last_ciphertext_block + AES_BLOCK_SIZE, residual_block_size);
204 AES_cbc_encrypt(next_to_last_plaintext_block, next_to_last_plaintext_block,
205 AES_BLOCK_SIZE, aes_key_.get(), local_iv.data(), AES_DECRYPT);