Files
media_cas_packager_sdk_source/common/ecb_util.cc
Fang Yu 9962e87676 Specify widevine/media_cas_packager_sdk/presubmit in media_cas_packager_sdk METADATA file.
-------------
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
2018-10-17 11:42:32 -07: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