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() {}
45 std::vector<uint8_t>
iv(iv_size, 0);
46 if (RAND_bytes(iv.data(), iv_size) != 1) {
47 LOG(ERROR) <<
"RAND_bytes failed with error: "
48 << ERR_error_string(ERR_get_error(), NULL);
55 const std::vector<uint8_t>& iv) {
56 if (!IsKeySizeValidForAes(key.size())) {
57 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
61 CHECK_EQ(AES_set_encrypt_key(key.data(), key.size() * 8, mutable_aes_key()),
66 AesCtrEncryptor::AesCtrEncryptor()
68 encrypted_counter_(AES_BLOCK_SIZE, 0),
69 counter_overflow_(false) {}
71 AesCtrEncryptor::~AesCtrEncryptor() {}
82 if (
iv().size() == 8) {
84 Increment64(&counter_[0]);
86 counter_.resize(AES_BLOCK_SIZE, 0);
88 DCHECK_EQ(16u,
iv().size());
96 if (counter_overflow_)
97 Increment64(&counter_[0]);
100 counter_overflow_ =
false;
104 if (!IsIvSizeValid(iv.size())) {
105 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
112 counter_.resize(AES_BLOCK_SIZE, 0);
116 bool AesCtrEncryptor::CryptInternal(
const uint8_t* plaintext,
117 size_t plaintext_size,
119 size_t* ciphertext_size) {
125 if (*ciphertext_size < plaintext_size) {
126 LOG(ERROR) <<
"Expecting output size of at least " << plaintext_size
130 *ciphertext_size = plaintext_size;
132 for (
size_t i = 0; i < plaintext_size; ++i) {
133 if (block_offset_ == 0) {
134 AES_encrypt(&counter_[0], &encrypted_counter_[0], aes_key());
140 if (Increment64(&counter_[8]))
141 counter_overflow_ =
true;
143 ciphertext[i] = plaintext[i] ^ encrypted_counter_[block_offset_];
144 block_offset_ = (block_offset_ + 1) % AES_BLOCK_SIZE;
150 bool chain_across_calls)
151 : padding_scheme_(padding_scheme),
152 chain_across_calls_(chain_across_calls) {
153 if (padding_scheme_ != kNoPadding) {
154 CHECK(!chain_across_calls) <<
"cipher block chain across calls only makes "
155 "sense if the padding_scheme is kNoPadding.";
158 AesCbcEncryptor::~AesCbcEncryptor() {}
171 if (iv.size() != AES_BLOCK_SIZE) {
172 LOG(ERROR) <<
"Invalid IV size: " << iv.size();
180 bool AesCbcEncryptor::CryptInternal(
const uint8_t* plaintext,
181 size_t plaintext_size,
183 size_t* ciphertext_size) {
186 const size_t residual_block_size = plaintext_size % AES_BLOCK_SIZE;
187 if (padding_scheme_ == kNoPadding && residual_block_size != 0) {
188 LOG(ERROR) <<
"Expecting input size to be multiple of " << AES_BLOCK_SIZE
189 <<
", got " << plaintext_size;
193 const size_t num_padding_bytes = NumPaddingBytes(plaintext_size);
194 const size_t required_ciphertext_size = plaintext_size + num_padding_bytes;
195 if (*ciphertext_size < required_ciphertext_size) {
196 LOG(ERROR) <<
"Expecting output size of at least "
197 << required_ciphertext_size <<
" bytes.";
200 *ciphertext_size = required_ciphertext_size;
203 const size_t cbc_size = plaintext_size - residual_block_size;
204 std::vector<uint8_t> local_iv(
iv());
206 AES_cbc_encrypt(plaintext, ciphertext, cbc_size, aes_key(), local_iv.data(),
208 }
else if (padding_scheme_ == kCtsPadding) {
210 memcpy(ciphertext, plaintext, plaintext_size);
213 if (residual_block_size == 0 && padding_scheme_ != kPkcs5Padding) {
214 if (chain_across_calls_)
219 DCHECK(!chain_across_calls_);
221 std::vector<uint8_t> residual_block(plaintext + cbc_size,
222 plaintext + plaintext_size);
223 DCHECK_EQ(residual_block.size(), residual_block_size);
224 uint8_t* residual_ciphertext_block = ciphertext + cbc_size;
226 if (padding_scheme_ == kPkcs5Padding) {
227 DCHECK_EQ(num_padding_bytes, AES_BLOCK_SIZE - residual_block_size);
230 residual_block.resize(AES_BLOCK_SIZE, static_cast<char>(num_padding_bytes));
231 AES_cbc_encrypt(residual_block.data(), residual_ciphertext_block,
232 AES_BLOCK_SIZE, aes_key(), local_iv.data(), AES_ENCRYPT);
234 DCHECK_EQ(num_padding_bytes, 0u);
235 DCHECK_EQ(padding_scheme_, kCtsPadding);
238 residual_block.resize(AES_BLOCK_SIZE, 0);
239 AES_cbc_encrypt(residual_block.data(), residual_block.data(),
240 AES_BLOCK_SIZE, aes_key(), local_iv.data(), AES_ENCRYPT);
247 memcpy(residual_ciphertext_block,
248 residual_ciphertext_block - AES_BLOCK_SIZE, residual_block_size);
249 memcpy(residual_ciphertext_block - AES_BLOCK_SIZE, residual_block.data(),
255 size_t AesCbcEncryptor::NumPaddingBytes(
size_t size)
const {
256 return (padding_scheme_ == kPkcs5Padding)
257 ? (AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE))