|
|
|
|
@@ -0,0 +1,414 @@
|
|
|
|
|
// Copyright 2017 Google Inc. All Rights Reserved.
|
|
|
|
|
//
|
|
|
|
|
// Mock implementation of OEMCrypto APIs
|
|
|
|
|
//
|
|
|
|
|
// This file contains oemcrypto engine properties that reads data from a file
|
|
|
|
|
// to decide what it's current status is. It is used for testing cdm code.
|
|
|
|
|
// The following properties are read from the file:
|
|
|
|
|
// log_level: logging level to use.
|
|
|
|
|
// 0 = LOG_ERROR,
|
|
|
|
|
// 1 = LOG_WARN,
|
|
|
|
|
// 2 = LOG_INFO,
|
|
|
|
|
// 3 = LOG_DEBUG,
|
|
|
|
|
// 4 = LOG_VERBOSE
|
|
|
|
|
// kLogging*: All logging flags found in oemcrypto/include/oemcrypto_logging.h
|
|
|
|
|
// can be turned on (1) or off (0).
|
|
|
|
|
// security_level: returned by OEMCrypto_SecurityLevel.
|
|
|
|
|
// secure_lib: If set, then this will be used as a path to
|
|
|
|
|
// the L1 liboemcrypto.so that we can use secure buffers.
|
|
|
|
|
// current_hdcp: returned by OEMCrypto_GetHDCPCapability and
|
|
|
|
|
// used to verify the key control block in methods like DecryptCENC.
|
|
|
|
|
// HDCP_NONE = 0, // No HDCP supported, no secure data path.
|
|
|
|
|
// HDCP_V1 = 1, // HDCP version 1.0
|
|
|
|
|
// HDCP_V2 = 2, // HDCP version 2.0 Type 1.
|
|
|
|
|
// HDCP_V2_1 = 3, // HDCP version 2.1 Type 1.
|
|
|
|
|
// HDCP_V2_2 = 4, // HDCP version 2.2 Type 1.
|
|
|
|
|
// HDCP_NO_DIGITAL_OUTPUT = 0xff // No digital output.
|
|
|
|
|
// max_hdcp: returned by OEMCrypto_GetHDCPCapability. Same values as above.
|
|
|
|
|
// srm_update_supported: If "1", then srm update is supported.
|
|
|
|
|
// srm_initial_version: Initial value for srm version.
|
|
|
|
|
// This will be ignored after a reset. If this is not set, CurrentSRM will
|
|
|
|
|
// return NOT_IMPLEMENTED.
|
|
|
|
|
// srm_load_fail: If set to a nonzero number, then load_srm will
|
|
|
|
|
// fail and the version will not be updated. The number is converted to
|
|
|
|
|
// an OEMCryptoResult and returned.
|
|
|
|
|
// srm_load_version: If this is set, then it will be used as the
|
|
|
|
|
// new srm version after loading an SRM -- ignoring the contents of the SRM.
|
|
|
|
|
// srm_blacklisted_device_attached: If set to "1", then a
|
|
|
|
|
// oemcrypto will act as if a blacklisted device is attached.
|
|
|
|
|
// security_patch_level: This is the value returned by
|
|
|
|
|
// OEMCrypto_Security_Patch_Level. If the key control block requires a
|
|
|
|
|
// higher level, then OEMCrypto_LoadKeys will fail.
|
|
|
|
|
// max_buffer_size: maximum size of a buffer accepted by DecryptCENC and
|
|
|
|
|
// friends. If this is 0, there is no restriction. If it is 1, the
|
|
|
|
|
// minimum allowed value is used.
|
|
|
|
|
// use_keybox: If this is 1, then the test keybox is used. If this is zero,
|
|
|
|
|
// then the test OEM certificate is used.
|
|
|
|
|
// use_fallback: If this is nonzero, then the installed Level 1 library will
|
|
|
|
|
// be used to play content to a secure buffer. Decryption and key
|
|
|
|
|
// verification are done by the mock, but then the data is copied to the
|
|
|
|
|
// secure buffer using OEMCrypto_CopyBuffer. The filename of the fallback
|
|
|
|
|
// library is hardcoded to "level1_backup_liboemcrypto.so". It is
|
|
|
|
|
// recommended you use the install script to ensure you have the right
|
|
|
|
|
// filename.
|
|
|
|
|
//
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
|
|
#include "log.h"
|
|
|
|
|
#include "oem_cert.h"
|
|
|
|
|
#include "oemcrypto_engine_mock.h"
|
|
|
|
|
#include "oemcrypto_logging.h"
|
|
|
|
|
#include "properties.h"
|
|
|
|
|
|
|
|
|
|
namespace wvoec_mock {
|
|
|
|
|
namespace {
|
|
|
|
|
typedef OEMCryptoResult (*L1_Initialize_t)(void);
|
|
|
|
|
typedef OEMCryptoResult (*L1_Terminate_t)(void);
|
|
|
|
|
typedef OEMCryptoResult (*L1_CopyBuffer_t)(const uint8_t* data_addr,
|
|
|
|
|
size_t data_length,
|
|
|
|
|
OEMCrypto_DestBufferDesc* out_buffer,
|
|
|
|
|
uint8_t subsample_flags);
|
|
|
|
|
const std::string kDefaultOptionsFile = "/data/mediadrm/oemcrypto/options.txt";
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
class AndroidModifiableCryptoEngine : public CryptoEngine {
|
|
|
|
|
public:
|
|
|
|
|
AndroidModifiableCryptoEngine(wvcdm::FileSystem *file_system)
|
|
|
|
|
: CryptoEngine(file_system),
|
|
|
|
|
options_file_(kDefaultOptionsFile),
|
|
|
|
|
srm_loaded_(false),
|
|
|
|
|
srm_version_(0),
|
|
|
|
|
level1_valid_(false),
|
|
|
|
|
level1_library_(NULL) {
|
|
|
|
|
std::string path;
|
|
|
|
|
if (wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
|
|
|
|
|
&path)) {
|
|
|
|
|
options_file_ = path + "options.txt";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MaybeReadOptionsFile() {
|
|
|
|
|
static time_t last_check = 0;
|
|
|
|
|
static time_t last_changed = 0;
|
|
|
|
|
time_t now = time(NULL);
|
|
|
|
|
if (now > last_check + 5) { // Check every five seconds.
|
|
|
|
|
last_check = now;
|
|
|
|
|
struct stat file_stat;
|
|
|
|
|
if (stat(options_file_.c_str(), &file_stat)) {
|
|
|
|
|
LOGE("Could not stat %s: %s", options_file_.c_str(), strerror(errno));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (file_stat.st_mtime > last_changed) {
|
|
|
|
|
last_changed = file_stat.st_mtime;
|
|
|
|
|
ReadOptionsFile();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ReadOptionsFile() {
|
|
|
|
|
FILE *file = fopen(options_file_.c_str(), "r");
|
|
|
|
|
if (!file) {
|
|
|
|
|
LOGE("Could not read %s %s", options_file_.c_str(), strerror(errno));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
while (!feof(file)) {
|
|
|
|
|
char name[80 + 1];
|
|
|
|
|
int value;
|
|
|
|
|
if (fscanf(file, "%80s %d", name, &value)) {
|
|
|
|
|
LOGV("Option %s = %d", name, value);
|
|
|
|
|
options_[std::string(name)] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fclose(file);
|
|
|
|
|
InitializeLogging();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int GetOption(const std::string &key, int default_value) {
|
|
|
|
|
MaybeReadOptionsFile();
|
|
|
|
|
if (options_.find(key) == options_.end() ) {
|
|
|
|
|
LOGV("Option %s not set. Using default %d", key.c_str(), default_value);
|
|
|
|
|
return default_value;
|
|
|
|
|
}
|
|
|
|
|
return options_[key];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InitializeLogging() {
|
|
|
|
|
int log_level = GetOption("log_level", 3);
|
|
|
|
|
int categories = 0;
|
|
|
|
|
if (GetOption("kLoggingTraceOEMCryptoCalls", 0) > 0)
|
|
|
|
|
categories |= kLoggingTraceOEMCryptoCalls;
|
|
|
|
|
if (GetOption("kLoggingDumpContentKeys", 0) > 0)
|
|
|
|
|
categories |= kLoggingDumpContentKeys;
|
|
|
|
|
if (GetOption("kLoggingDumpKeyControlBlocks", 0) > 0)
|
|
|
|
|
categories |= kLoggingDumpKeyControlBlocks;
|
|
|
|
|
if (GetOption("kLoggingDumpDerivedKeys", 0) > 0)
|
|
|
|
|
categories |= kLoggingDumpDerivedKeys;
|
|
|
|
|
if (GetOption("kLoggingTraceNonce", 0) > 0)
|
|
|
|
|
categories |= kLoggingTraceNonce;
|
|
|
|
|
if (GetOption("kLoggingTraceDecryption", 0) > 0)
|
|
|
|
|
categories |= kLoggingTraceDecryption;
|
|
|
|
|
if (GetOption("kLoggingTraceUsageTable", 0) > 0)
|
|
|
|
|
categories |= kLoggingTraceUsageTable;
|
|
|
|
|
if (GetOption("kLoggingTraceDecryptCalls", 0) > 0)
|
|
|
|
|
categories |= kLoggingTraceDecryptCalls;
|
|
|
|
|
if (GetOption("kLoggingDumpTraceAll", 0) > 0)
|
|
|
|
|
categories |= kLoggingDumpTraceAll;
|
|
|
|
|
SetLoggingSettings(log_level, categories);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define QUOTE_DEFINE(A) #A
|
|
|
|
|
#define QUOTE(A) QUOTE_DEFINE(A)
|
|
|
|
|
#define LOOKUP(Name, Function) \
|
|
|
|
|
Name = (L1_##Name##t)dlsym(level1_library_, QUOTE(Function)); \
|
|
|
|
|
if (!Name) { \
|
|
|
|
|
LOGW("Could not load L1 %s.", \
|
|
|
|
|
QUOTE(Function)); \
|
|
|
|
|
Terminate(); \
|
|
|
|
|
return false; \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual bool Initialize() {
|
|
|
|
|
LOGD("OEMCrypto Mock With Options " " " __DATE__ " " __TIME__);
|
|
|
|
|
MaybeReadOptionsFile();
|
|
|
|
|
if (!GetOption("use_fallback", 1)) {
|
|
|
|
|
LOGD("Level 1 fallback ignored.");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
level1_library_ = dlopen("level1_backup_liboemcrypto.so", RTLD_NOW);
|
|
|
|
|
if (level1_library_ == NULL) {
|
|
|
|
|
LOGE("Could not load backup: %s", dlerror());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
LOOKUP(Initialize_, OEMCrypto_Initialize);
|
|
|
|
|
LOOKUP(Terminate_, OEMCrypto_Terminate);
|
|
|
|
|
LOOKUP(CopyBuffer_, OEMCrypto_CopyBuffer);
|
|
|
|
|
level1_valid_ = true;
|
|
|
|
|
OEMCryptoResult sts = Initialize_();
|
|
|
|
|
LOGD("L1 fall back initialized. status = %d.", sts);
|
|
|
|
|
if (sts != OEMCrypto_SUCCESS) {
|
|
|
|
|
LOGW("Terminating L1 because init failed.");
|
|
|
|
|
Terminate();
|
|
|
|
|
LOGW("Continuing Mock without L1 fallback.");
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void Terminate() {
|
|
|
|
|
if (level1_valid_) Terminate_();
|
|
|
|
|
if (level1_library_ != NULL) {
|
|
|
|
|
LOGD("Closing L1 fall back.\n");
|
|
|
|
|
dlclose(level1_library_);
|
|
|
|
|
level1_valid_ = false;
|
|
|
|
|
level1_library_ = NULL;
|
|
|
|
|
CopyBuffer_ = NULL;
|
|
|
|
|
Initialize_ = NULL;
|
|
|
|
|
Terminate_ = NULL;
|
|
|
|
|
} else {
|
|
|
|
|
LOGD("Terminate mock.\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *HDCPCapabilityAsString(OEMCrypto_HDCP_Capability value) {
|
|
|
|
|
switch (value) {
|
|
|
|
|
case HDCP_NONE:
|
|
|
|
|
return "No HDCP supported, no secure data path";
|
|
|
|
|
case HDCP_V1:
|
|
|
|
|
return "HDCP version 1.0";
|
|
|
|
|
case HDCP_V2:
|
|
|
|
|
return "HDCP version 2.0";
|
|
|
|
|
case HDCP_V2_1:
|
|
|
|
|
return "HDCP version 2.1";
|
|
|
|
|
case HDCP_V2_2:
|
|
|
|
|
return "HDCP version 2.2";
|
|
|
|
|
case HDCP_NO_DIGITAL_OUTPUT:
|
|
|
|
|
return "No HDCP device attached/using local display with secure path";
|
|
|
|
|
default:
|
|
|
|
|
return "<INVALID VALUE>";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OEMCrypto_ProvisioningMethod config_provisioning_method() {
|
|
|
|
|
if (GetOption("use_keybox", 1)) {
|
|
|
|
|
return OEMCrypto_Keybox;
|
|
|
|
|
} else {
|
|
|
|
|
return OEMCrypto_OEMCertificate;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OEMCryptoResult get_oem_certificate(SessionContext* session,
|
|
|
|
|
uint8_t* public_cert,
|
|
|
|
|
size_t* public_cert_length) {
|
|
|
|
|
if (GetOption("use_keybox", 1)) {
|
|
|
|
|
LOGD("OEM Cert asked for when use_keybox = 1.");
|
|
|
|
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
if (kOEMPublicCertSize == 0) {
|
|
|
|
|
LOGD("OEM Cert Size is 0.");
|
|
|
|
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
if (public_cert_length == NULL) {
|
|
|
|
|
LOGD("OEM Cert length is 0.");
|
|
|
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
if (*public_cert_length < kOEMPublicCertSize) {
|
|
|
|
|
*public_cert_length = kOEMPublicCertSize;
|
|
|
|
|
return OEMCrypto_ERROR_SHORT_BUFFER;
|
|
|
|
|
}
|
|
|
|
|
*public_cert_length = kOEMPublicCertSize;
|
|
|
|
|
if (public_cert == NULL) {
|
|
|
|
|
return OEMCrypto_ERROR_SHORT_BUFFER;
|
|
|
|
|
}
|
|
|
|
|
memcpy(public_cert, kOEMPublicCert, kOEMPublicCertSize);
|
|
|
|
|
if (!session->LoadRSAKey(kOEMPrivateKey, kOEMPrivateKeySize)) {
|
|
|
|
|
LOGE("Private RSA Key did not load correctly.");
|
|
|
|
|
return OEMCrypto_ERROR_INVALID_RSA_KEY;
|
|
|
|
|
}
|
|
|
|
|
return OEMCrypto_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns "L3" for a software only library. L1 is for hardware protected
|
|
|
|
|
// data paths.
|
|
|
|
|
const char *config_security_level() {
|
|
|
|
|
switch (GetOption("security_level", 0)) {
|
|
|
|
|
default:
|
|
|
|
|
LOGW("Option security_level not set. Default is L3.");
|
|
|
|
|
case 3:
|
|
|
|
|
return "L3";
|
|
|
|
|
case 2:
|
|
|
|
|
return "L2";
|
|
|
|
|
case 1:
|
|
|
|
|
return "L1";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns the HDCP version currently in use.
|
|
|
|
|
OEMCrypto_HDCP_Capability config_current_hdcp_capability() {
|
|
|
|
|
static OEMCrypto_HDCP_Capability current_hdcp = HDCP_NONE;
|
|
|
|
|
OEMCrypto_HDCP_Capability new_current_hdcp =
|
|
|
|
|
static_cast<OEMCrypto_HDCP_Capability>(GetOption("current_hdcp", 0));
|
|
|
|
|
if (current_hdcp != new_current_hdcp) {
|
|
|
|
|
LOGI("OEMCrypto current HDCP changed from %d (%s) to %d (%s)", current_hdcp,
|
|
|
|
|
HDCPCapabilityAsString(current_hdcp), new_current_hdcp,
|
|
|
|
|
HDCPCapabilityAsString(new_current_hdcp));
|
|
|
|
|
current_hdcp = new_current_hdcp;
|
|
|
|
|
}
|
|
|
|
|
return current_hdcp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns the max HDCP version supported.
|
|
|
|
|
OEMCrypto_HDCP_Capability config_maximum_hdcp_capability() {
|
|
|
|
|
static OEMCrypto_HDCP_Capability max_hdcp = HDCP_NONE;
|
|
|
|
|
MaybeReadOptionsFile();
|
|
|
|
|
OEMCrypto_HDCP_Capability new_max_hdcp =
|
|
|
|
|
static_cast<OEMCrypto_HDCP_Capability>(GetOption("max_hdcp", 0));
|
|
|
|
|
if (max_hdcp != new_max_hdcp) {
|
|
|
|
|
LOGI("OEMCrypto max HDCP changed from %d (%s) to %d (%s)", max_hdcp,
|
|
|
|
|
HDCPCapabilityAsString(max_hdcp), new_max_hdcp,
|
|
|
|
|
HDCPCapabilityAsString(new_max_hdcp));
|
|
|
|
|
max_hdcp = new_max_hdcp;
|
|
|
|
|
}
|
|
|
|
|
return max_hdcp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This should start at 0, and be incremented only when a security patch has
|
|
|
|
|
// been applied to the device that fixes a security bug.
|
|
|
|
|
uint8_t config_security_patch_level() {
|
|
|
|
|
return GetOption("security_patch_level", 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t max_buffer_size() {
|
|
|
|
|
int max = GetOption("max_buffer_size", 0);
|
|
|
|
|
// If max is 1, just use default max buffer.
|
|
|
|
|
if (max == 1) return CryptoEngine::max_buffer_size();
|
|
|
|
|
return max; // If 0, no restriction. If something else, use that restriction.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void adjust_destination(OEMCrypto_DestBufferDesc *out_description,
|
|
|
|
|
size_t data_length, uint8_t subsample_flags) {
|
|
|
|
|
if (out_description->type != OEMCrypto_BufferType_Secure) return;
|
|
|
|
|
if (!level1_valid_) {
|
|
|
|
|
static bool warned_once = false;
|
|
|
|
|
if (!warned_once) {
|
|
|
|
|
warned_once = true;
|
|
|
|
|
LOGW("OEMCrypto Mock: given secure buffer with no level1 fallback.");
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (subsample_flags & OEMCrypto_FirstSubsample) {
|
|
|
|
|
final_destination_.type = OEMCrypto_BufferType_Secure;
|
|
|
|
|
final_destination_.buffer.secure.handle =
|
|
|
|
|
out_description->buffer.secure.handle;
|
|
|
|
|
final_destination_.buffer.secure.max_length =
|
|
|
|
|
out_description->buffer.secure.max_length;
|
|
|
|
|
final_destination_.buffer.secure.offset =
|
|
|
|
|
out_description->buffer.secure.offset;
|
|
|
|
|
temp_buffer_.resize(final_destination_.buffer.secure.max_length);
|
|
|
|
|
temp_buffer_length_ = 0;
|
|
|
|
|
}
|
|
|
|
|
if (temp_buffer_length_ != out_description->buffer.secure.offset) {
|
|
|
|
|
LOGW("OEMCrypto: offset into secure buffer is not correct %zd != %zd.",
|
|
|
|
|
temp_buffer_length_, out_description->buffer.secure.offset);
|
|
|
|
|
}
|
|
|
|
|
size_t new_length = temp_buffer_length_ + data_length;
|
|
|
|
|
if (new_length > temp_buffer_.size()) {
|
|
|
|
|
LOGW("Temp buffer was not big enough. %zd > %zd.", new_length,
|
|
|
|
|
temp_buffer_.size());
|
|
|
|
|
temp_buffer_.resize(new_length);
|
|
|
|
|
}
|
|
|
|
|
destination_ = &temp_buffer_[temp_buffer_length_];
|
|
|
|
|
temp_buffer_length_ = new_length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Push destination buffer to L1 output.
|
|
|
|
|
virtual OEMCryptoResult PushDestination(
|
|
|
|
|
OEMCrypto_DestBufferDesc *out_description, uint8_t subsample_flags) {
|
|
|
|
|
if (level1_valid_ &&
|
|
|
|
|
(out_description->type == OEMCrypto_BufferType_Secure)) {
|
|
|
|
|
if (subsample_flags & OEMCrypto_LastSubsample) {
|
|
|
|
|
return CopyBuffer_(&temp_buffer_[0], temp_buffer_length_,
|
|
|
|
|
&final_destination_,
|
|
|
|
|
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return OEMCrypto_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// If the SRM version has been loaded or not. If not, we use the system
|
|
|
|
|
// property to find the current SRM version.
|
|
|
|
|
bool srm_loaded_;
|
|
|
|
|
// Current srm version. Before an SRM has been loaded, this will be set from
|
|
|
|
|
// the system property.
|
|
|
|
|
int srm_version_;
|
|
|
|
|
|
|
|
|
|
std::map<std::string, int> options_;
|
|
|
|
|
|
|
|
|
|
std::string options_file_;
|
|
|
|
|
bool level1_valid_;
|
|
|
|
|
void* level1_library_;
|
|
|
|
|
L1_CopyBuffer_t CopyBuffer_;
|
|
|
|
|
L1_Initialize_t Initialize_;
|
|
|
|
|
L1_Terminate_t Terminate_;
|
|
|
|
|
OEMCrypto_DestBufferDesc final_destination_;
|
|
|
|
|
std::vector<uint8_t> temp_buffer_;
|
|
|
|
|
size_t temp_buffer_length_; // Length of temp buffer currently in use.
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CryptoEngine* CryptoEngine::MakeCryptoEngine(wvcdm::FileSystem *file_system) {
|
|
|
|
|
return new AndroidModifiableCryptoEngine(file_system);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace wvoec_mock
|