Files
provisioning_sdk_source/common/aes_cbc_util.cc
Kongqun Yang 8d17e4549a Export provisioning sdk
Change-Id: I4d47d80444c9507f84896767dc676112ca11e901
2017-01-24 20:06:25 -08:00

94 lines
3.4 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// Copyright 2016 Google Inc.
//
// This software is licensed under the terms defined in the Widevine Master
// License Agreement. For a copy of this agreement, please contact
// widevine-licensing@google.com.
////////////////////////////////////////////////////////////////////////////////
#include "common/aes_cbc_util.h"
#include <vector>
#include "glog/logging.h"
#include "openssl/aes.h"
namespace widevine {
namespace crypto_util {
// Encrypts the provided plantext std::string using AES-CBC encryption.
std::string EncryptAesCbc(const std::string& key, const std::string& iv,
const std::string& plaintext) {
if (iv.size() != AES_BLOCK_SIZE) return "";
const size_t num_padding_bytes =
AES_BLOCK_SIZE - (plaintext.size() % AES_BLOCK_SIZE);
std::string padded_text = plaintext;
padded_text.append(num_padding_bytes, static_cast<char>(num_padding_bytes));
AES_KEY aes_key;
if (AES_set_encrypt_key(reinterpret_cast<const uint8_t*>(&key[0]),
key.size() * 8, &aes_key) != 0) {
return "";
}
std::string encrypted(padded_text);
std::vector<uint8_t> local_iv(iv.begin(), iv.end());
AES_cbc_encrypt(reinterpret_cast<const uint8_t*>(padded_text.data()),
reinterpret_cast<uint8_t*>(&encrypted[0]), padded_text.size(),
&aes_key, &local_iv[0], AES_ENCRYPT);
return encrypted;
}
// Decrypts the AES-CBC encrypted text. Returns an empty std::string on error or
// the plaintext on success.
std::string DecryptAesCbc(const std::string& key, const std::string& iv,
const std::string& ciphertext) {
if (ciphertext.empty()) return "";
if (iv.size() != AES_BLOCK_SIZE) return "";
if ((ciphertext.size() % AES_BLOCK_SIZE) != 0) return "";
AES_KEY aes_key;
if (AES_set_decrypt_key(reinterpret_cast<const uint8_t*>(&key[0]),
key.size() * 8, &aes_key) != 0) {
return "";
}
std::string cleartext(ciphertext);
std::vector<uint8_t> local_iv(iv.begin(), iv.end());
AES_cbc_encrypt(reinterpret_cast<const uint8_t*>(ciphertext.data()),
reinterpret_cast<uint8_t*>(&cleartext[0]), ciphertext.size(),
&aes_key, &local_iv[0], AES_DECRYPT);
const uint8_t num_padding_bytes = cleartext[cleartext.size() - 1];
if (num_padding_bytes > AES_BLOCK_SIZE) return "";
for (uint8_t i = 0; i < num_padding_bytes; ++i) {
if (cleartext[cleartext.size() - 1 - i] != num_padding_bytes) return "";
}
cleartext.resize(cleartext.size() - num_padding_bytes);
return cleartext;
}
std::string DecryptAesCbcNoPad(const std::string& key, const std::string& iv,
const std::string& ciphertext) {
std::vector<uint8_t> local_iv(iv.begin(), iv.end());
if (local_iv.empty()) local_iv.resize(AES_BLOCK_SIZE, '\0');
else if (local_iv.size() != AES_BLOCK_SIZE) return "";
if ((ciphertext.size() % AES_BLOCK_SIZE) != 0) return "";
AES_KEY aes_key;
if (AES_set_decrypt_key(reinterpret_cast<const uint8_t*>(&key[0]),
key.size() * 8, &aes_key) != 0) {
return "";
}
std::string cleartext(ciphertext);
AES_cbc_encrypt(reinterpret_cast<const uint8_t*>(ciphertext.data()),
reinterpret_cast<uint8_t*>(&cleartext[0]), ciphertext.size(),
&aes_key, &local_iv[0], AES_DECRYPT);
return cleartext;
}
} // namespace crypto_util
} // namespace widevine