Export media_cas_packager_sdk
This commit is contained in:
113
common/ecb_util.cc
Normal file
113
common/ecb_util.cc
Normal file
@@ -0,0 +1,113 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
Reference in New Issue
Block a user