7 #include "packager/media/base/aes_encryptor.h" 9 #include <openssl/aes.h> 11 #include "packager/base/logging.h" 16 bool Increment64(uint8_t* counter) {
18 for (
int i = 7; i >= 0; --i) {
19 if (++counter[i] != 0)
26 bool IsKeySizeValidForAes(
size_t key_size) {
27 return key_size == 16 || key_size == 24 || key_size == 32;
37 AesEncryptor::~AesEncryptor() {}
40 const std::vector<uint8_t>&
iv) {
41 if (!IsKeySizeValidForAes(key.size())) {
42 LOG(ERROR) <<
"Invalid AES key size: " << key.size();
46 CHECK_EQ(AES_set_encrypt_key(key.data(), key.size() * 8, mutable_aes_key()),
53 AesCtrEncryptor::AesCtrEncryptor()
56 encrypted_counter_(AES_BLOCK_SIZE, 0) {}
58 AesCtrEncryptor::~AesCtrEncryptor() {}
61 bool AesCtrEncryptor::CryptInternal(
const uint8_t* plaintext,
62 size_t plaintext_size,
64 size_t* ciphertext_size) {
70 if (*ciphertext_size < plaintext_size) {
71 LOG(ERROR) <<
"Expecting output size of at least " << plaintext_size
75 *ciphertext_size = plaintext_size;
77 for (
size_t i = 0; i < plaintext_size; ++i) {
78 if (block_offset_ == 0) {
79 AES_encrypt(&counter_[0], &encrypted_counter_[0], aes_key());
85 Increment64(&counter_[8]);
87 ciphertext[i] = plaintext[i] ^ encrypted_counter_[block_offset_];
88 block_offset_ = (block_offset_ + 1) % AES_BLOCK_SIZE;
93 void AesCtrEncryptor::SetIvInternal() {
96 counter_.resize(AES_BLOCK_SIZE, 0);
103 ConstantIvFlag constant_iv_flag)
104 :
AesEncryptor(constant_iv_flag), padding_scheme_(padding_scheme) {
105 if (padding_scheme_ != kNoPadding) {
106 CHECK_EQ(constant_iv_flag, kUseConstantIv)
107 <<
"non-constant iv (cipher block chain across calls) only makes sense " 108 "if the padding_scheme is kNoPadding.";
112 AesCbcEncryptor::~AesCbcEncryptor() {}
114 bool AesCbcEncryptor::CryptInternal(
const uint8_t* plaintext,
115 size_t plaintext_size,
117 size_t* ciphertext_size) {
120 const size_t residual_block_size = plaintext_size % AES_BLOCK_SIZE;
121 const size_t num_padding_bytes = NumPaddingBytes(plaintext_size);
122 const size_t required_ciphertext_size = plaintext_size + num_padding_bytes;
123 if (*ciphertext_size < required_ciphertext_size) {
124 LOG(ERROR) <<
"Expecting output size of at least " 125 << required_ciphertext_size <<
" bytes.";
128 *ciphertext_size = required_ciphertext_size;
131 const size_t cbc_size = plaintext_size - residual_block_size;
133 AES_cbc_encrypt(plaintext, ciphertext, cbc_size, aes_key(),
134 internal_iv_.data(), AES_ENCRYPT);
135 }
else if (padding_scheme_ == kCtsPadding) {
137 memcpy(ciphertext, plaintext, plaintext_size);
140 if (residual_block_size == 0 && padding_scheme_ != kPkcs5Padding) {
145 if (padding_scheme_ == kNoPadding) {
147 memcpy(ciphertext + cbc_size, plaintext + cbc_size, residual_block_size);
151 std::vector<uint8_t> residual_block(plaintext + cbc_size,
152 plaintext + plaintext_size);
153 DCHECK_EQ(residual_block.size(), residual_block_size);
154 uint8_t* residual_ciphertext_block = ciphertext + cbc_size;
156 if (padding_scheme_ == kPkcs5Padding) {
157 DCHECK_EQ(num_padding_bytes, AES_BLOCK_SIZE - residual_block_size);
160 residual_block.resize(AES_BLOCK_SIZE, static_cast<char>(num_padding_bytes));
161 AES_cbc_encrypt(residual_block.data(), residual_ciphertext_block,
162 AES_BLOCK_SIZE, aes_key(), internal_iv_.data(),
165 DCHECK_EQ(num_padding_bytes, 0u);
166 DCHECK_EQ(padding_scheme_, kCtsPadding);
169 residual_block.resize(AES_BLOCK_SIZE, 0);
170 AES_cbc_encrypt(residual_block.data(), residual_block.data(),
171 AES_BLOCK_SIZE, aes_key(), internal_iv_.data(),
179 memcpy(residual_ciphertext_block,
180 residual_ciphertext_block - AES_BLOCK_SIZE, residual_block_size);
181 memcpy(residual_ciphertext_block - AES_BLOCK_SIZE, residual_block.data(),
187 void AesCbcEncryptor::SetIvInternal() {
189 internal_iv_.resize(AES_BLOCK_SIZE, 0);
192 size_t AesCbcEncryptor::NumPaddingBytes(
size_t size)
const {
193 return (padding_scheme_ == kPkcs5Padding)
194 ? (AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE))
All the methods that are virtual are virtual for mocking.