#include "media/cdm/aes_cbc_crypto.h"
#include "base/check_op.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "crypto/openssl_util.h"
#include "third_party/boringssl/src/include/openssl/aes.h"
#include "third_party/boringssl/src/include/openssl/err.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
namespace media {
AesCbcCrypto::AesCbcCrypto() = default;
AesCbcCrypto::~AesCbcCrypto() = default;
bool AesCbcCrypto::Initialize(base::span<const uint8_t> key,
base::span<const uint8_t> iv) {
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
const EVP_CIPHER* cipher = EVP_aes_128_cbc();
const uint8_t* key_data = reinterpret_cast<const uint8_t*>(key.data());
if (key.size() != EVP_CIPHER_key_length(cipher)) {
DVLOG(1) << "Key length is incorrect.";
return false;
}
if (iv.size_bytes() != EVP_CIPHER_iv_length(cipher)) {
DVLOG(1) << "IV length is incorrect.";
return false;
}
if (!EVP_DecryptInit_ex(ctx_.get(), cipher, nullptr, key_data, iv.data())) {
DVLOG(1) << "EVP_DecryptInit_ex() failed.";
return false;
}
if (!EVP_CIPHER_CTX_set_padding(ctx_.get(), 0)) {
DVLOG(1) << "EVP_CIPHER_CTX_set_padding() failed.";
return false;
}
return true;
}
bool AesCbcCrypto::Decrypt(base::span<const uint8_t> encrypted_data,
base::span<uint8_t> decrypted_data) {
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
CHECK_GE(decrypted_data.size(), encrypted_data.size());
if (encrypted_data.size_bytes() % EVP_CIPHER_CTX_block_size(ctx_.get()) !=
0) {
DVLOG(1) << "Encrypted bytes not a multiple of block size.";
return false;
}
size_t out_length;
if (!EVP_DecryptUpdate_ex(ctx_.get(), decrypted_data.data(), &out_length,
decrypted_data.size(), encrypted_data.data(),
encrypted_data.size_bytes())) {
DVLOG(1) << "EVP_DecryptUpdate() failed.";
return false;
}
return encrypted_data.size_bytes() == out_length;
}
}