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 AesEncryptor::AesEncryptor() {}
44 AesEncryptor::~AesEncryptor() {}
47 const std::vector<uint8_t>& key,
49 std::vector<uint8_t> iv(iv_size, 0);
50 if (RAND_bytes(&iv[0], iv_size) != 1) {
51 LOG(ERROR) <<
"RAND_bytes failed with error: "
52 << ERR_error_string(ERR_get_error(), NULL);
58 bool AesEncryptor::Encrypt(
const std::vector<uint8_t>& plaintext,
59 std::vector<uint8_t>* ciphertext) {
60 if (plaintext.empty())
62 ciphertext->resize(plaintext.size() + NumPaddingBytes(plaintext.size()));
63 return EncryptData(plaintext.data(), plaintext.size(), ciphertext->data());
66 bool AesEncryptor::Encrypt(
const std::string& plaintext,
67 std::string* ciphertext) {
68 ciphertext->resize(plaintext.size() + NumPaddingBytes(plaintext.size()));
69 return EncryptData(reinterpret_cast<const uint8_t*>(plaintext.data()),
71 reinterpret_cast<uint8_t*
>(string_as_array(ciphertext)));
74 AesCtrEncryptor::AesCtrEncryptor()
76 encrypted_counter_(AES_BLOCK_SIZE, 0),
77 counter_overflow_(false) {
78 COMPILE_ASSERT(AES_BLOCK_SIZE == kCencKeySize,
79 cenc_key_size_should_be_the_same_as_aes_block_size);
82 AesCtrEncryptor::~AesCtrEncryptor() {}
85 const std::vector<uint8_t>& iv) {
86 if (key.size() != kCencKeySize) {
87 LOG(ERROR) <<
"Invalid key size of " << key.size() <<
" for CENC.";
90 if (!IsIvSizeValid(iv.size())) {
91 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
95 aes_key_.reset(
new AES_KEY());
96 CHECK_EQ(AES_set_encrypt_key(&key[0], AES_BLOCK_SIZE * 8, aes_key_.get()), 0);
100 size_t AesCtrEncryptor::NumPaddingBytes(
size_t size) {
104 bool AesCtrEncryptor::EncryptData(
const uint8_t* plaintext,
105 size_t plaintext_size,
106 uint8_t* ciphertext) {
111 for (
size_t i = 0; i < plaintext_size; ++i) {
112 if (block_offset_ == 0) {
113 AES_encrypt(&counter_[0], &encrypted_counter_[0], aes_key_.get());
119 if (Increment64(&counter_[8]))
120 counter_overflow_ =
true;
122 ciphertext[i] = plaintext[i] ^ encrypted_counter_[block_offset_];
123 block_offset_ = (block_offset_ + 1) % AES_BLOCK_SIZE;
137 if (iv_.size() == 8) {
138 Increment64(&iv_[0]);
140 counter_.resize(AES_BLOCK_SIZE, 0);
142 DCHECK_EQ(16u, iv_.size());
150 if (counter_overflow_)
151 Increment64(&counter_[0]);
154 counter_overflow_ =
false;
158 if (!IsIvSizeValid(iv.size())) {
159 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
165 counter_.resize(AES_BLOCK_SIZE, 0);
169 AesCbcPkcs5Encryptor::AesCbcPkcs5Encryptor() {}
170 AesCbcPkcs5Encryptor::~AesCbcPkcs5Encryptor() {}
173 const std::vector<uint8_t>& iv) {
174 if (!IsKeySizeValidForAes(key.size())) {
175 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
178 if (iv.size() != AES_BLOCK_SIZE) {
179 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
183 aes_key_.reset(
new AES_KEY());
184 CHECK_EQ(AES_set_encrypt_key(&key[0], key.size() * 8, aes_key_.get()), 0);
190 size_t AesCbcPkcs5Encryptor::NumPaddingBytes(
size_t size) {
191 return AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE);
194 bool AesCbcPkcs5Encryptor::EncryptData(
const uint8_t* plaintext,
195 size_t plaintext_size,
196 uint8_t* ciphertext) {
202 memcpy(ciphertext, plaintext, plaintext_size);
203 for (
size_t i = plaintext_size;
204 i < plaintext_size + NumPaddingBytes(plaintext_size); ++i) {
205 ciphertext[i] = NumPaddingBytes(plaintext_size);
208 std::vector<uint8_t> iv(iv_);
209 AES_cbc_encrypt(ciphertext, ciphertext,
210 plaintext_size + NumPaddingBytes(plaintext_size),
211 aes_key_.get(), &iv[0], AES_ENCRYPT);
218 if (iv.size() != AES_BLOCK_SIZE) {
219 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
227 AesCbcCtsEncryptor::AesCbcCtsEncryptor() {}
228 AesCbcCtsEncryptor::~AesCbcCtsEncryptor() {}
231 const std::vector<uint8_t>& iv) {
232 if (!IsKeySizeValidForAes(key.size())) {
233 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
236 if (iv.size() != AES_BLOCK_SIZE) {
237 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
241 aes_key_.reset(
new AES_KEY());
242 CHECK_EQ(AES_set_encrypt_key(&key[0], key.size() * 8, aes_key_.get()), 0);
248 size_t AesCbcCtsEncryptor::NumPaddingBytes(
size_t size) {
252 bool AesCbcCtsEncryptor::EncryptData(
const uint8_t* plaintext,
254 uint8_t* ciphertext) {
258 if (size < AES_BLOCK_SIZE) {
260 memcpy(ciphertext, plaintext, size);
264 std::vector<uint8_t> iv(iv_);
265 size_t residual_block_size = size % AES_BLOCK_SIZE;
266 size_t cbc_size = size - residual_block_size;
269 AES_cbc_encrypt(plaintext,
275 if (residual_block_size == 0) {
281 std::vector<uint8_t> residual_block(plaintext + size - residual_block_size,
283 residual_block.resize(AES_BLOCK_SIZE, 0);
284 AES_cbc_encrypt(&residual_block[0],
296 uint8_t* residual_ciphertext_block = ciphertext + size - residual_block_size;
297 memcpy(residual_ciphertext_block,
298 residual_ciphertext_block - AES_BLOCK_SIZE,
299 residual_block_size);
300 memcpy(residual_ciphertext_block - AES_BLOCK_SIZE,
301 residual_block.data(),
309 if (iv.size() != AES_BLOCK_SIZE) {
310 LOG(ERROR) <<
"Invalid IV size: " << iv.size();