Files
media_cas_proxy_sdk_source/common/ecb_util.cc
2018-12-11 10:51:52 -08:00

114 lines
3.8 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// Copyright 2016 Google LLC.
//
// 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.
////////////////////////////////////////////////////////////////////////////////
// Implementation of ecb crypto routines used by Widevine services.
#include "common/ecb_util.h"
#include "glog/logging.h"
#include "absl/strings/string_view.h"
#include "openssl/aes.h"
#include "openssl/des.h"
namespace widevine {
namespace crypto_util {
const int kWvmDESKeySizeBytes = 16;
static bool EncryptOrDecrypt3DesCbc(absl::string_view key,
absl::string_view src, std::string* dst,
bool encrypt) {
CHECK(dst);
if (key.size() != kWvmDESKeySizeBytes) {
LOG(WARNING) << "Invalid 3DES key size (" << key.size() << "!=16).";
dst->clear();
return false;
}
const int data_size = src.size();
if (data_size % DES_KEY_SZ != 0) {
// Data must be a multiple of block size
LOG(WARNING) << "3DES data is not a multiple of 8 bytes.";
dst->clear();
return false;
}
const int data_size_blocks = data_size / DES_KEY_SZ;
DES_key_schedule schedule[2];
// const_DES_cblock (the type of the first argument to DES_ecb3_encrypt) isn't
// actually const, so we have to cast away const.
DES_cblock* keyblock =
const_cast<DES_cblock*>(reinterpret_cast<const DES_cblock*>(key.data()));
DES_set_key(keyblock + 0, schedule + 1);
DES_set_key(keyblock + 1, schedule + 0);
DES_cblock* srcblock =
const_cast<DES_cblock*>(reinterpret_cast<const DES_cblock*>(src.data()));
dst->resize(data_size);
DES_cblock* dstblock = reinterpret_cast<DES_cblock*>(&*dst->begin());
for (int i = 0; i < data_size_blocks; i++) {
DES_ecb3_encrypt(srcblock + i, dstblock + i, schedule + 0, schedule + 1,
schedule + 0, encrypt);
}
return true;
}
bool Encrypt3DesEcb(absl::string_view key, absl::string_view src, std::string* dst) {
return EncryptOrDecrypt3DesCbc(key, src, dst, DES_ENCRYPT);
}
bool Decrypt3DesEcb(absl::string_view key, absl::string_view src, std::string* dst) {
return EncryptOrDecrypt3DesCbc(key, src, dst, DES_DECRYPT);
}
bool EncryptAesEcb(absl::string_view key, absl::string_view src, std::string* dst) {
CHECK(dst);
dst->clear();
if (src.size() % 16 != 0) {
LOG(WARNING) << "AES-ECB data is not a multiple of 16 bytes.";
return false;
}
int num_bits = key.size() * 8;
AES_KEY aes_key;
int aes_result = AES_set_encrypt_key(
reinterpret_cast<const uint8_t*>(key.data()), num_bits, &aes_key);
if (aes_result != 0) {
LOG(WARNING) << "AES result is not zero.";
return false;
}
dst->resize(src.size());
for (int i = 0; i < src.size(); i += AES_BLOCK_SIZE) {
AES_encrypt(reinterpret_cast<const uint8_t*>(src.data() + i),
reinterpret_cast<uint8_t*>(&(*dst)[i]), &aes_key);
}
return true;
}
bool DecryptAesEcb(absl::string_view key, absl::string_view src, std::string* dst) {
CHECK(dst);
dst->clear();
if (src.size() % 16 != 0) {
LOG(WARNING) << "AES-ECB data is not a multiple of 16 bytes.";
return false;
}
int num_bits = key.size() * 8;
AES_KEY aes_key;
int aes_result = AES_set_decrypt_key(
reinterpret_cast<const uint8_t*>(key.data()), num_bits, &aes_key);
if (aes_result != 0) {
LOG(WARNING) << "AES result is not zero.";
return false;
}
dst->resize(src.size());
for (int i = 0; i < src.size(); i += AES_BLOCK_SIZE) {
AES_decrypt(reinterpret_cast<const uint8_t*>(src.data() + i),
reinterpret_cast<uint8_t*>(&(*dst)[i]), &aes_key);
}
return true;
}
} // namespace crypto_util
} // namespace widevine