7#include <packager/media/base/aes_decryptor.h>
15#include <absl/log/check.h>
16#include <absl/log/log.h>
17#include <mbedtls/cipher.h>
19#include <packager/macros/crypto.h>
20#include <packager/media/base/aes_cryptor.h>
21#include <packager/media/base/aes_encryptor.h>
30 ConstantIvFlag constant_iv_flag)
31 :
AesCryptor(constant_iv_flag), padding_scheme_(padding_scheme) {
32 if (padding_scheme_ != kNoPadding) {
33 CHECK_EQ(constant_iv_flag, kUseConstantIv)
34 <<
"non-constant iv (cipher block chain across calls) only makes sense "
35 "if the padding_scheme is kNoPadding.";
39AesCbcDecryptor::~AesCbcDecryptor() {}
42 const std::vector<uint8_t>& iv) {
43 if (!SetupCipher(key.size(), kCbcMode)) {
47 if (mbedtls_cipher_setkey(&cipher_ctx_, key.data(),
48 static_cast<int>(8 * key.size()),
49 MBEDTLS_DECRYPT) != 0) {
50 LOG(ERROR) <<
"Failed to set CBC decryption key";
57size_t AesCbcDecryptor::RequiredOutputSize(
size_t plaintext_size) {
58 return plaintext_size;
61bool AesCbcDecryptor::CryptInternal(
const uint8_t* ciphertext,
62 size_t ciphertext_size,
64 size_t* plaintext_size) {
65 DCHECK(plaintext_size);
69 if (*plaintext_size < ciphertext_size) {
70 LOG(ERROR) <<
"Expecting output size of at least " << ciphertext_size
74 *plaintext_size = ciphertext_size;
78 if (ciphertext_size == 0) {
79 if (padding_scheme_ == kPkcs5Padding) {
80 LOG(ERROR) <<
"Expected ciphertext to be at least " << AES_BLOCK_SIZE
81 <<
" bytes with Pkcs5 padding.";
88 const size_t residual_block_size = ciphertext_size % AES_BLOCK_SIZE;
89 const size_t cbc_size = ciphertext_size - residual_block_size;
90 if (residual_block_size == 0) {
91 CbcDecryptBlocks(ciphertext, ciphertext_size, plaintext,
93 if (padding_scheme_ != kPkcs5Padding)
97 const uint8_t num_padding_bytes = plaintext[ciphertext_size - 1];
98 if (num_padding_bytes > AES_BLOCK_SIZE) {
99 LOG(ERROR) <<
"Padding length is too large : "
100 <<
static_cast<int>(num_padding_bytes);
103 *plaintext_size -= num_padding_bytes;
105 }
else if (padding_scheme_ == kNoPadding) {
107 CbcDecryptBlocks(ciphertext, cbc_size, plaintext, internal_iv_.data());
110 memcpy(plaintext + cbc_size, ciphertext + cbc_size, residual_block_size);
112 }
else if (padding_scheme_ != kCtsPadding) {
113 LOG(ERROR) <<
"Expecting cipher text size to be multiple of "
114 << AES_BLOCK_SIZE <<
", got " << ciphertext_size;
118 DCHECK_EQ(padding_scheme_, kCtsPadding);
119 if (ciphertext_size < AES_BLOCK_SIZE) {
121 memcpy(plaintext, ciphertext, ciphertext_size);
126 if (cbc_size > AES_BLOCK_SIZE) {
127 CbcDecryptBlocks(ciphertext, cbc_size - AES_BLOCK_SIZE, plaintext,
128 internal_iv_.data());
131 const uint8_t* next_to_last_ciphertext_block =
132 ciphertext + ciphertext_size - residual_block_size - AES_BLOCK_SIZE;
133 uint8_t* next_to_last_plaintext_block =
134 plaintext + ciphertext_size - residual_block_size - AES_BLOCK_SIZE;
138 std::vector<uint8_t> last_iv(
139 ciphertext + ciphertext_size - residual_block_size,
140 ciphertext + ciphertext_size);
141 last_iv.resize(AES_BLOCK_SIZE, 0);
145 CbcDecryptBlocks(next_to_last_ciphertext_block, AES_BLOCK_SIZE,
146 next_to_last_plaintext_block, last_iv.data());
149 if (plaintext == ciphertext) {
150 std::swap_ranges(next_to_last_plaintext_block,
151 next_to_last_plaintext_block + residual_block_size,
152 next_to_last_plaintext_block + AES_BLOCK_SIZE);
154 memcpy(next_to_last_plaintext_block + AES_BLOCK_SIZE,
155 next_to_last_plaintext_block, residual_block_size);
156 memcpy(next_to_last_plaintext_block,
157 next_to_last_ciphertext_block + AES_BLOCK_SIZE, residual_block_size);
161 CbcDecryptBlocks(next_to_last_plaintext_block, AES_BLOCK_SIZE,
162 next_to_last_plaintext_block, internal_iv_.data());
166void AesCbcDecryptor::SetIvInternal() {
168 internal_iv_.resize(AES_BLOCK_SIZE, 0);
171void AesCbcDecryptor::CbcDecryptBlocks(
const uint8_t* ciphertext,
172 size_t ciphertext_size,
175 CHECK_EQ(ciphertext_size % AES_BLOCK_SIZE, 0u);
176 CHECK_GT(ciphertext_size, 0u);
180 const uint8_t* last_block = ciphertext + ciphertext_size - AES_BLOCK_SIZE;
181 std::vector<uint8_t> next_iv(last_block, last_block + AES_BLOCK_SIZE);
183 size_t output_size = 0;
184 CHECK_EQ(mbedtls_cipher_crypt(&cipher_ctx_,
iv, AES_BLOCK_SIZE, ciphertext,
185 ciphertext_size, plaintext, &output_size),
187 DCHECK_EQ(output_size % AES_BLOCK_SIZE, 0u);
189 memcpy(
iv, next_iv.data(), next_iv.size());
All the methods that are virtual are virtual for mocking.