Improve OEMCrypto unit tests
This change updates the unit tests to have more comments so that it is more clear what went wrong if a test fails. Also, some utility code has been changed to make it easier to support new platforms and read/write locks. Also, the reference code has had some refactoring added to make it easier for Widevine to test CDM code. There should be no functionality differences in the reference code. Also, in the main API doc, there was an obsolete paragraph in the description of the threading model. This paragraph has been removed.
This commit is contained in:
Binary file not shown.
@@ -1,15 +1,15 @@
|
||||
# Copyright 2017 Google Inc. All Rights Reserved.
|
||||
# Copyright 2017 Google LLC. All Rights Reserved.
|
||||
|
||||
"""OEM certificate generation tool.
|
||||
|
||||
Supports:
|
||||
- Generating CSR (certificate signing request)
|
||||
- Generating OEM intermediate certificate (for testing)
|
||||
- Generating OEM intermediate certificate (for testing only)
|
||||
- Generating OEM leaf certificate chain
|
||||
- Erasing file securely
|
||||
- Getting CSR/certificate/certificate chain information
|
||||
|
||||
Prerequirements:
|
||||
Prerequirements (if running the script directly):
|
||||
- Install pip: https://pip.pypa.io/en/stable/installing/
|
||||
- Install python cryptography: https://cryptography.io/en/latest/installation/
|
||||
|
||||
@@ -124,9 +124,9 @@ class X509CertificateChain(object):
|
||||
for certificate in self._certificates:
|
||||
backend._lib.sk_X509_push(x509_stack, certificate._x509)
|
||||
|
||||
pkcs7_partial = 0x4000
|
||||
p7 = backend._lib.PKCS7_sign(backend._ffi.NULL, backend._ffi.NULL,
|
||||
x509_stack, backend._ffi.NULL, pkcs7_partial)
|
||||
x509_stack, backend._ffi.NULL,
|
||||
backend._lib.PKCS7_DETACHED)
|
||||
p7 = backend._ffi.gc(p7, backend._lib.PKCS7_free)
|
||||
|
||||
bio = backend._create_mem_bio_gc()
|
||||
@@ -247,8 +247,14 @@ def generate_intermediate_certificate(args):
|
||||
def generate_leaf_certificate(args):
|
||||
"""Subparser handler for generating leaf certificate."""
|
||||
intermediate_cert_bytes = args.intermediate_certificate_file.read()
|
||||
intermediate_cert = x509.load_der_x509_certificate(intermediate_cert_bytes,
|
||||
backends.default_backend())
|
||||
|
||||
try:
|
||||
intermediate_cert = x509.load_pem_x509_certificate(
|
||||
intermediate_cert_bytes, backends.default_backend())
|
||||
except ValueError:
|
||||
intermediate_cert = x509.load_der_x509_certificate(
|
||||
intermediate_cert_bytes, backends.default_backend())
|
||||
|
||||
intermediate_private_key = serialization.load_der_private_key(
|
||||
args.intermediate_private_key_file.read(),
|
||||
password=args.intermediate_private_key_passphrase,
|
||||
@@ -334,8 +340,14 @@ def _handle_csr(data):
|
||||
x509.load_pem_x509_csr(data, backends.default_backend()))
|
||||
|
||||
|
||||
def _handle_certificate(data):
|
||||
"""Utility function for get_info to parse certificate."""
|
||||
def _handle_pem_certificate(data):
|
||||
"""Utility function for get_info to parse pem certificate."""
|
||||
return _certificate_as_string(
|
||||
x509.load_pem_x509_certificate(data, backends.default_backend()))
|
||||
|
||||
|
||||
def _handle_der_certificate(data):
|
||||
"""Utility function for get_info to parse der certificate."""
|
||||
return _certificate_as_string(
|
||||
x509.load_der_x509_certificate(data, backends.default_backend()))
|
||||
|
||||
@@ -353,7 +365,10 @@ def get_info(args, out=sys.stdout):
|
||||
# The input is either a CSR or a certificate, or a certificate chain.
|
||||
# Loop through the corresponding handlers one by one.
|
||||
data = args.file.read()
|
||||
for handler in [_handle_csr, _handle_certificate, _handle_certificate_chain]:
|
||||
for handler in [
|
||||
_handle_csr, _handle_der_certificate, _handle_pem_certificate,
|
||||
_handle_certificate_chain
|
||||
]:
|
||||
try:
|
||||
out.write(handler(data))
|
||||
return
|
||||
|
||||
@@ -61,6 +61,7 @@ class AuthenticationRoot {
|
||||
RSA_shared_ptr& SharedRsaKey() { return rsa_key_; }
|
||||
RSA* rsa_key() { return rsa_key_.get(); }
|
||||
bool LoadTestRsaKey();
|
||||
void Clear() { use_test_keybox_ = false; }
|
||||
|
||||
private:
|
||||
OEMCrypto_ProvisioningMethod provisioning_method_;
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace wvoec_ref {
|
||||
|
||||
class CertOnlyCryptoEngine : public CryptoEngine {
|
||||
public:
|
||||
explicit CertOnlyCryptoEngine(std::unique_ptr<wvcdm::FileSystem> file_system)
|
||||
: CryptoEngine(file_system) {}
|
||||
explicit CertOnlyCryptoEngine(std::unique_ptr<wvcdm::FileSystem>&& file_system)
|
||||
: CryptoEngine(std::move(file_system)) {}
|
||||
|
||||
bool config_local_display_only() { return true; }
|
||||
|
||||
@@ -30,8 +30,8 @@ class CertOnlyCryptoEngine : public CryptoEngine {
|
||||
};
|
||||
|
||||
CryptoEngine* CryptoEngine::MakeCryptoEngine(
|
||||
std::unique_ptr<wvcdm::FileSystem> file_system) {
|
||||
return new CertOnlyCryptoEngine(file_system);
|
||||
std::unique_ptr<wvcdm::FileSystem>&& file_system) {
|
||||
return new CertOnlyCryptoEngine(std::move(file_system));
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
//
|
||||
#include "oemcrypto_engine_ref.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <chrono>
|
||||
#include <string.h>
|
||||
@@ -39,12 +38,6 @@ CryptoEngine::CryptoEngine(std::unique_ptr<wvcdm::FileSystem>&& file_system)
|
||||
}
|
||||
|
||||
CryptoEngine::~CryptoEngine() {
|
||||
std::unique_lock<std::mutex> lock(session_table_lock_);
|
||||
ActiveSessions::iterator it;
|
||||
for (it = sessions_.begin(); it != sessions_.end(); ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
sessions_.clear();
|
||||
ERR_free_strings();
|
||||
}
|
||||
|
||||
@@ -53,6 +46,16 @@ bool CryptoEngine::Initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CryptoEngine::Terminate() {
|
||||
std::unique_lock<std::mutex> lock(session_table_lock_);
|
||||
ActiveSessions::iterator it;
|
||||
for (it = sessions_.begin(); it != sessions_.end(); ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
sessions_.clear();
|
||||
root_of_trust_.Clear();
|
||||
}
|
||||
|
||||
SessionId CryptoEngine::OpenSession() {
|
||||
std::unique_lock<std::mutex> lock(session_table_lock_);
|
||||
static OEMCrypto_SESSION unique_id = 1;
|
||||
@@ -212,6 +215,13 @@ OEMCryptoResult CryptoEngine::SetDestination(
|
||||
default:
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
size_t max_allowed = max_output_size();
|
||||
if (max_allowed > 0 &&
|
||||
(max_allowed < max_length || max_allowed < data_length)) {
|
||||
LOGE("Output too large (or buffer too small).");
|
||||
return OEMCrypto_ERROR_OUTPUT_TOO_LARGE;
|
||||
}
|
||||
|
||||
if (out_description->type != OEMCrypto_BufferType_Direct &&
|
||||
max_length < data_length) {
|
||||
LOGE("[SetDestination(): OEMCrypto_ERROR_SHORT_BUFFER]");
|
||||
|
||||
@@ -71,11 +71,11 @@ class CryptoEngine {
|
||||
return root_of_trust_.DeviceToken();
|
||||
}
|
||||
|
||||
virtual void Terminate() {}
|
||||
virtual void Terminate();
|
||||
|
||||
virtual SessionId OpenSession();
|
||||
|
||||
bool DestroySession(SessionId sid);
|
||||
virtual bool DestroySession(SessionId sid);
|
||||
|
||||
SessionContext* FindSession(SessionId sid);
|
||||
|
||||
@@ -150,6 +150,11 @@ class CryptoEngine {
|
||||
// This is the same as the max subsample size, not the sample or frame size.
|
||||
virtual size_t max_buffer_size() { return 1024 * 100; } // 100 KiB.
|
||||
|
||||
// If 0 no restriction, otherwise it's the max output buffer for DecryptCENC
|
||||
// and CopyBuffer. This is the same as the max frame or sample size, not the
|
||||
// subsample size.
|
||||
virtual size_t max_output_size() { return 0; }
|
||||
|
||||
virtual bool srm_update_supported() { return false; }
|
||||
|
||||
virtual OEMCryptoResult current_srm_version(uint16_t* version) {
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
//
|
||||
#include "oemcrypto_keybox_ref.h"
|
||||
|
||||
#include <arpa/inet.h> // needed for ntoh()
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "log.h"
|
||||
#include "oemcrypto_types.h"
|
||||
#include "platform.h"
|
||||
#include "wvcrc32.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
@@ -53,7 +53,7 @@ uint32_t unaligned_dereference_uint32(const void* unaligned_ptr) {
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
static CryptoEngine* crypto_engine = NULL;
|
||||
static std::unique_ptr<CryptoEngine> crypto_engine;
|
||||
|
||||
typedef struct {
|
||||
uint8_t signature[wvoec::MAC_KEY_SIZE];
|
||||
@@ -63,17 +63,15 @@ typedef struct {
|
||||
} WrappedRSAKey;
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_Initialize(void) {
|
||||
if (crypto_engine) {
|
||||
if (crypto_engine != nullptr) {
|
||||
LOGE("------------------------- Calling Initialize without Terminate\n");
|
||||
delete crypto_engine;
|
||||
crypto_engine = NULL;
|
||||
crypto_engine.reset();
|
||||
}
|
||||
// NOTE: This requires a compatible Filesystem implementation.
|
||||
// NOTE: Ownership of the FileSystem object is transferred to CryptoEngine
|
||||
std::unique_ptr<wvcdm::FileSystem> fs(new wvcdm::FileSystem());
|
||||
crypto_engine = CryptoEngine::MakeCryptoEngine(std::move(fs));
|
||||
|
||||
if (!crypto_engine || !crypto_engine->Initialize()) {
|
||||
crypto_engine.reset(CryptoEngine::MakeCryptoEngine(std::move(fs)));
|
||||
if (crypto_engine == nullptr || !crypto_engine->Initialize()) {
|
||||
LOGE("[OEMCrypto_Initialize(): failed]");
|
||||
return OEMCrypto_ERROR_INIT_FAILED;
|
||||
}
|
||||
@@ -86,20 +84,18 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_SetSandbox(
|
||||
}
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_Terminate(void) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("[OEMCrypto_Terminate(): not initialized]");
|
||||
return OEMCrypto_ERROR_TERMINATE_FAILED;
|
||||
}
|
||||
crypto_engine->Terminate();
|
||||
|
||||
delete crypto_engine;
|
||||
crypto_engine = NULL;
|
||||
crypto_engine.reset();
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_OpenSession(
|
||||
OEMCrypto_SESSION* session) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_OpenSession: OEMCrypto not initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -115,7 +111,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_OpenSession(
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_CloseSession(
|
||||
OEMCrypto_SESSION session) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_CloseSession: OEMCrypto not initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -130,7 +126,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
|
||||
OEMCrypto_SESSION session, const uint8_t* mac_key_context,
|
||||
uint32_t mac_key_context_length, const uint8_t* enc_key_context,
|
||||
uint32_t enc_key_context_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GenerateDerivedKeys: OEMCrypto not initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -164,7 +160,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
|
||||
uint32_t* nonce) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GenerateNonce: OEMCrypto not initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -209,7 +205,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateSignature(
|
||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||
uint8_t* signature, size_t* signature_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GenerateSignature: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -261,7 +257,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadKeys(
|
||||
size_t num_keys, const OEMCrypto_KeyObject* key_array,
|
||||
OEMCrypto_Substring pst, OEMCrypto_Substring srm_restriction_data,
|
||||
OEMCrypto_LicenseType license_type) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_LoadKeys: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -321,7 +317,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
|
||||
LOGE("[OEMCrypto_LoadEntitledContentKeys(): missing key_array.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_LoadEntitledContentKeys: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -352,7 +348,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_RefreshKeys(
|
||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length, size_t num_keys,
|
||||
const OEMCrypto_KeyRefreshObject* key_array) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_RefreshKeys: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -440,7 +436,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_RefreshKeys(
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_QueryKeyControl(
|
||||
OEMCrypto_SESSION session, const uint8_t* key_id, size_t key_id_length,
|
||||
uint8_t* key_control_block, size_t* key_control_block_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_QueryKeyControl: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -498,7 +494,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_DecryptCENC(
|
||||
bool is_encrypted, const uint8_t* iv, size_t block_offset,
|
||||
OEMCrypto_DestBufferDesc* out_buffer,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern, uint8_t subsample_flags) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_DecryptCENC: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -543,7 +539,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_DecryptCENC(
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_CopyBuffer(
|
||||
OEMCrypto_SESSION session, const uint8_t* data_addr, size_t data_length,
|
||||
OEMCrypto_DestBufferDesc* out_buffer, uint8_t subsample_flags) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_CopyBuffer: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -586,7 +582,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_WrapKeyboxOrOEMCert(
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_InstallKeyboxOrOEMCert(
|
||||
const uint8_t* keybox, size_t keyBoxLength) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_InstallKeyboxOrOEMCert: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -601,7 +597,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_InstallKeyboxOrOEMCert(
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer,
|
||||
size_t length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_LoadTestKeybox: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -613,7 +609,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer,
|
||||
}
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_IsKeyboxOrOEMCertValid: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -645,7 +641,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void) {
|
||||
}
|
||||
|
||||
OEMCRYPTO_API OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod() {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetProvisioningMethod: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ProvisioningError;
|
||||
}
|
||||
@@ -655,7 +651,7 @@ OEMCRYPTO_API OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod() {
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(
|
||||
OEMCrypto_SESSION session, uint8_t* public_cert,
|
||||
size_t* public_cert_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetOEMPublicCertificate: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -675,7 +671,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
|
||||
size_t* idLength) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetDeviceID: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -704,7 +700,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
||||
size_t* keyDataLength) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetKeyData: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -733,7 +729,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
|
||||
size_t dataLength) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetRandom: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -756,7 +752,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
|
||||
if (unaligned_nonce == NULL) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_RewrapDeviceRSAKey30: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -873,7 +869,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
|
||||
if (unaligned_nonce == NULL) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_RewrapDeviceRSAKey: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -990,7 +986,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(
|
||||
LOGE("[OEMCrypto_LoadDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_LoadDeviceRSAKey: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1053,7 +1049,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(
|
||||
}
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadTestRSAKey() {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_LoadTestRSAKey: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1065,7 +1061,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||
uint8_t* signature, size_t* signature_length,
|
||||
RSA_Padding_Scheme padding_scheme) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GenerateRSASignature: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1103,7 +1099,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
|
||||
size_t enc_session_key_length, const uint8_t* mac_key_context,
|
||||
size_t mac_key_context_length, const uint8_t* enc_key_context,
|
||||
size_t enc_key_context_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_DeriveKeysFromSessionKey: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1151,7 +1147,7 @@ OEMCRYPTO_API const char* OEMCrypto_SecurityLevel() {
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetHDCPCapability(
|
||||
OEMCrypto_HDCP_Capability* current, OEMCrypto_HDCP_Capability* maximum) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetHDCPCapability: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1163,7 +1159,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetHDCPCapability(
|
||||
}
|
||||
|
||||
OEMCRYPTO_API uint32_t OEMCrypto_GetAnalogOutputFlags() {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetAnalogOutputFlags: OEMCrypto Not Initialized.");
|
||||
return 0;
|
||||
}
|
||||
@@ -1175,7 +1171,7 @@ OEMCRYPTO_API const char* OEMCrypto_BuildInformation() {
|
||||
}
|
||||
|
||||
OEMCRYPTO_API uint32_t OEMCrypto_ResourceRatingTier() {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_ResourceRatingTier: OEMCrypto Not Initialized.");
|
||||
return 0;
|
||||
}
|
||||
@@ -1183,7 +1179,7 @@ OEMCRYPTO_API uint32_t OEMCrypto_ResourceRatingTier() {
|
||||
}
|
||||
|
||||
OEMCRYPTO_API bool OEMCrypto_SupportsUsageTable() {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_SupportsUsageTable: OEMCrypto Not Initialized.");
|
||||
return 0;
|
||||
}
|
||||
@@ -1192,7 +1188,7 @@ OEMCRYPTO_API bool OEMCrypto_SupportsUsageTable() {
|
||||
}
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* count) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetNumberOfOpenSessions: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1203,7 +1199,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* count) {
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(
|
||||
size_t* maximum) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetMaxNumberOfSessions: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1220,7 +1216,7 @@ OEMCRYPTO_API bool OEMCrypto_IsAntiRollbackHwPresent() {
|
||||
}
|
||||
|
||||
OEMCRYPTO_API uint32_t OEMCrypto_SupportedCertificates() {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetProvisioningMethod: OEMCrypto Not Initialized.");
|
||||
return 0;
|
||||
}
|
||||
@@ -1234,7 +1230,7 @@ OEMCRYPTO_API uint32_t OEMCrypto_SupportedCertificates() {
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Encrypt(
|
||||
OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
|
||||
const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_Generic_Encrypt: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1260,7 +1256,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Encrypt(
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Decrypt(
|
||||
OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
|
||||
const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_Generic_Decrypt: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1287,7 +1283,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Sign(
|
||||
OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
|
||||
OEMCrypto_Algorithm algorithm, uint8_t* signature,
|
||||
size_t* signature_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_Generic_Sign: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1317,7 +1313,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Verify(
|
||||
OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
|
||||
OEMCrypto_Algorithm algorithm, const uint8_t* signature,
|
||||
size_t signature_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_Generic_Verify: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1348,7 +1344,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_UpdateUsageTable() {
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_DeactivateUsageEntry(
|
||||
OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_DeactivateUsageEntry: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1369,7 +1365,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
|
||||
size_t pst_length,
|
||||
uint8_t* buffer,
|
||||
size_t* buffer_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_ReportUsage: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1403,7 +1399,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_ForceDeleteUsageEntry(const uint8_t*,
|
||||
}
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_DeleteOldUsageTable() {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_DeleteOldUsageTable: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1414,7 +1410,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_DeleteOldUsageTable() {
|
||||
}
|
||||
|
||||
OEMCRYPTO_API bool OEMCrypto_IsSRMUpdateSupported() {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_IsSRMUpdateSupported: OEMCrypto Not Initialized.");
|
||||
return false;
|
||||
}
|
||||
@@ -1424,7 +1420,7 @@ OEMCRYPTO_API bool OEMCrypto_IsSRMUpdateSupported() {
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetCurrentSRMVersion(
|
||||
uint16_t* version) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetCurrentSRMVersion: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1437,7 +1433,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetCurrentSRMVersion(
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadSRM(const uint8_t* buffer,
|
||||
size_t buffer_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_LoadSRM: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1445,7 +1441,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadSRM(const uint8_t* buffer,
|
||||
}
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_RemoveSRM() {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_RemoveSRM: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1454,7 +1450,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_RemoveSRM() {
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_CreateUsageTableHeader(
|
||||
uint8_t* header_buffer, size_t* header_buffer_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_CreateUsageTableHeader: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1468,7 +1464,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_CreateUsageTableHeader(
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadUsageTableHeader(
|
||||
const uint8_t* buffer, size_t buffer_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_LoadUsageTableHeader: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1485,7 +1481,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadUsageTableHeader(
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_CreateNewUsageEntry(
|
||||
OEMCrypto_SESSION session, uint32_t* usage_entry_number) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_CreateNewUsageEntry: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1507,7 +1503,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_CreateNewUsageEntry(
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadUsageEntry(
|
||||
OEMCrypto_SESSION session, uint32_t index, const uint8_t* buffer,
|
||||
size_t buffer_size) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_LoadUsageEntry: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1531,7 +1527,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_UpdateUsageEntry(
|
||||
OEMCrypto_SESSION session, uint8_t* header_buffer,
|
||||
size_t* header_buffer_length, uint8_t* entry_buffer,
|
||||
size_t* entry_buffer_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_UpdateUsageEntry: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1553,7 +1549,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_UpdateUsageEntry(
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader(
|
||||
uint32_t new_table_size, uint8_t* header_buffer,
|
||||
size_t* header_buffer_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_ShrinkUsageTableHeader: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1566,7 +1562,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader(
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_MoveEntry(OEMCrypto_SESSION session,
|
||||
uint32_t new_index) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_MoveEntry: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1583,7 +1579,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_MoveEntry(OEMCrypto_SESSION session,
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_CopyOldUsageEntry(
|
||||
OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_CopyOldUsageEntry: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1604,7 +1600,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_CreateOldUsageEntry(
|
||||
uint64_t time_since_last_decrypt, OEMCrypto_Usage_Entry_Status status,
|
||||
uint8_t* server_mac_key, uint8_t* client_mac_key, const uint8_t* pst,
|
||||
size_t pst_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_CreateOldUsageEntry: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1624,7 +1620,7 @@ OEMCRYPTO_API uint32_t OEMCrypto_SupportsDecryptHash() {
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_SetDecryptHash(
|
||||
OEMCrypto_SESSION session, uint32_t frame_number, const uint8_t* hash,
|
||||
size_t hash_length) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_SetDecryptHash: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
@@ -1638,7 +1634,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_SetDecryptHash(
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetHashErrorCode(
|
||||
OEMCrypto_SESSION session, uint32_t* failed_frame_number) {
|
||||
if (!crypto_engine) {
|
||||
if (crypto_engine == nullptr) {
|
||||
LOGE("OEMCrypto_GetHashErrorCode: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
//
|
||||
#include "oemcrypto_session.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
@@ -30,6 +29,7 @@
|
||||
#include "oemcrypto_key_ref.h"
|
||||
#include "oemcrypto_rsa_key_shared.h"
|
||||
#include "oemcrypto_types.h"
|
||||
#include "platform.h"
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wvcrc32.h"
|
||||
@@ -67,8 +67,7 @@ class ContentKeysContext : public SessionContextKeys {
|
||||
bool SetContentKey(const KeyId& entitlement_id,
|
||||
const KeyId& content_key_id,
|
||||
const std::vector<uint8_t>& content_key) override;
|
||||
bool GetEntitlementKey(const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** entitlement_key) override;
|
||||
EntitlementKey* GetEntitlementKey(const KeyId& entitlement_id) override;
|
||||
|
||||
private:
|
||||
SessionKeyTable session_keys_;
|
||||
@@ -98,11 +97,11 @@ bool ContentKeysContext::SetContentKey(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ContentKeysContext::GetEntitlementKey(const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** key) {
|
||||
EntitlementKey* ContentKeysContext::GetEntitlementKey(
|
||||
const KeyId& entitlement_id) {
|
||||
// Unsupported action for this type.
|
||||
return false;
|
||||
};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/***************************************/
|
||||
|
||||
@@ -118,8 +117,7 @@ class EntitlementKeysContext : public SessionContextKeys {
|
||||
bool SetContentKey(const KeyId& entitlement_id,
|
||||
const KeyId& content_key_id,
|
||||
const std::vector<uint8_t>& content_key) override;
|
||||
bool GetEntitlementKey(const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** key) override;
|
||||
EntitlementKey* GetEntitlementKey(const KeyId& entitlement_id) override;
|
||||
|
||||
OEMCrypto_LicenseType type() override { return OEMCrypto_EntitlementLicense; }
|
||||
|
||||
@@ -151,9 +149,9 @@ bool EntitlementKeysContext::SetContentKey(
|
||||
content_key);
|
||||
}
|
||||
|
||||
bool EntitlementKeysContext::GetEntitlementKey(
|
||||
const KeyId& entitlement_id, const std::vector<uint8_t>** out_key) {
|
||||
return session_keys_.GetEntitlementKey(entitlement_id, out_key);
|
||||
EntitlementKey* EntitlementKeysContext::GetEntitlementKey(
|
||||
const KeyId& entitlement_id) {
|
||||
return session_keys_.GetEntitlementKey(entitlement_id);
|
||||
}
|
||||
|
||||
/***************************************/
|
||||
@@ -552,10 +550,6 @@ OEMCryptoResult SessionContext::LoadKeys(
|
||||
}
|
||||
}
|
||||
|
||||
// If there are already keys installed in this session, then we can load
|
||||
// a shared license.
|
||||
bool second_license = (session_keys_->size() > 0);
|
||||
|
||||
// Decrypt and install keys in key object
|
||||
// Each key will have a key control block. They will all have the same nonce.
|
||||
OEMCryptoResult status = OEMCrypto_SUCCESS;
|
||||
@@ -587,7 +581,7 @@ OEMCryptoResult SessionContext::LoadKeys(
|
||||
|
||||
OEMCryptoResult result =
|
||||
InstallKey(key_id, enc_key_data, key_data_iv, key_control,
|
||||
key_control_iv, second_license);
|
||||
key_control_iv);
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
status = result;
|
||||
break;
|
||||
@@ -661,9 +655,9 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
||||
message + key_data->entitlement_key_id.offset +
|
||||
key_data->entitlement_key_id.length);
|
||||
|
||||
const std::vector<uint8_t>* entitlement_key = NULL;
|
||||
if (!session_keys_->GetEntitlementKey(entitlement_key_id,
|
||||
&entitlement_key)) {
|
||||
EntitlementKey* entitlement_key =
|
||||
session_keys_->GetEntitlementKey(entitlement_key_id);
|
||||
if (entitlement_key == nullptr) {
|
||||
return OEMCrypto_KEY_NOT_ENTITLED;
|
||||
}
|
||||
std::vector<uint8_t> content_key;
|
||||
@@ -679,8 +673,9 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
||||
content_key_id.assign(message + key_data->content_key_id.offset,
|
||||
message + key_data->content_key_id.offset +
|
||||
key_data->content_key_id.length);
|
||||
if (!DecryptMessage(*entitlement_key, iv, encrypted_content_key,
|
||||
&content_key, 256 /* key size */)) {
|
||||
if (!DecryptMessage(entitlement_key->entitlement_key(), iv,
|
||||
encrypted_content_key, &content_key,
|
||||
256 /* key size */)) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (!session_keys_->SetContentKey(entitlement_key_id, content_key_id,
|
||||
@@ -695,7 +690,7 @@ OEMCryptoResult SessionContext::InstallKey(
|
||||
const KeyId& key_id, const std::vector<uint8_t>& key_data,
|
||||
const std::vector<uint8_t>& key_data_iv,
|
||||
const std::vector<uint8_t>& key_control,
|
||||
const std::vector<uint8_t>& key_control_iv, bool second_license) {
|
||||
const std::vector<uint8_t>& key_control_iv) {
|
||||
// Decrypt encrypted key_data using derived encryption key and offered iv
|
||||
std::vector<uint8_t> content_key;
|
||||
std::vector<uint8_t> key_control_str;
|
||||
@@ -745,12 +740,6 @@ OEMCryptoResult SessionContext::InstallKey(
|
||||
LOGE("LoadKeys: Failed Nonce/PST check.");
|
||||
return result;
|
||||
}
|
||||
if (key_control_block.control_bits() & wvoec::kSharedLicense) {
|
||||
if (!second_license) {
|
||||
LOGE("LoadKeys: Shared License, but no keys previously loaded.");
|
||||
return OEMCrypto_ERROR_MISSING_MASTER;
|
||||
}
|
||||
}
|
||||
if (key_control_block.control_bits() & wvoec::kControlSRMVersionRequired) {
|
||||
if (srm_requirements_status_ == NoSRMVersion) {
|
||||
LOGE("[LoadKeys: control bit says SRM version required]");
|
||||
|
||||
@@ -46,8 +46,7 @@ class SessionContextKeys {
|
||||
virtual bool SetContentKey(const KeyId& entitlement_id,
|
||||
const KeyId& content_key_id,
|
||||
const std::vector<uint8_t>& content_key) = 0;
|
||||
virtual bool GetEntitlementKey(const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** key) = 0;
|
||||
virtual EntitlementKey* GetEntitlementKey(const KeyId& entitlement_id) = 0;
|
||||
|
||||
virtual ~SessionContextKeys() {}
|
||||
|
||||
@@ -132,12 +131,11 @@ class SessionContext {
|
||||
OEMCryptoResult LoadEntitledContentKeys(
|
||||
const uint8_t* message, size_t message_length, size_t num_keys,
|
||||
const OEMCrypto_EntitledContentKeyObject* key_array);
|
||||
virtual OEMCryptoResult InstallKey(const KeyId& key_id,
|
||||
const std::vector<uint8_t>& key_data,
|
||||
const std::vector<uint8_t>& key_data_iv,
|
||||
const std::vector<uint8_t>& key_control,
|
||||
const std::vector<uint8_t>& key_control_iv,
|
||||
bool second_license);
|
||||
virtual OEMCryptoResult InstallKey(
|
||||
const KeyId& key_id, const std::vector<uint8_t>& key_data,
|
||||
const std::vector<uint8_t>& key_data_iv,
|
||||
const std::vector<uint8_t>& key_control,
|
||||
const std::vector<uint8_t>& key_control_iv);
|
||||
bool InstallRSAEncryptedKey(const uint8_t* encrypted_message_key,
|
||||
size_t encrypted_message_key_length);
|
||||
bool DecryptRSAKey(const uint8_t* enc_rsa_key, size_t enc_rsa_key_length,
|
||||
|
||||
@@ -102,18 +102,13 @@ bool EntitlementKeyTable::SetContentKey(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EntitlementKeyTable::GetEntitlementKey(
|
||||
const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** entitlement_key) {
|
||||
if (!entitlement_key) {
|
||||
return false;
|
||||
}
|
||||
EntitlementKey* EntitlementKeyTable::GetEntitlementKey(
|
||||
const KeyId& entitlement_id) {
|
||||
EntitlementKeyMap::iterator it = keys_.find(entitlement_id);
|
||||
if (it == keys_.end()) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
*entitlement_key = &it->second->entitlement_key();
|
||||
return true;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
@@ -57,8 +57,7 @@ class EntitlementKeyTable {
|
||||
size_t size() const { return contentid_to_entitlementid_.size(); }
|
||||
bool SetContentKey(const KeyId& entitlement_id, const KeyId& content_key_id,
|
||||
const std::vector<uint8_t> content_key);
|
||||
bool GetEntitlementKey(const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** entitlement_key);
|
||||
EntitlementKey* GetEntitlementKey(const KeyId& entitlement_id);
|
||||
|
||||
private:
|
||||
EntitlementKeyMap keys_;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//
|
||||
// Compute CRC32 Checksum. Needed for verification of WV Keybox.
|
||||
//
|
||||
#include <arpa/inet.h>
|
||||
#include "platform.h"
|
||||
#include "wvcrc32.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
@@ -133,7 +133,7 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
|
||||
}
|
||||
std::string security_level = OEMCrypto_SecurityLevel();
|
||||
supports_level_1 = (security_level == "L1");
|
||||
printf("SecurityLevel is %s (%s)",
|
||||
printf("SecurityLevel is %s (%s)\n",
|
||||
supports_level_1 ? "Level 1" : "Not Level 1",
|
||||
security_level.c_str());
|
||||
OEMCrypto_Terminate();
|
||||
@@ -153,12 +153,33 @@ std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
|
||||
if (provisioning_method
|
||||
!= OEMCrypto_OEMCertificate) FilterOut(&filter, "*Prov30*");
|
||||
if (!supports_rsa_3072) FilterOut(&filter, "*RSAKey3072*");
|
||||
if (api_version < 9) FilterOut(&filter, "*API09*");
|
||||
if (api_version < 10) FilterOut(&filter, "*API10*");
|
||||
if (api_version < 11) FilterOut(&filter, "*API11*");
|
||||
if (api_version < 12) FilterOut(&filter, "*API12*");
|
||||
if (api_version < 13) FilterOut(&filter, "*API13*");
|
||||
if (api_version < 14) FilterOut(&filter, "*API14*");
|
||||
if (api_version < 14) {
|
||||
// Because API 13 uses an old hard coded test keybox, none of these tests
|
||||
// will pass. Partners who wish to test with a v13 OEMCrypto should use
|
||||
// code on an older v13 branch.
|
||||
printf("These unit tests are designed for OEMCrypto API 15 and above.\n");
|
||||
printf("This device has an OEMCrypto with API version %d.\n", api_version);
|
||||
printf("To verify correctness, please build unit tests from a "
|
||||
"compatible branch.\n");
|
||||
FilterOut(&filter, "*API09*");
|
||||
FilterOut(&filter, "*API10*");
|
||||
FilterOut(&filter, "*API11*");
|
||||
FilterOut(&filter, "*API12*");
|
||||
FilterOut(&filter, "*API13*");
|
||||
FilterOut(&filter, "*API14*");
|
||||
FilterOut(&filter, "*TestKeyboxTest*");
|
||||
FilterOut(&filter, "*SessionTest*");
|
||||
FilterOut(&filter, "*UsageTable*");
|
||||
FilterOut(&filter, "*GenericCrypto*");
|
||||
FilterOut(&filter, "*LoadsCertificate*");
|
||||
FilterOut(&filter, "*UsesCertificate*");
|
||||
// We also expect some CDM tests to fail without a new test keybox:
|
||||
FilterOut(&filter, "*WvCdmRequestLicenseTest*");
|
||||
FilterOut(&filter, "*WvGenericOperations*");
|
||||
FilterOut(&filter, "*WvCdmEngine*");
|
||||
FilterOut(&filter, "*Cdm/WvCdm*");
|
||||
FilterOut(&filter, "*Cdm/WvHls*");
|
||||
}
|
||||
if (api_version < 15) FilterOut(&filter, "*API15*");
|
||||
// Some tests may require root access. If user is not root, filter these tests
|
||||
// out.
|
||||
|
||||
@@ -8,8 +8,13 @@
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// Keeps track of which features are supported by the version of OEMCrypto being
|
||||
// tested. See the integration guide for a list of optional features.
|
||||
class DeviceFeatures {
|
||||
public:
|
||||
// There are several possible methods used to derive a set of known session
|
||||
// keys. For example, the test can install a known test keybox, or it can
|
||||
// parse the OEM certificate.
|
||||
enum DeriveMethod { // Method to use derive session keys.
|
||||
NO_METHOD, // Cannot derive known session keys.
|
||||
LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys.
|
||||
@@ -32,15 +37,24 @@ class DeviceFeatures {
|
||||
uint32_t api_version;
|
||||
OEMCrypto_ProvisioningMethod provisioning_method;
|
||||
|
||||
// This should be called from the test program's main procedure.
|
||||
void Initialize(bool is_cast_receiver, bool force_load_test_keybox);
|
||||
// Generate a GTest filter of tests that should not be run. This should be
|
||||
// called after Initialize. Tests are filtered out based on which features
|
||||
// are not supported. For example, a device that uses Provisioning 3.0 will
|
||||
// have all keybox tests filtered out.
|
||||
std::string RestrictFilter(const std::string& initial_filter);
|
||||
|
||||
private:
|
||||
// Decide which method should be used to derive session keys, based on
|
||||
// supported featuers.
|
||||
void PickDerivedKey();
|
||||
bool IsTestKeyboxInstalled();
|
||||
// Add a GTest filter restriction to the current filter.
|
||||
void FilterOut(std::string* current_filter, const std::string& new_filter);
|
||||
};
|
||||
|
||||
// There is one global set of features for the version of OEMCrypto being
|
||||
// tested. This should be initialized in the test program's main procedure.
|
||||
extern DeviceFeatures global_features;
|
||||
const char* ProvisioningMethodName(OEMCrypto_ProvisioningMethod method);
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "oec_session_util.h"
|
||||
|
||||
#include <arpa/inet.h> // needed for ntoh()
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/cmac.h>
|
||||
@@ -32,6 +31,7 @@
|
||||
#include "oec_device_features.h"
|
||||
#include "oec_test_data.h"
|
||||
#include "oemcrypto_types.h"
|
||||
#include "platform.h"
|
||||
#include "string_conversions.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -80,6 +80,8 @@ void dump_boringssl_error() {
|
||||
}
|
||||
}
|
||||
|
||||
// A smart pointer for BoringSSL objects. It uses the specified free function
|
||||
// to release resources and free memory when the pointer is deleted.
|
||||
template <typename T, void (*func)(T*)>
|
||||
class boringssl_ptr {
|
||||
public:
|
||||
@@ -163,6 +165,7 @@ void Session::close() {
|
||||
}
|
||||
|
||||
void Session::GenerateNonce(int* error_counter) {
|
||||
// We make one attempt. If it fails, we assume there was a nonce flood.
|
||||
if (OEMCrypto_SUCCESS == OEMCrypto_GenerateNonce(session_id(), &nonce_)) {
|
||||
return;
|
||||
}
|
||||
@@ -170,6 +173,8 @@ void Session::GenerateNonce(int* error_counter) {
|
||||
(*error_counter)++;
|
||||
} else {
|
||||
sleep(1); // wait a second, then try again.
|
||||
// The following is after a 1 second pause, so it cannot be from a nonce
|
||||
// flood.
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GenerateNonce(session_id(), &nonce_));
|
||||
}
|
||||
@@ -196,6 +201,9 @@ void Session::FillDefaultContext(vector<uint8_t>* mac_context,
|
||||
"180120002a0c31383836373837343035000000000080");
|
||||
}
|
||||
|
||||
// This generates the truth data for deriving one key. If there are failures in
|
||||
// this function, then there is something wrong with the test program and its
|
||||
// dependency on BoringSSL.
|
||||
void Session::DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
|
||||
int counter, vector<uint8_t>* out) {
|
||||
ASSERT_FALSE(context.empty());
|
||||
@@ -222,6 +230,9 @@ void Session::DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
|
||||
CMAC_CTX_free(cmac_ctx);
|
||||
}
|
||||
|
||||
// This generates the truth data for deriving a set of keys. If there are
|
||||
// failures in this function, then there is something wrong with the test
|
||||
// program and its dependency on BoringSSL.
|
||||
void Session::DeriveKeys(const uint8_t* master_key,
|
||||
const vector<uint8_t>& mac_key_context,
|
||||
const vector<uint8_t>& enc_key_context) {
|
||||
@@ -241,6 +252,8 @@ void Session::DeriveKeys(const uint8_t* master_key,
|
||||
DeriveKey(master_key, enc_key_context, 1, &enc_key_);
|
||||
}
|
||||
|
||||
// This should only be called if the device uses Provisioning 2.0. A failure in
|
||||
// this function is probably caused by a bad keybox.
|
||||
void Session::GenerateDerivedKeysFromKeybox(
|
||||
const wvoec::WidevineKeybox& keybox) {
|
||||
GenerateNonce();
|
||||
@@ -261,10 +274,13 @@ void Session::GenerateDerivedKeysFromSessionKey() {
|
||||
vector<uint8_t> session_key;
|
||||
vector<uint8_t> enc_session_key;
|
||||
if (public_rsa_ == NULL) PreparePublicKey();
|
||||
// A failure here probably indicates that there is something wrong with the
|
||||
// test program and its dependency on BoringSSL.
|
||||
ASSERT_TRUE(GenerateRSASessionKey(&session_key, &enc_session_key));
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> enc_context;
|
||||
FillDefaultContext(&mac_context, &enc_context);
|
||||
// A failure here is probably caused by having the wrong RSA key loaded.
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_DeriveKeysFromSessionKey(
|
||||
session_id(), enc_session_key.data(), enc_session_key.size(),
|
||||
@@ -424,6 +440,10 @@ void Session::LoadEntitledContentKeys(OEMCryptoResult expected_sts) {
|
||||
VerifyEntitlementTestKeys();
|
||||
}
|
||||
|
||||
// This function verifies that the key control block reported by OEMCrypto agree
|
||||
// with the truth key control block. Failures in this function probably
|
||||
// indicate the OEMCrypto_LoadKeys did not correctly process the key control
|
||||
// block.
|
||||
void Session::VerifyTestKeys() {
|
||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||
KeyControlBlock block;
|
||||
@@ -446,6 +466,10 @@ void Session::VerifyTestKeys() {
|
||||
}
|
||||
}
|
||||
|
||||
// This function verifies that the key control block reported by OEMCrypto agree
|
||||
// with the truth key control block. Failures in this function probably
|
||||
// indicate the OEMCrypto_LoadEntitledKeys did not correctly process the key
|
||||
// control block.
|
||||
void Session::VerifyEntitlementTestKeys() {
|
||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||
KeyControlBlock block;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
// OEMCrypto unit tests
|
||||
//
|
||||
#include <openssl/rsa.h>
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ const uint8_t* find(const vector<uint8_t>& message,
|
||||
return &(*pos);
|
||||
}
|
||||
|
||||
// If force is true, we assert that the key loads successfully.
|
||||
// This creates a wrapped RSA key for devices that have the test keybox
|
||||
// installed. If force is true, we assert that the key loads successfully.
|
||||
void SessionUtil::CreateWrappedRSAKeyFromKeybox(uint32_t allowed_schemes,
|
||||
bool force) {
|
||||
Session s;
|
||||
@@ -42,7 +43,8 @@ void SessionUtil::CreateWrappedRSAKeyFromKeybox(uint32_t allowed_schemes,
|
||||
ASSERT_EQ(NULL, find(wrapped_rsa_key_, encoded_rsa_key_));
|
||||
}
|
||||
|
||||
// If force is true, we assert that the key loads successfully.
|
||||
// This creates a wrapped RSA key for devices using provisioning 3.0. If force
|
||||
// is true, we assert that the key loads successfully.
|
||||
void SessionUtil::CreateWrappedRSAKeyFromOEMCert(
|
||||
uint32_t allowed_schemes, bool force) {
|
||||
Session s;
|
||||
|
||||
@@ -26,8 +26,12 @@ public:
|
||||
// If force is true, we assert that the key loads successfully.
|
||||
void CreateWrappedRSAKey(uint32_t allowed_schemes, bool force);
|
||||
|
||||
// This is used to force installation of a keybox. This overwrites the
|
||||
// production keybox -- it does NOT use OEMCrypto_LoadTestKeybox.
|
||||
void InstallKeybox(const wvoec::WidevineKeybox& keybox, bool good);
|
||||
|
||||
// This loads the test keybox or the test RSA key, using LoadTestKeybox or
|
||||
// LoadTestRSAKey as needed.
|
||||
void EnsureTestKeys();
|
||||
|
||||
void InstallTestSessionKeys(Session* s);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,17 +43,13 @@ TEST_F(OEMCryptoAndroidLMPTest, GetKeyDataImplemented) {
|
||||
}
|
||||
}
|
||||
|
||||
// Android devices must have a valid keybox.
|
||||
TEST_F(OEMCryptoAndroidLMPTest, ValidKeybox) {
|
||||
if (OEMCrypto_GetProvisioningMethod() == OEMCrypto_Keybox) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoAndroidLMPTest, MinVersionNumber9) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_LE(9u, version);
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoAndroidLMPTest, ValidKeyboxTest) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
|
||||
}
|
||||
@@ -70,12 +66,14 @@ TEST_F(OEMCryptoAndroidLMPTest, RewrapDeviceRSAKeyImplemented) {
|
||||
}
|
||||
}
|
||||
|
||||
// This verifies that the device can load a DRM Certificate.
|
||||
TEST_F(OEMCryptoAndroidLMPTest, RSASignatureImplemented) {
|
||||
ASSERT_NE(
|
||||
OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_GenerateRSASignature(0, NULL, 0, NULL, NULL, kSign_RSASSA_PSS));
|
||||
}
|
||||
|
||||
// The Generic Crypto API functions are required for Android.
|
||||
TEST_F(OEMCryptoAndroidLMPTest, GenericCryptoImplemented) {
|
||||
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_Generic_Encrypt(0, NULL, 0, NULL,
|
||||
@@ -91,10 +89,13 @@ TEST_F(OEMCryptoAndroidLMPTest, GenericCryptoImplemented) {
|
||||
OEMCrypto_Generic_Verify(0, NULL, 0, OEMCrypto_HMAC_SHA256, NULL, 0));
|
||||
}
|
||||
|
||||
// Android requires support of usage table. The usage table is used for Secure
|
||||
// Stops and for offline licenses.
|
||||
TEST_F(OEMCryptoAndroidLMPTest, SupportsUsageTable) {
|
||||
ASSERT_TRUE(OEMCrypto_SupportsUsageTable());
|
||||
}
|
||||
|
||||
// Android devices require L1 OEMCrypto.
|
||||
TEST_F(OEMCryptoAndroidLMPTest, Level1Required) {
|
||||
const char* char_level = OEMCrypto_SecurityLevel();
|
||||
std::string security_level(char_level ? char_level : "");
|
||||
@@ -107,11 +108,8 @@ TEST_F(OEMCryptoAndroidLMPTest, Level1Required) {
|
||||
// These tests are required for M Android devices.
|
||||
class OEMCryptoAndroidMNCTest : public OEMCryptoAndroidLMPTest {};
|
||||
|
||||
TEST_F(OEMCryptoAndroidMNCTest, MinVersionNumber10) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_GE(version, 10u);
|
||||
}
|
||||
|
||||
// Android devices using Provisioning 2.0 must be able to load a test keybox.
|
||||
// If they are not using Provisioning 2.0, then they must use Provisioning 3.0.
|
||||
TEST_F(OEMCryptoAndroidMNCTest, LoadsTestKeyboxImplemented) {
|
||||
if (OEMCrypto_Keybox == OEMCrypto_GetProvisioningMethod()) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestKeybox(
|
||||
@@ -123,6 +121,7 @@ TEST_F(OEMCryptoAndroidMNCTest, LoadsTestKeyboxImplemented) {
|
||||
}
|
||||
}
|
||||
|
||||
// Android requires implementation of these functions.
|
||||
TEST_F(OEMCryptoAndroidMNCTest, NumberOfSessionsImplemented) {
|
||||
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_GetNumberOfOpenSessions(NULL));
|
||||
@@ -130,33 +129,10 @@ TEST_F(OEMCryptoAndroidMNCTest, NumberOfSessionsImplemented) {
|
||||
OEMCrypto_GetMaxNumberOfSessions(NULL));
|
||||
}
|
||||
|
||||
// Android requires implementation of these functions.
|
||||
TEST_F(OEMCryptoAndroidMNCTest, QueryKeyControlImplemented) {
|
||||
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_QueryKeyControl(0, NULL, 0, NULL, NULL));
|
||||
}
|
||||
|
||||
// These tests are required for N Android devices.
|
||||
class OEMCryptoAndroidNYCTest : public OEMCryptoAndroidMNCTest {};
|
||||
|
||||
TEST_F(OEMCryptoAndroidNYCTest, MinVersionNumber11) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_GE(version, 11u);
|
||||
}
|
||||
|
||||
// These tests are required for O MR1 Android devices.
|
||||
class OEMCryptoAndroidOCTest : public OEMCryptoAndroidNYCTest {};
|
||||
|
||||
TEST_F(OEMCryptoAndroidOCTest, MinVersionNumber13) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_GE(version, 13u);
|
||||
}
|
||||
|
||||
// These tests are required for Q Android devices.
|
||||
class OEMCryptoAndroidQTest : public OEMCryptoAndroidOCTest {};
|
||||
|
||||
TEST_F(OEMCryptoAndroidQTest, MinVersionNumber14) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_GE(version, 15u);
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -12,6 +12,9 @@ static void acknowledge_cast() {
|
||||
<< "==================================================================\n";
|
||||
}
|
||||
|
||||
// This special main procedure is used instead of the standard GTest main,
|
||||
// because we need to initialize the list of features supported by the device.
|
||||
// Also, the test filter is updated based on the feature list.
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
wvcdm::g_cutoff = wvcdm::LOG_INFO;
|
||||
|
||||
@@ -20,15 +20,14 @@
|
||||
'oemcrypto_test_main.cpp',
|
||||
'<(platform_specific_dir)/file_store.cpp',
|
||||
'<(platform_specific_dir)/log.cpp',
|
||||
'<(util_dir)/src/platform.cpp',
|
||||
'<(util_dir)/src/rw_lock.cpp',
|
||||
'<(util_dir)/src/string_conversions.cpp',
|
||||
],
|
||||
'includes': [
|
||||
'oemcrypto_unittests.gypi',
|
||||
'../ref/oec_ref.gypi',
|
||||
],
|
||||
'libraries': [
|
||||
'-lpthread', # gtest
|
||||
],
|
||||
'dependencies': [
|
||||
'<(boringssl_dependency)',
|
||||
'<(gtest_dependency)',
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//
|
||||
// Compute CRC32 Checksum. Needed for verification of WV Keybox.
|
||||
//
|
||||
#include <arpa/inet.h>
|
||||
#include "platform.h"
|
||||
#include "wvcrc32.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
#ifndef WVCDM_UTIL_FILE_STORE_H_
|
||||
#define WVCDM_UTIL_FILE_STORE_H_
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "platform.h"
|
||||
#include "util_common.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
33
util/include/platform.h
Normal file
33
util/include/platform.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Platform - Abstracts some utilities between platforms.
|
||||
//
|
||||
#ifndef WVCDM_UTIL_PLATFORM_H_
|
||||
#define WVCDM_UTIL_PLATFORM_H_
|
||||
|
||||
#include "util_common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <wtypes.h>
|
||||
# include <BaseTsd.h>
|
||||
# include <winsock2.h> // For htonl and ntohl.
|
||||
# define __PRETTY_FUNCTION__ __FUNCTION__
|
||||
# undef NO_ERROR
|
||||
# undef GetCurrentTime
|
||||
# undef DeleteFile
|
||||
|
||||
using ssize_t = SSIZE_T;
|
||||
|
||||
inline void sleep(int seconds) {
|
||||
Sleep(seconds * 1000);
|
||||
}
|
||||
CORE_UTIL_EXPORT int setenv(const char* key, const char* value, int overwrite);
|
||||
#else
|
||||
# include <arpa/inet.h>
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#endif // WVCDM_UTIL_PLATFORM_H_
|
||||
65
util/include/rw_lock.h
Normal file
65
util/include/rw_lock.h
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#ifndef WVCDM_UTIL_RW_LOCK_H_
|
||||
#define WVCDM_UTIL_RW_LOCK_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "util_common.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
// A simple reader-writer mutex implementation that mimics the one from C++17
|
||||
class CORE_UTIL_EXPORT shared_mutex {
|
||||
public:
|
||||
shared_mutex() : reader_count_(0), has_writer_(false) {}
|
||||
~shared_mutex();
|
||||
|
||||
// These methods take the mutex as a reader. They do not fulfill the
|
||||
// SharedMutex requirement from the C++14 STL, but they fulfill enough of it
|
||||
// to be used with |shared_lock| below.
|
||||
void lock_shared();
|
||||
void unlock_shared();
|
||||
|
||||
// These methods take the mutex as a writer. They fulfill the Mutex
|
||||
// requirement from the C++11 STL so that this mutex can be used with
|
||||
// |std::unique_lock|.
|
||||
void lock() { lock_implementation(false); }
|
||||
bool try_lock() { return lock_implementation(true); }
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
bool lock_implementation(bool abort_if_unavailable);
|
||||
|
||||
uint32_t reader_count_;
|
||||
bool has_writer_;
|
||||
|
||||
std::mutex mutex_;
|
||||
std::condition_variable condition_variable_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(shared_mutex);
|
||||
};
|
||||
|
||||
// A simple reader lock implementation that mimics the one from C++14
|
||||
template <typename Mutex>
|
||||
class shared_lock {
|
||||
public:
|
||||
explicit shared_lock(Mutex& lock) : lock_(&lock) { lock_->lock_shared(); }
|
||||
explicit shared_lock(Mutex* lock) : lock_(lock) { lock_->lock_shared(); }
|
||||
~shared_lock() { lock_->unlock_shared(); }
|
||||
|
||||
private:
|
||||
Mutex* lock_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(shared_lock);
|
||||
};
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
#endif // WVCDM_UTIL_RW_LOCK_H_
|
||||
12
util/src/dllmain.cpp
Normal file
12
util/src/dllmain.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// dllmain - A dummy DllMain method for Windows DLLs.
|
||||
//
|
||||
#include <windows.h>
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
|
||||
LPVOID lpReserved) {
|
||||
return TRUE;
|
||||
}
|
||||
21
util/src/platform.cpp
Normal file
21
util/src/platform.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include "stdlib.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
int setenv(const char* key, const char* value, int overwrite) {
|
||||
if (!overwrite) {
|
||||
size_t size;
|
||||
errno_t err = getenv_s(&size, nullptr, 0, key);
|
||||
if (err != 0 || size != 0)
|
||||
return err; // Return 0 if it exists, but don't change.
|
||||
}
|
||||
return _putenv_s(key, value);
|
||||
}
|
||||
|
||||
#endif
|
||||
60
util/src/rw_lock.cpp
Normal file
60
util/src/rw_lock.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "rw_lock.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
shared_mutex::~shared_mutex() {
|
||||
if (reader_count_ > 0) {
|
||||
LOGE("shared_mutex destroyed with active readers!");
|
||||
}
|
||||
if (has_writer_) {
|
||||
LOGE("shared_mutex destroyed with an active writer!");
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex::lock_shared() {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
|
||||
while (has_writer_) {
|
||||
condition_variable_.wait(lock);
|
||||
}
|
||||
|
||||
++reader_count_;
|
||||
}
|
||||
|
||||
void shared_mutex::unlock_shared() {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
|
||||
--reader_count_;
|
||||
|
||||
if (reader_count_ == 0) {
|
||||
condition_variable_.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
bool shared_mutex::lock_implementation(bool abort_if_unavailable) {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
|
||||
while (reader_count_ > 0 || has_writer_) {
|
||||
if (abort_if_unavailable) return false;
|
||||
condition_variable_.wait(lock);
|
||||
}
|
||||
|
||||
has_writer_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void shared_mutex::unlock() {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
|
||||
has_writer_ = false;
|
||||
|
||||
condition_variable_.notify_all();
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "string_conversions.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -13,6 +12,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "log.h"
|
||||
#include "platform.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user