7 #include <packager/media/base/aes_cryptor.h>
12 #include <absl/log/check.h>
13 #include <absl/log/log.h>
14 #include <mbedtls/entropy.h>
16 #include <packager/macros/compiler.h>
17 #include <packager/macros/crypto.h>
23 bool IsIvSizeValid(
size_t iv_size) {
24 return iv_size == 8 || iv_size == 16;
33 : constant_iv_flag_(constant_iv_flag), num_crypt_bytes_(0) {
34 mbedtls_cipher_init(&cipher_ctx_);
37 AesCryptor::~AesCryptor() {
38 mbedtls_cipher_free(&cipher_ctx_);
41 bool AesCryptor::Crypt(
const std::vector<uint8_t>& text,
42 std::vector<uint8_t>* crypt_text) {
45 const size_t text_size = text.size();
46 crypt_text->resize(text_size + NumPaddingBytes(text_size));
47 size_t crypt_text_size = crypt_text->size();
48 if (!Crypt(text.data(), text_size, crypt_text->data(), &crypt_text_size)) {
51 DCHECK_LE(crypt_text_size, crypt_text->size());
52 crypt_text->resize(crypt_text_size);
56 bool AesCryptor::Crypt(
const std::string& text, std::string* crypt_text) {
59 const size_t text_size = text.size();
60 crypt_text->resize(text_size + NumPaddingBytes(text_size));
61 size_t crypt_text_size = crypt_text->size();
62 if (!Crypt(
reinterpret_cast<const uint8_t*
>(text.data()), text_size,
63 reinterpret_cast<uint8_t*
>(&(*crypt_text)[0]), &crypt_text_size))
65 DCHECK_LE(crypt_text_size, crypt_text->size());
66 crypt_text->resize(crypt_text_size);
71 if (!IsIvSizeValid(
iv.size())) {
72 LOG(ERROR) <<
"Invalid IV size: " <<
iv.size();
82 if (constant_iv_flag_ == kUseConstantIv)
85 uint64_t increment = 0;
94 if (iv_.size() == 8) {
97 DCHECK_EQ(16u, iv_.size());
98 increment = (num_crypt_bytes_ + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE;
101 for (int64_t i = iv_.size() - 1; increment > 0 && i >= 0; --i) {
103 iv_[i] = increment & 0xFF;
106 num_crypt_bytes_ = 0;
111 std::vector<uint8_t>* iv) {
116 const size_t iv_size =
117 (protection_scheme == FOURCC_cenc || protection_scheme == FOURCC_cens)
122 mbedtls_entropy_context entropy_ctx;
123 mbedtls_entropy_init(&entropy_ctx);
124 int rv = mbedtls_entropy_func(&entropy_ctx,
iv->data(), iv_size);
125 mbedtls_entropy_free(&entropy_ctx);
128 LOG(ERROR) <<
"mbedtls_entropy_func failed with: " << rv;
134 size_t AesCryptor::NumPaddingBytes(
size_t size)
const {
140 bool AesCryptor::SetupCipher(
size_t key_size, CipherMode mode) {
141 mbedtls_cipher_type_t type;
148 type = mode == kCtrMode ? MBEDTLS_CIPHER_AES_128_ECB
149 : MBEDTLS_CIPHER_AES_128_CBC;
152 type = mode == kCtrMode ? MBEDTLS_CIPHER_AES_192_ECB
153 : MBEDTLS_CIPHER_AES_192_CBC;
156 type = mode == kCtrMode ? MBEDTLS_CIPHER_AES_256_ECB
157 : MBEDTLS_CIPHER_AES_256_CBC;
160 LOG(ERROR) <<
"Invalid AES key size: " << key_size;
164 const mbedtls_cipher_info_t* cipher_info =
165 mbedtls_cipher_info_from_type(type);
168 if (mbedtls_cipher_setup(&cipher_ctx_, cipher_info) != 0) {
169 LOG(ERROR) <<
"Cipher setup failed";
174 if (mode == kCbcMode) {
176 mbedtls_cipher_padding_t cipher_padding = MBEDTLS_PADDING_NONE;
178 if (mbedtls_cipher_set_padding_mode(&cipher_ctx_, cipher_padding) != 0) {
179 LOG(ERROR) <<
"Failed to set CBC padding mode";
All the methods that are virtual are virtual for mocking.