7#include <packager/media/base/aes_cryptor.h>
14#include <absl/log/check.h>
15#include <absl/log/log.h>
16#include <mbedtls/cipher.h>
17#include <mbedtls/entropy.h>
19#include <packager/macros/compiler.h>
20#include <packager/macros/crypto.h>
21#include <packager/media/base/fourccs.h>
27bool IsIvSizeValid(
size_t iv_size) {
28 return iv_size == 8 || iv_size == 16;
37 : constant_iv_flag_(constant_iv_flag), num_crypt_bytes_(0) {
38 mbedtls_cipher_init(&cipher_ctx_);
41AesCryptor::~AesCryptor() {
42 mbedtls_cipher_free(&cipher_ctx_);
45bool AesCryptor::Crypt(
const std::vector<uint8_t>& text,
46 std::vector<uint8_t>* crypt_text) {
49 const size_t text_size = text.size();
50 crypt_text->resize(text_size + NumPaddingBytes(text_size));
51 size_t crypt_text_size = crypt_text->size();
52 if (!Crypt(text.data(), text_size, crypt_text->data(), &crypt_text_size)) {
55 DCHECK_LE(crypt_text_size, crypt_text->size());
56 crypt_text->resize(crypt_text_size);
60bool AesCryptor::Crypt(
const std::string& text, std::string* crypt_text) {
63 const size_t text_size = text.size();
64 crypt_text->resize(text_size + NumPaddingBytes(text_size));
65 size_t crypt_text_size = crypt_text->size();
66 if (!Crypt(
reinterpret_cast<const uint8_t*
>(text.data()), text_size,
67 reinterpret_cast<uint8_t*
>(&(*crypt_text)[0]), &crypt_text_size))
69 DCHECK_LE(crypt_text_size, crypt_text->size());
70 crypt_text->resize(crypt_text_size);
75 if (!IsIvSizeValid(
iv.size())) {
76 LOG(ERROR) <<
"Invalid IV size: " <<
iv.size();
86 if (constant_iv_flag_ == kUseConstantIv)
89 uint64_t increment = 0;
98 if (iv_.size() == 8) {
101 DCHECK_EQ(16u, iv_.size());
102 increment = (num_crypt_bytes_ + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE;
105 for (int64_t i = iv_.size() - 1; increment > 0 && i >= 0; --i) {
107 iv_[i] = increment & 0xFF;
110 num_crypt_bytes_ = 0;
115 std::vector<uint8_t>* iv) {
120 const size_t iv_size =
121 (protection_scheme == FOURCC_cenc || protection_scheme == FOURCC_cens)
126 mbedtls_entropy_context entropy_ctx;
127 mbedtls_entropy_init(&entropy_ctx);
128 int rv = mbedtls_entropy_func(&entropy_ctx,
iv->data(), iv_size);
129 mbedtls_entropy_free(&entropy_ctx);
132 LOG(ERROR) <<
"mbedtls_entropy_func failed with: " << rv;
138size_t AesCryptor::NumPaddingBytes(
size_t size)
const {
144bool AesCryptor::SetupCipher(
size_t key_size, CipherMode mode) {
145 mbedtls_cipher_type_t type;
152 type = mode == kCtrMode ? MBEDTLS_CIPHER_AES_128_ECB
153 : MBEDTLS_CIPHER_AES_128_CBC;
156 type = mode == kCtrMode ? MBEDTLS_CIPHER_AES_192_ECB
157 : MBEDTLS_CIPHER_AES_192_CBC;
160 type = mode == kCtrMode ? MBEDTLS_CIPHER_AES_256_ECB
161 : MBEDTLS_CIPHER_AES_256_CBC;
164 LOG(ERROR) <<
"Invalid AES key size: " << key_size;
168 const mbedtls_cipher_info_t* cipher_info =
169 mbedtls_cipher_info_from_type(type);
172 if (mbedtls_cipher_setup(&cipher_ctx_, cipher_info) != 0) {
173 LOG(ERROR) <<
"Cipher setup failed";
178 if (mode == kCbcMode) {
180 mbedtls_cipher_padding_t cipher_padding = MBEDTLS_PADDING_NONE;
182 if (mbedtls_cipher_set_padding_mode(&cipher_ctx_, cipher_padding) != 0) {
183 LOG(ERROR) <<
"Failed to set CBC padding mode";
All the methods that are virtual are virtual for mocking.