7 #include "packager/media/base/aes_encryptor.h"
9 #include <openssl/aes.h>
10 #include <openssl/err.h>
11 #include <openssl/rand.h>
13 #include "packager/base/logging.h"
18 bool Increment64(uint8_t* counter) {
20 for (
int i = 7; i >= 0; --i)
21 if (++counter[i] != 0)
28 bool IsIvSizeValid(
size_t iv_size) {
return iv_size == 8 || iv_size == 16; }
31 bool IsKeySizeValidForAes(
size_t key_size) {
32 return key_size == 16 || key_size == 24 || key_size == 32;
36 const uint32_t kCencKeySize = 16;
40 namespace edash_packager {
43 AesCtrEncryptor::AesCtrEncryptor()
45 encrypted_counter_(AES_BLOCK_SIZE, 0),
46 counter_overflow_(false) {
47 COMPILE_ASSERT(AES_BLOCK_SIZE == kCencKeySize,
48 cenc_key_size_should_be_the_same_as_aes_block_size);
51 AesCtrEncryptor::~AesCtrEncryptor() {}
53 bool AesCtrEncryptor::InitializeWithRandomIv(
const std::vector<uint8_t>& key,
55 std::vector<uint8_t> iv(iv_size, 0);
56 if (RAND_bytes(&iv[0], iv_size) != 1) {
57 LOG(ERROR) <<
"RAND_bytes failed with error: "
58 << ERR_error_string(ERR_get_error(), NULL);
61 return InitializeWithIv(key, iv);
64 bool AesCtrEncryptor::InitializeWithIv(
const std::vector<uint8_t>& key,
65 const std::vector<uint8_t>& iv) {
66 if (key.size() != kCencKeySize) {
67 LOG(ERROR) <<
"Invalid key size of " << key.size() <<
" for CENC.";
70 if (!IsIvSizeValid(iv.size())) {
71 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
75 aes_key_.reset(
new AES_KEY());
76 CHECK_EQ(AES_set_encrypt_key(&key[0], AES_BLOCK_SIZE * 8, aes_key_.get()), 0);
80 bool AesCtrEncryptor::Encrypt(
const uint8_t* plaintext,
81 size_t plaintext_size,
82 uint8_t* ciphertext) {
87 for (
size_t i = 0; i < plaintext_size; ++i) {
88 if (block_offset_ == 0) {
89 AES_encrypt(&counter_[0], &encrypted_counter_[0], aes_key_.get());
95 if (Increment64(&counter_[8]))
96 counter_overflow_ =
true;
98 ciphertext[i] = plaintext[i] ^ encrypted_counter_[block_offset_];
99 block_offset_ = (block_offset_ + 1) % AES_BLOCK_SIZE;
104 void AesCtrEncryptor::UpdateIv() {
113 if (iv_.size() == 8) {
114 Increment64(&iv_[0]);
116 counter_.resize(AES_BLOCK_SIZE, 0);
118 DCHECK_EQ(16u, iv_.size());
126 if (counter_overflow_)
127 Increment64(&counter_[0]);
130 counter_overflow_ =
false;
133 bool AesCtrEncryptor::SetIv(
const std::vector<uint8_t>& iv) {
134 if (!IsIvSizeValid(iv.size())) {
135 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
141 counter_.resize(AES_BLOCK_SIZE, 0);
145 AesCbcPkcs5Encryptor::AesCbcPkcs5Encryptor() {}
146 AesCbcPkcs5Encryptor::~AesCbcPkcs5Encryptor() {}
148 bool AesCbcPkcs5Encryptor::InitializeWithIv(
const std::vector<uint8_t>& key,
149 const std::vector<uint8_t>& iv) {
150 if (!IsKeySizeValidForAes(key.size())) {
151 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
154 if (iv.size() != AES_BLOCK_SIZE) {
155 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
159 encrypt_key_.reset(
new AES_KEY());
160 CHECK_EQ(AES_set_encrypt_key(&key[0], key.size() * 8, encrypt_key_.get()), 0);
166 void AesCbcPkcs5Encryptor::Encrypt(
const std::string& plaintext,
167 std::string* ciphertext) {
169 DCHECK(encrypt_key_);
172 const size_t num_padding_bytes =
173 AES_BLOCK_SIZE - (plaintext.size() % AES_BLOCK_SIZE);
174 std::string padded_text = plaintext;
175 padded_text.append(num_padding_bytes, static_cast<char>(num_padding_bytes));
177 ciphertext->resize(padded_text.size());
178 std::vector<uint8_t> iv(iv_);
179 AES_cbc_encrypt(reinterpret_cast<const uint8_t*>(padded_text.data()),
180 reinterpret_cast<uint8_t*>(string_as_array(ciphertext)),
187 bool AesCbcPkcs5Encryptor::SetIv(
const std::vector<uint8_t>& iv) {
188 if (iv.size() != AES_BLOCK_SIZE) {
189 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
197 AesCbcPkcs5Decryptor::AesCbcPkcs5Decryptor() {}
198 AesCbcPkcs5Decryptor::~AesCbcPkcs5Decryptor() {}
200 bool AesCbcPkcs5Decryptor::InitializeWithIv(
const std::vector<uint8_t>& key,
201 const std::vector<uint8_t>& iv) {
202 if (!IsKeySizeValidForAes(key.size())) {
203 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
206 if (iv.size() != AES_BLOCK_SIZE) {
207 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
211 decrypt_key_.reset(
new AES_KEY());
212 CHECK_EQ(AES_set_decrypt_key(&key[0], key.size() * 8, decrypt_key_.get()), 0);
218 bool AesCbcPkcs5Decryptor::Decrypt(
const std::string& ciphertext,
219 std::string* plaintext) {
220 if ((ciphertext.size() % AES_BLOCK_SIZE) != 0) {
221 LOG(ERROR) <<
"Expecting cipher text size to be multiple of "
222 << AES_BLOCK_SIZE <<
", got " << ciphertext.size();
227 DCHECK(decrypt_key_);
229 plaintext->resize(ciphertext.size());
230 AES_cbc_encrypt(reinterpret_cast<const uint8_t*>(ciphertext.data()),
231 reinterpret_cast<uint8_t*>(string_as_array(plaintext)),
238 const uint8_t num_padding_bytes = (*plaintext)[plaintext->size() - 1];
239 if (num_padding_bytes > AES_BLOCK_SIZE) {
240 LOG(ERROR) <<
"Padding length is too large : "
241 <<
static_cast<int>(num_padding_bytes);
244 plaintext->resize(plaintext->size() - num_padding_bytes);
248 bool AesCbcPkcs5Decryptor::SetIv(
const std::vector<uint8_t>& iv) {
249 if (iv.size() != AES_BLOCK_SIZE) {
250 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
258 AesCbcCtsEncryptor::AesCbcCtsEncryptor() {}
259 AesCbcCtsEncryptor::~AesCbcCtsEncryptor() {}
261 bool AesCbcCtsEncryptor::InitializeWithIv(
const std::vector<uint8_t>& key,
262 const std::vector<uint8_t>& iv) {
263 if (!IsKeySizeValidForAes(key.size())) {
264 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
267 if (iv.size() != AES_BLOCK_SIZE) {
268 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
272 encrypt_key_.reset(
new AES_KEY());
273 CHECK_EQ(AES_set_encrypt_key(&key[0], key.size() * 8, encrypt_key_.get()), 0);
279 void AesCbcCtsEncryptor::Encrypt(
const uint8_t* plaintext,
281 uint8_t* ciphertext) {
285 if (size < AES_BLOCK_SIZE) {
287 memcpy(ciphertext, plaintext, size);
291 std::vector<uint8_t> iv(iv_);
292 size_t residual_block_size = size % AES_BLOCK_SIZE;
293 size_t cbc_size = size - residual_block_size;
296 AES_cbc_encrypt(plaintext,
302 if (residual_block_size == 0) {
308 std::vector<uint8_t> residual_block(plaintext + size - residual_block_size,
310 residual_block.resize(AES_BLOCK_SIZE, 0);
311 AES_cbc_encrypt(&residual_block[0],
323 uint8_t* residual_ciphertext_block = ciphertext + size - residual_block_size;
324 memcpy(residual_ciphertext_block,
325 residual_ciphertext_block - AES_BLOCK_SIZE,
326 residual_block_size);
327 memcpy(residual_ciphertext_block - AES_BLOCK_SIZE,
328 residual_block.data(),
332 void AesCbcCtsEncryptor::Encrypt(
const std::vector<uint8_t>& plaintext,
333 std::vector<uint8_t>* ciphertext) {
336 ciphertext->resize(plaintext.size(), 0);
337 if (plaintext.empty())
340 Encrypt(plaintext.data(), plaintext.size(), &(*ciphertext)[0]);
343 bool AesCbcCtsEncryptor::SetIv(
const std::vector<uint8_t>& iv) {
344 if (iv.size() != AES_BLOCK_SIZE) {
345 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
353 AesCbcCtsDecryptor::AesCbcCtsDecryptor() {}
354 AesCbcCtsDecryptor::~AesCbcCtsDecryptor() {}
356 bool AesCbcCtsDecryptor::InitializeWithIv(
const std::vector<uint8_t>& key,
357 const std::vector<uint8_t>& iv) {
358 if (!IsKeySizeValidForAes(key.size())) {
359 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
362 if (iv.size() != AES_BLOCK_SIZE) {
363 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
367 decrypt_key_.reset(
new AES_KEY());
368 CHECK_EQ(AES_set_decrypt_key(&key[0], key.size() * 8, decrypt_key_.get()), 0);
374 void AesCbcCtsDecryptor::Decrypt(
const uint8_t* ciphertext,
376 uint8_t* plaintext) {
380 if (size < AES_BLOCK_SIZE) {
382 memcpy(plaintext, ciphertext, size);
386 std::vector<uint8_t> iv(iv_);
387 size_t residual_block_size = size % AES_BLOCK_SIZE;
389 if (residual_block_size == 0) {
391 AES_cbc_encrypt(ciphertext,
401 size_t cbc_size = size - residual_block_size;
402 if (cbc_size > AES_BLOCK_SIZE) {
403 AES_cbc_encrypt(ciphertext,
405 cbc_size - AES_BLOCK_SIZE,
413 std::vector<uint8_t> last_iv(ciphertext + size - residual_block_size,
415 last_iv.resize(AES_BLOCK_SIZE, 0);
419 AES_cbc_encrypt(ciphertext + size - residual_block_size - AES_BLOCK_SIZE,
420 plaintext + size - residual_block_size - AES_BLOCK_SIZE,
427 if (plaintext == ciphertext) {
428 uint8_t* ptr1 = plaintext + size - residual_block_size;
429 uint8_t* ptr2 = plaintext + size - residual_block_size - AES_BLOCK_SIZE;
430 for (
size_t i = 0; i < residual_block_size; ++i) {
431 uint8_t temp = *ptr1;
438 uint8_t* residual_plaintext_block = plaintext + size - residual_block_size;
439 memcpy(residual_plaintext_block,
440 residual_plaintext_block - AES_BLOCK_SIZE,
441 residual_block_size);
442 memcpy(residual_plaintext_block - AES_BLOCK_SIZE,
443 ciphertext + size - residual_block_size,
444 residual_block_size);
448 AES_cbc_encrypt(plaintext + size - residual_block_size - AES_BLOCK_SIZE,
449 plaintext + size - residual_block_size - AES_BLOCK_SIZE,
456 void AesCbcCtsDecryptor::Decrypt(
const std::vector<uint8_t>& ciphertext,
457 std::vector<uint8_t>* plaintext) {
460 plaintext->resize(ciphertext.size(), 0);
461 if (ciphertext.empty())
464 Decrypt(ciphertext.data(), ciphertext.size(), &(*plaintext)[0]);
467 bool AesCbcCtsDecryptor::SetIv(
const std::vector<uint8_t>& iv) {
468 if (iv.size() != AES_BLOCK_SIZE) {
469 LOG(ERROR) <<
"Invalid IV size: " << iv.size();