------------- Moves ecm_generator to media_cas_packager_sdk/internal. ------------- Add a simple TCP server listening on a port. My intention is to use this server to support the Simulcrypt APIs (TODO). Also add a simple TCP client binary for testing the server and also demo how to call the Simulcrypt APIs (TODO). ------------- If only a single key is in the ECM, it is the EVEN key. To make the code matches this understanding, change a parameter from 'false' to 'true'. But this change has NO impact on the produced ECM, regardless this parameter is 'false' or 'true' (i.e., whether using push_front or push_back), only a single key is in the ECM. ------------- Add classes that process Simulcrypt ECMG messages 1) Stream_set-up 2) CW_provision ------------- Renames server and client binaries. ------------- Make ecmg call ecm_generator to generate ecm. The return of the ecm to Simulcrypt caller will be implemented in the next CL. For now, using the 'key' (control word) in CW_provision message also as the 'key_id'. ------------- Move common folder ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=217358698
114 lines
3.8 KiB
C++
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
|