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;
37 namespace edash_packager {
40 AesEncryptor::AesEncryptor() {}
41 AesEncryptor::~AesEncryptor() {}
44 const std::vector<uint8_t>& key,
46 std::vector<uint8_t>
iv(iv_size, 0);
47 if (RAND_bytes(iv.data(), iv_size) != 1) {
48 LOG(ERROR) <<
"RAND_bytes failed with error: "
49 << ERR_error_string(ERR_get_error(), NULL);
56 const std::vector<uint8_t>& iv) {
57 if (!IsKeySizeValidForAes(key.size())) {
58 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
62 aes_key_.reset(
new AES_KEY());
63 CHECK_EQ(AES_set_encrypt_key(key.data(), key.size() * 8, aes_key_.get()), 0);
67 bool AesEncryptor::Encrypt(
const std::vector<uint8_t>& plaintext,
68 std::vector<uint8_t>* ciphertext) {
71 const size_t plaintext_size = plaintext.size();
73 return EncryptInternal(plaintext.data(), plaintext_size, ciphertext->data());
76 bool AesEncryptor::Encrypt(
const std::string& plaintext,
77 std::string* ciphertext) {
80 const size_t plaintext_size = plaintext.size();
83 reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext_size,
84 reinterpret_cast<uint8_t*>(string_as_array(ciphertext)));
87 AesCtrEncryptor::AesCtrEncryptor()
89 encrypted_counter_(AES_BLOCK_SIZE, 0),
90 counter_overflow_(false) {}
92 AesCtrEncryptor::~AesCtrEncryptor() {}
103 if (
iv().size() == 8) {
105 Increment64(&counter_[0]);
107 counter_.resize(AES_BLOCK_SIZE, 0);
109 DCHECK_EQ(16u,
iv().size());
117 if (counter_overflow_)
118 Increment64(&counter_[0]);
121 counter_overflow_ =
false;
125 if (!IsIvSizeValid(iv.size())) {
126 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
133 counter_.resize(AES_BLOCK_SIZE, 0);
138 size_t plaintext_size,
139 uint8_t* ciphertext) {
144 for (
size_t i = 0; i < plaintext_size; ++i) {
145 if (block_offset_ == 0) {
146 AES_encrypt(&counter_[0], &encrypted_counter_[0], aes_key());
152 if (Increment64(&counter_[8]))
153 counter_overflow_ =
true;
155 ciphertext[i] = plaintext[i] ^ encrypted_counter_[block_offset_];
156 block_offset_ = (block_offset_ + 1) % AES_BLOCK_SIZE;
167 bool chain_across_calls)
168 : padding_scheme_(padding_scheme),
169 chain_across_calls_(chain_across_calls) {
170 if (padding_scheme_ != kNoPadding) {
171 CHECK(!chain_across_calls) <<
"cipher block chain across calls only makes "
172 "sense if the padding_scheme is kNoPadding.";
175 AesCbcEncryptor::~AesCbcEncryptor() {}
188 if (iv.size() != AES_BLOCK_SIZE) {
189 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
198 size_t plaintext_size,
199 uint8_t* ciphertext) {
202 const size_t residual_block_size = plaintext_size % AES_BLOCK_SIZE;
203 if (padding_scheme_ == kNoPadding && residual_block_size != 0) {
204 LOG(ERROR) <<
"Expecting input size to be multiple of " << AES_BLOCK_SIZE
205 <<
", got " << plaintext_size;
210 const size_t cbc_size = plaintext_size - residual_block_size;
211 std::vector<uint8_t> local_iv(
iv());
213 AES_cbc_encrypt(plaintext, ciphertext, cbc_size, aes_key(), local_iv.data(),
215 }
else if (padding_scheme_ == kCtsPadding) {
217 memcpy(ciphertext, plaintext, plaintext_size);
220 if (residual_block_size == 0 && padding_scheme_ != kPkcs5Padding) {
221 if (chain_across_calls_)
226 DCHECK(!chain_across_calls_);
228 std::vector<uint8_t> residual_block(plaintext + cbc_size,
229 plaintext + plaintext_size);
230 DCHECK_EQ(residual_block.size(), residual_block_size);
231 uint8_t* residual_ciphertext_block = ciphertext + cbc_size;
233 if (padding_scheme_ == kPkcs5Padding) {
234 const size_t num_padding_bytes = AES_BLOCK_SIZE - residual_block_size;
237 residual_block.resize(AES_BLOCK_SIZE, static_cast<char>(num_padding_bytes));
238 AES_cbc_encrypt(residual_block.data(), residual_ciphertext_block,
239 AES_BLOCK_SIZE, aes_key(), local_iv.data(), AES_ENCRYPT);
241 DCHECK_EQ(padding_scheme_, kCtsPadding);
244 residual_block.resize(AES_BLOCK_SIZE, 0);
245 AES_cbc_encrypt(residual_block.data(), residual_block.data(),
246 AES_BLOCK_SIZE, aes_key(), local_iv.data(), AES_ENCRYPT);
253 memcpy(residual_ciphertext_block,
254 residual_ciphertext_block - AES_BLOCK_SIZE, residual_block_size);
255 memcpy(residual_ciphertext_block - AES_BLOCK_SIZE, residual_block.data(),
262 return (padding_scheme_ == kPkcs5Padding)
263 ? (AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE))