Updates to ref code and unit tests

This CL updates has several changes.

The document WidevineModularDRMSecurityIntegrationGuideforCENC_v14.pdf
had an incorrect definition of the PST_Report structure.  The header
file had the correct definition. This has been updated and the version
number of the document was rolled to 14.1

The unit tests TwoHundredEntries has been modifed to make sure that if
the usage table is full, then OEMCrypto will return the error
OEMCrypto_ERROR_INSUFFICIENT_RESOURCES.  This is important for the CDM
layer to correctly delete old licenses and secure stops when this
happens.

Several other unit tests covering corner cases have been added.

The reference code has been cleaned up a bit.  Some logging that might
be dangerous has been removed.
This commit is contained in:
Fred Gylys-Colwell
2018-09-19 20:27:19 -07:00
parent 61f02edda4
commit 1655d891de
54 changed files with 774 additions and 1257 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -289,6 +289,8 @@ typedef enum OEMCrypto_Usage_Entry_Status {
* Platforms that have compilers that support packed structures, may use the
* following definition. Other platforms may use the header pst_report.h which
* defines a wrapper class.
*
* All fields are in network byte order.
*/
#if 0 // If your compiler supports __attribute__((packed)).
typedef struct {
@@ -368,78 +370,87 @@ typedef enum OEMCrypto_ProvisioningMethod {
/*
* Obfuscation Renames.
*/
#define OEMCrypto_Initialize _oecc01
#define OEMCrypto_Terminate _oecc02
#define OEMCrypto_InstallKeybox _oecc03
#define OEMCrypto_GetKeyData _oecc04
#define OEMCrypto_IsKeyboxValid _oecc05
#define OEMCrypto_GetRandom _oecc06
#define OEMCrypto_GetDeviceID _oecc07
#define OEMCrypto_WrapKeybox _oecc08
#define OEMCrypto_OpenSession _oecc09
#define OEMCrypto_CloseSession _oecc10
#define OEMCrypto_DecryptCTR_V10 _oecc11
#define OEMCrypto_GenerateDerivedKeys _oecc12
#define OEMCrypto_GenerateSignature _oecc13
#define OEMCrypto_GenerateNonce _oecc14
#define OEMCrypto_LoadKeys_V8 _oecc15
#define OEMCrypto_RefreshKeys _oecc16
#define OEMCrypto_SelectKey_V13 _oecc17
#define OEMCrypto_RewrapDeviceRSAKey _oecc18
#define OEMCrypto_LoadDeviceRSAKey _oecc19
#define OEMCrypto_GenerateRSASignature_V8 _oecc20
#define OEMCrypto_DeriveKeysFromSessionKey _oecc21
#define OEMCrypto_APIVersion _oecc22
#define OEMCrypto_SecurityLevel _oecc23
#define OEMCrypto_Generic_Encrypt _oecc24
#define OEMCrypto_Generic_Decrypt _oecc25
#define OEMCrypto_Generic_Sign _oecc26
#define OEMCrypto_Generic_Verify _oecc27
#define OEMCrypto_GetHDCPCapability_V9 _oecc28
#define OEMCrypto_SupportsUsageTable _oecc29
#define OEMCrypto_UpdateUsageTable _oecc30
#define OEMCrypto_DeactivateUsageEntry_V12 _oecc31
#define OEMCrypto_ReportUsage _oecc32
#define OEMCrypto_DeleteUsageEntry _oecc33
#define OEMCrypto_DeleteOldUsageTable _oecc34
#define OEMCrypto_LoadKeys_V9_or_V10 _oecc35
#define OEMCrypto_GenerateRSASignature _oecc36
#define OEMCrypto_GetMaxNumberOfSessions _oecc37
#define OEMCrypto_GetNumberOfOpenSessions _oecc38
#define OEMCrypto_IsAntiRollbackHwPresent _oecc39
#define OEMCrypto_CopyBuffer _oecc40
#define OEMCrypto_QueryKeyControl _oecc41
#define OEMCrypto_LoadTestKeybox_V13 _oecc42
#define OEMCrypto_ForceDeleteUsageEntry _oecc43
#define OEMCrypto_GetHDCPCapability _oecc44
#define OEMCrypto_LoadTestRSAKey _oecc45
#define OEMCrypto_Security_Patch_Level _oecc46
#define OEMCrypto_LoadKeys_V11_or_V12 _oecc47
#define OEMCrypto_DecryptCENC _oecc48
#define OEMCrypto_GetProvisioningMethod _oecc49
#define OEMCrypto_GetOEMPublicCertificate _oecc50
#define OEMCrypto_RewrapDeviceRSAKey30 _oecc51
#define OEMCrypto_SupportedCertificates _oecc52
#define OEMCrypto_IsSRMUpdateSupported _oecc53
#define OEMCrypto_GetCurrentSRMVersion _oecc54
#define OEMCrypto_LoadSRM _oecc55
#define OEMCrypto_LoadKeys_V13 _oecc56
#define OEMCrypto_RemoveSRM _oecc57
#define OEMCrypto_CreateUsageTableHeader _oecc61
#define OEMCrypto_LoadUsageTableHeader _oecc62
#define OEMCrypto_CreateNewUsageEntry _oecc63
#define OEMCrypto_LoadUsageEntry _oecc64
#define OEMCrypto_UpdateUsageEntry _oecc65
#define OEMCrypto_DeactivateUsageEntry _oecc66
#define OEMCrypto_ShrinkUsageTableHeader _oecc67
#define OEMCrypto_MoveEntry _oecc68
#define OEMCrypto_CopyOldUsageEntry _oecc69
#define OEMCrypto_CreateOldUsageEntry _oecc70
#define OEMCrypto_GetAnalogOutputFlags _oecc71
#define OEMCrypto_LoadTestKeybox _oecc78
#define OEMCrypto_LoadEntitledContentKeys _oecc79
#define OEMCrypto_SelectKey _oecc81
#define OEMCrypto_LoadKeys _oecc82
#define OEMCrypto_Initialize _oecc01
#define OEMCrypto_Terminate _oecc02
#define OEMCrypto_InstallKeybox _oecc03
// Rename InstallKeybox to InstallKeyboxOrOEMCert.
#define OEMCrypto_InstallRootKeyCertificate _oecc03
#define OEMCrypto_InstallKeyboxOrOEMCert _oecc03
#define OEMCrypto_GetKeyData _oecc04
#define OEMCrypto_IsKeyboxValid _oecc05
// Rename IsKeyboxValid to IsKeyboxOrOEMCertValid.
#define OEMCrypto_IsRootKeyCertificateValid _oecc05
#define OEMCrypto_IsKeyboxOrOEMCertValid _oecc05
#define OEMCrypto_GetRandom _oecc06
#define OEMCrypto_GetDeviceID _oecc07
#define OEMCrypto_WrapKeybox _oecc08
// Rename WrapKeybox to WrapKeyboxOrOEMCert
#define OEMCrypto_WrapRootKeyCertificate _oecc08
#define OEMCrypto_WrapKeyboxOrOEMCert _oecc08
#define OEMCrypto_OpenSession _oecc09
#define OEMCrypto_CloseSession _oecc10
#define OEMCrypto_DecryptCTR_V10 _oecc11
#define OEMCrypto_GenerateDerivedKeys _oecc12
#define OEMCrypto_GenerateSignature _oecc13
#define OEMCrypto_GenerateNonce _oecc14
#define OEMCrypto_LoadKeys_V8 _oecc15
#define OEMCrypto_RefreshKeys _oecc16
#define OEMCrypto_SelectKey_V13 _oecc17
#define OEMCrypto_RewrapDeviceRSAKey _oecc18
#define OEMCrypto_LoadDeviceRSAKey _oecc19
#define OEMCrypto_GenerateRSASignature_V8 _oecc20
#define OEMCrypto_DeriveKeysFromSessionKey _oecc21
#define OEMCrypto_APIVersion _oecc22
#define OEMCrypto_SecurityLevel _oecc23
#define OEMCrypto_Generic_Encrypt _oecc24
#define OEMCrypto_Generic_Decrypt _oecc25
#define OEMCrypto_Generic_Sign _oecc26
#define OEMCrypto_Generic_Verify _oecc27
#define OEMCrypto_GetHDCPCapability_V9 _oecc28
#define OEMCrypto_SupportsUsageTable _oecc29
#define OEMCrypto_UpdateUsageTable _oecc30
#define OEMCrypto_DeactivateUsageEntry_V12 _oecc31
#define OEMCrypto_ReportUsage _oecc32
#define OEMCrypto_DeleteUsageEntry _oecc33
#define OEMCrypto_DeleteOldUsageTable _oecc34
#define OEMCrypto_LoadKeys_V9_or_V10 _oecc35
#define OEMCrypto_GenerateRSASignature _oecc36
#define OEMCrypto_GetMaxNumberOfSessions _oecc37
#define OEMCrypto_GetNumberOfOpenSessions _oecc38
#define OEMCrypto_IsAntiRollbackHwPresent _oecc39
#define OEMCrypto_CopyBuffer _oecc40
#define OEMCrypto_QueryKeyControl _oecc41
#define OEMCrypto_LoadTestKeybox_V13 _oecc42
#define OEMCrypto_ForceDeleteUsageEntry _oecc43
#define OEMCrypto_GetHDCPCapability _oecc44
#define OEMCrypto_LoadTestRSAKey _oecc45
#define OEMCrypto_Security_Patch_Level _oecc46
#define OEMCrypto_LoadKeys_V11_or_V12 _oecc47
#define OEMCrypto_DecryptCENC _oecc48
#define OEMCrypto_GetProvisioningMethod _oecc49
#define OEMCrypto_GetOEMPublicCertificate _oecc50
#define OEMCrypto_RewrapDeviceRSAKey30 _oecc51
#define OEMCrypto_SupportedCertificates _oecc52
#define OEMCrypto_IsSRMUpdateSupported _oecc53
#define OEMCrypto_GetCurrentSRMVersion _oecc54
#define OEMCrypto_LoadSRM _oecc55
#define OEMCrypto_LoadKeys_V13 _oecc56
#define OEMCrypto_RemoveSRM _oecc57
#define OEMCrypto_CreateUsageTableHeader _oecc61
#define OEMCrypto_LoadUsageTableHeader _oecc62
#define OEMCrypto_CreateNewUsageEntry _oecc63
#define OEMCrypto_LoadUsageEntry _oecc64
#define OEMCrypto_UpdateUsageEntry _oecc65
#define OEMCrypto_DeactivateUsageEntry _oecc66
#define OEMCrypto_ShrinkUsageTableHeader _oecc67
#define OEMCrypto_MoveEntry _oecc68
#define OEMCrypto_CopyOldUsageEntry _oecc69
#define OEMCrypto_CreateOldUsageEntry _oecc70
#define OEMCrypto_GetAnalogOutputFlags _oecc71
#define OEMCrypto_LoadTestKeybox _oecc78
#define OEMCrypto_LoadEntitledContentKeys _oecc79
#define OEMCrypto_SelectKey _oecc81
#define OEMCrypto_LoadKeys _oecc82
/*
* OEMCrypto_Initialize
@@ -1493,36 +1504,38 @@ OEMCryptoResult OEMCrypto_CopyBuffer(const uint8_t* data_addr,
uint8_t subsample_flags);
/*
* OEMCrypto_WrapKeybox
* OEMCrypto_WrapKeyboxOrOEMCert
*
* Description:
* During manufacturing, the keybox should be encrypted with the OEM root key
* and stored on the file system in a region that will not be erased during
* factory reset. As described in section 5.5.4, the keybox may be directly
* encrypted and stored on the device in a single step, or it may use the
* two-step WrapKeybox/InstallKeybox approach. When the Widevine DRM plugin
* initializes, it will look for a wrapped keybox in the file
* /factory/wv.keys and install it into the security processor by calling
* OEMCrypto_InstallKeybox().
*
* OEMCrypto_WrapKeybox() is used to generate an OEM-encrypted keybox that
* may be passed to OEMCrypto_InstallKeybox() for provisioning. The keybox
* may be either passed in the clear or previously encrypted with a transport
* key. If a transport key is supplied, the keybox is first decrypted with
* the transport key before being wrapped with the OEM root key. This
* function is only needed if the provisioning method involves saving the
* keybox to the file system.
* A device should be provisioned at the factory with either an OEM
* Certificate or a keybox. We will call this data the root of trust. During
* manufacturing, the root of trust should be encrypted with the OEM root key
* and stored on the file system in a region that will not be erased during
* factory reset. This function may be used by legacy systems that use the
* two-step WrapKeyboxOrOEMCert/InstallKeyboxOrOEMCert approach. When
* the Widevine DRM plugin initializes, it will look for a wrapped root of
* trust in the file /factory/wv.keys and install it into the security
* processor by calling OEMCrypto_InstallKeyboxOrOEMCert().
*
* OEMCrypto_WrapKeyboxOrOEMCert() is used to generate an OEM-encrypted
* root of trust that may be passed to OEMCrypto_InstallKeyboxOrOEMCert()
* for provisioning. The root of trust may be either passed in the clear or
* previously encrypted with a transport key. If a transport key is supplied,
* the keybox is first decrypted with the transport key before being wrapped
* with the OEM root key. This function is only needed if the root of trust
* provisioning method involves saving the keybox to the file system.
*
* Parameters:
* keybox (in) - pointer to Keybox data to encrypt. May be NULL on the first
* call to test size of wrapped keybox. The keybox may either be clear or
* previously encrypted.
* keyboxLength (in) - length the keybox data in bytes
* wrappedKeybox (out) Pointer to wrapped keybox
* wrappedKeyboxLength (out) Pointer to the length of the wrapped keybox in
* rot (in) - pointer to root of trust data to encrypt. May be NULL on the
* first call to test size of wrapped keybox. The keybox may either be
* clear or previously encrypted.
* rotLength (in) - length the rot data in bytes
* wrappedRot (out) Pointer to wrapped rot
* wrappedRotLength (out) Pointer to the length of the wrapped keybox in
* bytes
* transportKey (in) Optional. AES transport key. If provided, the keybox
* parameter was previously encrypted with this key. The keybox will be
* transportKey (in) Optional. AES transport key. If provided, the rot
* parameter was previously encrypted with this key. The rot will be
* decrypted with the transport key using AES-CBC and a null IV.
* transportKeyLength (in) Optional. Number of bytes in the transportKey, if
* used.
@@ -1541,26 +1554,29 @@ OEMCryptoResult OEMCrypto_CopyBuffer(const uint8_t* data_addr,
* Version:
* This method is supported by all API versions.
*/
OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox, size_t keyBoxLength,
uint8_t* wrappedKeybox,
size_t* wrappedKeyBoxLength,
const uint8_t* transportKey,
size_t transportKeyLength);
OEMCryptoResult OEMCrypto_WrapKeyboxOrOEMCert(const uint8_t* rot, size_t rotLength,
uint8_t* wrappedRot,
size_t* wrappedRotLength,
const uint8_t* transportKey,
size_t transportKeyLength);
/*
* OEMCrypto_InstallKeybox
* OEMCrypto_InstallKeyboxOrOEMCert
*
* Description:
* Decrypts a wrapped keybox and installs it in the security processor. The
* keybox is unwrapped then encrypted with the OEM root key. This function is
* called from the Widevine DRM plugin at initialization time if there is no
* valid keybox installed. It looks for a wrapped keybox in the file
* /factory/wv.keys and if it is present, will read the file and call
* OEMCrypto_InstallKeybox() with the contents of the file.
*
* Decrypts a wrapped root of trust and installs it in the security processor.
* The root of trust is unwrapped then encrypted with the OEM root key. This
* function is called from the Widevine DRM plugin at initialization time if
* there is no valid root of trust installed. It looks for wrapped data in
* the file /factory/wv.keys and if it is present, will read the file and call
* OEMCrypto_InstallKeyboxOrOEMCert() with the contents of the file. This
* function is only needed if the factory provisioning method involves saving
* the keybox to the file system.
*
* Parameters:
* keybox (in) - pointer to encrypted Keybox data as input
* keyboxLength (in) - length of the keybox data in bytes
* rot (in) - pointer to encrypted data as input
* rotLength (in) - length of the data in bytes
*
* Threading:
* This function is not called simultaneously with any other functions.
@@ -1575,8 +1591,8 @@ OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox, size_t keyBoxLength,
* Version:
* This method is supported in all API versions.
*/
OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox,
size_t keyBoxLength);
OEMCryptoResult OEMCrypto_InstallKeyboxOrOEMCert(const uint8_t* rot,
size_t rotLength);
/*
* OEMCrypto_GetProvisioningMethod
@@ -1671,10 +1687,12 @@ OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(OEMCrypto_SESSION session,
OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t *buffer, size_t length);
/*
* OEMCrypto_IsKeyboxValid
* OEMCrypto_IsKeyboxOrOEMCertValid
*
* Description:
* Validate the Widevine Keybox stored on the device.
*
* If the device has a keybox, this validates the Widevine Keybox loaded into
* the security processor device.
*
* The API performs two verification steps on the Keybox. It first verifies
* the MAGIC field contains a valid signature (must be 'kbox'). The API then
@@ -1682,6 +1700,9 @@ OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t *buffer, size_t length);
* checksum to the CRC stored in the Keybox. The CRC is computed over the
* entire Keybox excluding the 4 CRC bytes (i.e. Keybox[0..123]).
*
* If the device has an OEM Certificate, this validates the certificate private
* key.
*
* Parameters:
* none
*
@@ -1692,11 +1713,13 @@ OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t *buffer, size_t length);
* OEMCrypto_SUCCESS
* OEMCrypto_ERROR_BAD_MAGIC
* OEMCrypto_ERROR_BAD_CRC
* OEMCrypto_ERROR_KEYBOX_INVALID
* OEMCrypto_ERROR_NOT_IMPLEMENTED
*
* Version:
* This method is supported by all API versions.
*/
OEMCryptoResult OEMCrypto_IsKeyboxValid(void);
OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void);
/*
* OEMCrypto_GetDeviceID

View File

@@ -1,5 +1,5 @@
# Reference OEMCrypto
This directory contains a testing-only implementation of OEMCrypto. **This
implementation is *NOT* suitable for production use and should *NOT* be released
implementation is *NOT* suitable for production use and must *NOT* be released
on devices.**

View File

@@ -31,8 +31,6 @@
'<(oemcrypto_dir)/ref/src/wvcrc.cpp',
# TODO(fredgc) remove these:
'<(oemcrypto_dir)/ref/src/oemcrypto_logging.cpp',
'<(oemcrypto_dir)/ref/src/oemcrypto_keybox_testkey.cpp',
'<(oemcrypto_dir)/ref/src/oemcrypto_engine_device_properties.cpp',
],
'dependencies': [

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_auth_ref.h"
@@ -10,14 +10,13 @@
#include "keys.h"
#include "log.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_rsa_key_shared.h"
namespace {
// A 2048 bit RSA key in PKCS#8 PrivateKeyInfo format
// This is the RSA Test Key.
// This is the RSA Test Key. This key is not derived
// from any Widevine authentication root.
static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = {
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#ifndef OEMCRYPTO_AUTH_REF_H_
#define OEMCRYPTO_AUTH_REF_H_
@@ -67,7 +67,7 @@ class AuthenticationRoot {
WvKeybox& real_keybox() { return keybox_; }
WvKeybox keybox_;
WvTestKeybox test_keybox_;
WvKeybox test_keybox_;
bool use_test_keybox_;
RSA_shared_ptr rsa_key_; // If no keybox, this is baked in certificate.

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_engine_ref.h"

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
// This file contains oemcrypto engine properties that would be for a
// level 1 device.

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
// This file contains oemcrypto engine properties that would be for a device
// that does not have persistant storage or a keybox.

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
// This file contains oemcrypto engine properties that would be for a
// level 2 device that does not have persistant storage or a keybox.

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_engine_ref.h"
@@ -30,7 +30,7 @@ namespace wvoec_ref {
CryptoEngine::CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system)
: root_of_trust_(config_provisioning_method()),
file_system_(file_system),
usage_table_(this) {
usage_table_(NULL) {
ERR_load_crypto_strings();
}
@@ -44,16 +44,25 @@ CryptoEngine::~CryptoEngine() {
ERR_free_strings();
}
SessionId CryptoEngine::CreateSession() {
wvcdm::AutoLock lock(session_table_lock_);
static int unique_id = 1;
SessionId sid = (SessionId)++unique_id;
SessionContext* sctx =
new SessionContext(this, sid, root_of_trust_.SharedRsaKey());
sessions_[sid] = sctx;
return sid;
bool CryptoEngine::Initialize() {
usage_table_.reset(MakeUsageTable());
return true;
}
SessionId CryptoEngine::OpenSession() {
wvcdm::AutoLock lock(session_table_lock_);
static OEMCrypto_SESSION unique_id = 1;
SessionId id = ++unique_id;
sessions_[id] = MakeSession(id);
return id;
}
SessionContext* CryptoEngine::MakeSession(SessionId sid) {
return new SessionContext(this, sid, root_of_trust_.SharedRsaKey());
}
UsageTable* CryptoEngine::MakeUsageTable() { return new UsageTable(this); }
bool CryptoEngine::DestroySession(SessionId sid) {
SessionContext* sctx = FindSession(sid);
wvcdm::AutoLock lock(session_table_lock_);

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#ifndef REF_OEMCRYPTO_ENGINE_REF_H_
#define REF_OEMCRYPTO_ENGINE_REF_H_
@@ -15,7 +15,7 @@
#include <openssl/rsa.h>
#include "OEMCryptoCENC.h" // Needed for enums only.
#include "OEMCryptoCENC.h"
#include "file_store.h"
#include "lock.h"
#include "oemcrypto_auth_ref.h"
@@ -42,7 +42,7 @@ class CryptoEngine {
virtual ~CryptoEngine();
virtual bool Initialize() { return true; }
virtual bool Initialize();
bool ValidRootOfTrust() { return root_of_trust_.Validate(); }
@@ -58,8 +58,8 @@ class CryptoEngine {
KeyboxError ValidateKeybox() { return root_of_trust_.ValidateKeybox(); }
const std::vector<uint8_t>& DeviceRootKey(bool override_to_real = false) {
return root_of_trust_.DeviceKey(override_to_real);
const std::vector<uint8_t>& DeviceRootKey() {
return root_of_trust_.DeviceKey();
}
const std::vector<uint8_t>& DeviceRootId() {
@@ -74,7 +74,7 @@ class CryptoEngine {
virtual void Terminate() {}
SessionId CreateSession();
virtual SessionId OpenSession();
bool DestroySession(SessionId sid);
@@ -94,7 +94,21 @@ class CryptoEngine {
// Returns the max HDCP version supported.
virtual OEMCrypto_HDCP_Capability config_maximum_hdcp_capability();
UsageTable& usage_table() { return usage_table_; }
// Return true if there might be analog video output enabled.
virtual bool analog_display_active() {
return !config_local_display_only();
}
// Return true if there is an analog display, and CGMS A is turned on.
virtual bool cgms_a_active() { return false; }
// Return the analog output flags.
virtual uint32_t analog_output_flags() {
return config_local_display_only() ? OEMCrypto_No_Analog_Output
: OEMCrypto_Supports_Analog_Output;
}
UsageTable& usage_table() { return *(usage_table_.get()); }
wvcdm::FileSystem* file_system() { return file_system_.get(); }
// If config_local_display_only() returns true, we pretend we are using a
@@ -152,6 +166,10 @@ class CryptoEngine {
// Rate limit for nonce generation. Default to 20 nonce/second.
virtual int nonce_flood_count() { return 20; }
// Limit for size of usage table. If this is zero, then the
// size is unlimited -- or limited only by memory size.
virtual size_t max_usage_table_size() { return 0; }
// Set destination pointer based on the output destination description.
OEMCryptoResult SetDestination(OEMCrypto_DestBufferDesc* out_description,
size_t data_length, uint8_t subsample_flags);
@@ -172,14 +190,14 @@ class CryptoEngine {
protected:
explicit CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system);
virtual SessionContext* MakeSession(SessionId sid);
virtual UsageTable* MakeUsageTable();
uint8_t* destination_;
private:
ActiveSessions sessions_;
AuthenticationRoot root_of_trust_;
wvcdm::Lock session_table_lock_;
scoped_ptr<wvcdm::FileSystem> file_system_;
UsageTable usage_table_;
scoped_ptr<UsageTable> usage_table_;
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
};

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_key_ref.h"
#include "oemcrypto_types.h"
@@ -11,7 +11,6 @@
#include <vector>
#include "log.h"
#include "oemcrypto_logging.h"
namespace wvoec_ref {
@@ -55,61 +54,6 @@ KeyControlBlock::KeyControlBlock(
duration_ = ExtractField(key_control_string, 1);
nonce_ = ExtractField(key_control_string, 2);
control_bits_ = ExtractField(key_control_string, 3);
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("KCB:");
LOGD(" valid: %d", valid());
LOGD(" duration: %d", duration());
LOGD(" nonce: %08X", nonce());
LOGD(" magic: %08X", verification());
LOGD(" bits: %08X", control_bits());
LOGD(" bit kSharedLicense %s.",
(control_bits() & wvoec::kSharedLicense) ? "set" : "unset");
LOGD(" bit kControlSRMVersionRequired %s.",
(control_bits() & wvoec::kControlSRMVersionRequired) ? "set" : "unset");
LOGD(" bit kControlDisableAnalogOutput %s.",
(control_bits() & wvoec::kControlDisableAnalogOutput) ? "set"
: "unset");
LOGD(" bits kControlSecurityPatchLevel 0x%02x.",
(control_bits() & wvoec::kControlSecurityPatchLevelMask) >>
wvoec::kControlSecurityPatchLevelShift);
switch (control_bits() & wvoec::kControlReplayMask) {
case wvoec::kControlNonceRequired:
LOGD(" bits kControlReplay kControlNonceRequired.");
break;
case wvoec::kControlNonceOrEntry:
LOGD(" bits kControlReplay kControlNonceOrEntry.");
break;
default:
LOGD(" bits kControlReplay unset.");
break;
}
LOGD(" bits kControlHDCPVersion 0x%02x.",
(control_bits() & wvoec::kControlHDCPVersionMask) >>
wvoec::kControlHDCPVersionShift);
LOGD(" bit kControlAllowEncrypt %s.",
(control_bits() & wvoec::kControlAllowEncrypt) ? "set" : "unset");
LOGD(" bit kControlAllowDecrypt %s.",
(control_bits() & wvoec::kControlAllowDecrypt) ? "set" : "unset");
LOGD(" bit kControlAllowSign %s.",
(control_bits() & wvoec::kControlAllowSign) ? "set" : "unset");
LOGD(" bit kControlAllowVerify %s.",
(control_bits() & wvoec::kControlAllowVerify) ? "set" : "unset");
LOGD(" bit kControlObserveDataPath %s.",
(control_bits() & wvoec::kControlObserveDataPath) ? "set" : "unset");
LOGD(" bit kControlObserveHDCP %s.",
(control_bits() & wvoec::kControlObserveHDCP) ? "set" : "unset");
LOGD(" bit kControlObserveCGMS %s.",
(control_bits() & wvoec::kControlObserveCGMS) ? "set" : "unset");
LOGD(" bit kControlDataPathSecure %s.",
(control_bits() & wvoec::kControlDataPathSecure) ? "set" : "unset");
LOGD(" bit kControlNonceEnabled %s.",
(control_bits() & wvoec::kControlNonceEnabled) ? "set" : "unset");
LOGD(" bit kControlHDCPRequired %s.",
(control_bits() & wvoec::kControlHDCPRequired) ? "set" : "unset");
uint32_t cgms_bits = control_bits() & 0x3;
const char* cgms_values[4] = {"free", "BAD", "once", "never"};
LOGD(" CGMS = %s", cgms_values[cgms_bits]);
}
Validate();
}

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#ifndef OEMCRYPTO_KEY_REF_H_
#define OEMCRYPTO_KEY_REF_H_

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_keybox_ref.h"
@@ -10,54 +10,17 @@
#include <string.h>
#include <sys/types.h>
#include <string>
#include "log.h"
#include "oemcrypto_types.h"
#include "wvcrc32.h"
namespace wvoec_ref {
namespace {
const wvoec::WidevineKeybox kTestKeybox = {
// Sample keybox used for test vectors
{
// deviceID
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey01
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
}, {
// key
0xfb, 0xda, 0x04, 0x89, 0xa1, 0x58, 0x16, 0x0e,
0xa4, 0x02, 0xe9, 0x29, 0xe3, 0xb6, 0x8f, 0x04,
}, {
// data
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1,
0x22, 0x67, 0x80, 0x53, 0x36, 0x21, 0x36, 0xbd,
0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4, 0xc2, 0xd8,
0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64,
0x6e, 0x58, 0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8,
0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a, 0x14, 0xa8,
0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64,
0x0b, 0xd2, 0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39,
}, {
// magic
0x6b, 0x62, 0x6f, 0x78,
}, {
// Crc
0x0a, 0x7a, 0x2c, 0x35,
}
};
} // namespace
WvKeybox::WvKeybox() {
valid_ = Prepare();
}
WvKeybox::WvKeybox() : loaded_(false) {}
KeyboxError WvKeybox::Validate() {
if (!valid_) {
if (!loaded_) {
LOGE("[KEYBOX NOT LOADED]");
return OTHER_ERROR;
}
@@ -67,7 +30,7 @@ KeyboxError WvKeybox::Validate() {
}
uint32_t crc_computed;
uint32_t crc_stored;
uint8_t* crc_stored_bytes = (uint8_t*) &crc_stored;
uint8_t* crc_stored_bytes = (uint8_t*)&crc_stored;
memcpy(crc_stored_bytes, crc_, sizeof(crc_));
wvoec::WidevineKeybox keybox;
memset(&keybox, 0, sizeof(keybox));
@@ -90,25 +53,18 @@ bool WvKeybox::InstallKeybox(const uint8_t* buffer, size_t keyBoxLength) {
if (keyBoxLength != 128) {
return false;
}
const wvoec::WidevineKeybox* keybox
= reinterpret_cast<const wvoec::WidevineKeybox*>(buffer);
size_t device_id_length
= strnlen(reinterpret_cast<const char*>(keybox->device_id_), 32);
device_id_.assign(keybox->device_id_,
keybox->device_id_ + device_id_length);
const wvoec::WidevineKeybox* keybox =
reinterpret_cast<const wvoec::WidevineKeybox*>(buffer);
size_t device_id_length =
strnlen(reinterpret_cast<const char*>(keybox->device_id_), 32);
device_id_.assign(keybox->device_id_, keybox->device_id_ + device_id_length);
device_key_.assign(keybox->device_key_,
keybox->device_key_ + sizeof(keybox->device_key_));
memcpy(key_data_, keybox->data_, sizeof(keybox->data_));
memcpy(magic_, keybox->magic_, sizeof(keybox->magic_));
memcpy(crc_, keybox->crc_, sizeof(keybox->crc_));
loaded_ = true;
return true;
}
WvTestKeybox::WvTestKeybox() {
InstallKeybox(reinterpret_cast<const uint8_t*>(&kTestKeybox),
sizeof(kTestKeybox));
}
} // namespace wvoec_ref

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#ifndef OEMCRYPTO_KEYBOX_REF_H_
#define OEMCRYPTO_KEYBOX_REF_H_
@@ -33,9 +33,7 @@ class WvKeybox {
bool InstallKeybox(const uint8_t* keybox, size_t keyBoxLength);
private:
bool Prepare();
bool valid_;
bool loaded_;
std::vector<uint8_t> device_id_;
std::vector<uint8_t> device_key_;
WvKeyboxKeyData key_data_;
@@ -43,11 +41,6 @@ class WvKeybox {
uint8_t crc_[4];
};
class WvTestKeybox : public WvKeybox {
public:
WvTestKeybox();
};
} // namespace wvoec_ref
#endif // OEMCRYPTO_KEYBOX_REF_H_

View File

@@ -1,56 +0,0 @@
// 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.
//
// Test keybox.
#include "oemcrypto_keybox_ref.h"
#include "oemcrypto_types.h"
namespace wvoec_ref {
namespace {
// Note: this is a valid keybox, but it is not accepted by production servers.
// However, it is different from the one used for most of the unit tests.
const wvoec::WidevineKeybox kKeybox = {
// Sample keybox used for test vectors
{
// deviceID
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey02
0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
}, {
// key
0x76, 0x5d, 0xce, 0x01, 0x04, 0x89, 0xb3, 0xd0,
0xdf, 0xce, 0x54, 0x8a, 0x49, 0xda, 0xdc, 0xb6,
}, {
// data
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
0x92, 0x27, 0x0b, 0x1f, 0x1a, 0xd5, 0xc6, 0x93,
0x19, 0x3f, 0xaa, 0x74, 0x1f, 0xdd, 0x5f, 0xb4,
0xe9, 0x40, 0x2f, 0x34, 0xa4, 0x92, 0xf4, 0xae,
0x9a, 0x52, 0x39, 0xbc, 0xb7, 0x24, 0x38, 0x13,
0xab, 0xf4, 0x92, 0x96, 0xc4, 0x81, 0x60, 0x33,
0xd8, 0xb8, 0x09, 0xc7, 0x55, 0x0e, 0x12, 0xfa,
0xa8, 0x98, 0x62, 0x8a, 0xec, 0xea, 0x74, 0x8a,
0x4b, 0xfa, 0x5a, 0x9e, 0xb6, 0x49, 0x0d, 0x80,
}, {
// magic
0x6b, 0x62, 0x6f, 0x78,
}, {
// Crc
0x2a, 0x3b, 0x3e, 0xe4,
}
};
} // namespace
bool WvKeybox::Prepare() {
InstallKeybox(reinterpret_cast<const uint8_t*>(&kKeybox),
sizeof(kKeybox));
return true;
}
} // namespace wvoec_ref

View File

@@ -1,106 +0,0 @@
// 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 "oemcrypto_logging.h"
#include <stdio.h>
namespace wvoec_ref {
int logging_category_setting = 0x00;
void SetLoggingSettings(int level, int categories) {
SetLoggingLevel(level);
TurnOffLoggingForAllCategories();
AddLoggingForCategories(categories);
}
void TurnOffLoggingForAllCategories() { logging_category_setting = 0; }
void SetLoggingLevel(int level) {
wvcdm::g_cutoff = static_cast<wvcdm::LogPriority>(level);
}
void SetLoggingLevel(wvcdm::LogPriority level) { wvcdm::g_cutoff = level; }
void AddLoggingForCategories(int categories) {
logging_category_setting |= categories;
}
void RemoveLoggingForCategories(int categories) {
logging_category_setting &= ~categories;
}
bool LogCategoryEnabled(int categories) {
return ((logging_category_setting & categories) != 0);
}
void dump_hex_helper(std::string& buffer, std::string name,
const uint8_t* vector, size_t length) {
buffer += name + " = ";
if (vector == NULL) {
buffer += "NULL;\n";
LOGE(buffer.c_str());
return;
}
int a, b;
char int_to_hexcar[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
for (size_t i = 0; i < length; i++) {
if (i == 0) {
buffer += "\n a2b_hex(\"";
} else if (i % 32 == 0) {
buffer += "\"\n \"";
}
a = vector[i] % 16;
b = (vector[i] - a) / 16;
buffer += int_to_hexcar[b];
buffer += int_to_hexcar[a];
}
buffer += "\");\n";
}
void dump_hex(std::string name, const uint8_t* vector, size_t length) {
std::string buffer = "";
dump_hex_helper(buffer, name, vector, length);
LOGV(buffer.c_str());
}
void dump_array_part_helper(std::string& buffer, std::string array,
size_t index, std::string name,
const uint8_t* vector, size_t length) {
char index_str[256];
snprintf(index_str, sizeof index_str, "%zu", index);
if (vector == NULL) {
buffer += array.c_str();
buffer += "[";
buffer += index_str;
buffer += "].";
buffer += name.c_str();
buffer += " = NULL;\n";
LOGW(buffer.c_str());
return;
}
buffer += "std::string s";
buffer += index_str;
buffer += "_";
dump_hex_helper(buffer, name, vector, length);
buffer += array.c_str();
buffer += "[";
buffer += index_str;
buffer += "]." + name + " = message_ptr + message.find(s";
buffer += index_str;
buffer += "_" + name + ".data());\n";
}
void dump_array_part(std::string array, size_t index, std::string name,
const uint8_t* vector, size_t length) {
std::string buffer = "";
dump_array_part_helper(buffer, array, index, name, vector, length);
LOGV(buffer.c_str());
}
} // namespace wvoec_ref

View File

@@ -1,67 +0,0 @@
// 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.
#ifndef WVOEC_OEMCRYPTO_LOGGING_H_
#define WVOEC_OEMCRYPTO_LOGGING_H_
#include <iostream>
#include <string>
#include "OEMCryptoCENC.h"
#include "log.h"
namespace wvoec_ref {
// The constants below represent integers with a single "on" bit that
// represents categories of logging This allows users to specify with
// more precision what they want to log. LogCategoryEnabled(category)
// is used to see if the category passed in the parameters is to
// be logged based on the current settings. Categories can be combines
// using the | (or) bitwise operator. For example
// LogCategoryEnabled(category1 | category2) will return true if
// category1 and/or category2 are set to logging.
const int kLoggingTraceOEMCryptoCalls = 0x01; // All except decrypt calls.
const int kLoggingDumpContentKeys = 0x02;
const int kLoggingDumpKeyControlBlocks = 0x04;
const int kLoggingDumpDerivedKeys = 0x08;
const int kLoggingTraceNonce = 0x10;
const int kLoggingTraceDecryption = 0x20;
const int kLoggingTraceUsageTable = 0x40;
const int kLoggingTraceDecryptCalls = 0x80;
const int kLoggingDumpTraceAll = 0xFF;
void SetLoggingSettings(int level, int categories);
// set level of logging
void SetLoggingLevel(int level);
void TurnOffLoggingForAllCategories();
// Returns true if the category passed is set to logging.
// Returns false otherwise. The category constant declared
// above are passed.
bool LogCategoryEnabled(int category);
// Turn on logging for the categories passed.
void AddLoggingForCategories(int categories);
// Turn off logging for the categories passed.
void RemoveLoggingForCategories(int categories);
void dump_hex_helper(std::string& buffer, std::string name,
const uint8_t* vector, size_t length);
void dump_hex(std::string name, const uint8_t* vector, size_t length);
void dump_array_part_helper(std::string& buffer, std::string array,
size_t index, std::string name,
const uint8_t* vector, size_t length);
void dump_array_part(std::string array, size_t index, std::string name,
const uint8_t* vector, size_t length);
} // namespace wvoec_ref
#endif

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_nonce_table.h"

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#ifndef REF_OEMCRYPTO_NONCE_TABLE_H_
#define REF_OEMCRYPTO_NONCE_TABLE_H_

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
// This is from the v12 version of oemcrypto usage tables. It is used for
// devices that upgrade from v12 to v13 in the field, and need to convert from
@@ -23,7 +23,6 @@
#include "file_store.h"
#include "log.h"
#include "oemcrypto_engine_ref.h"
#include "oemcrypto_logging.h"
// TODO(fredgc): Setting the device files base bath is currently broken as
// wvcdm::Properties is no longer used by the reference code.
//#include "properties.h"
@@ -72,9 +71,6 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
}*/
std::string filename = path + "UsageTable.dat";
if (!file_system->Exists(filename)) {
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
LOGI("OldUsageTable: No saved usage table. Creating new table.");
}
return;
}
@@ -98,8 +94,7 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
// This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox key.
const bool override_to_real = true;
const std::vector<uint8_t> &key = ce_->DeviceRootKey(override_to_real);
const std::vector<uint8_t> &key = ce_->DeviceRootKey();
uint8_t computed_signature[SHA256_DIGEST_LENGTH];
unsigned int sig_length = sizeof(computed_signature);
@@ -144,16 +139,8 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
}
file->Read(reinterpret_cast<char *>(&generation_), sizeof(int64_t));
file->Close();
if (stored_table->generation == generation_ + 1) {
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
LOGW("OldUsageTable: File is one generation old. Acceptable rollback.");
}
} else if (stored_table->generation == generation_ - 1) {
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
LOGW("OldUsageTable: File is one generation new. Acceptable rollback.");
}
// This might happen if the generation number was rolled back?
} else if (stored_table->generation != generation_) {
if ((stored_table->generation > generation_ + 1) ||
(stored_table->generation < generation_ - 1)) {
LOGE("OldUsageTable: Rollback detected. Clearing Usage Table. %lx -> %lx",
generation_, stored_table->generation);
table_.clear();
@@ -168,9 +155,6 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
new OldUsageTableEntry(&stored_table->entries[i].entry);
table_[entry->pst_hash()] = entry;
}
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
LOGI("OldUsageTable: loaded %d entries.", stored_table->count);
}
}
OldUsageTableEntry *OldUsageTable::FindEntry(const std::vector<uint8_t> &pst) {

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
// This is from the v12 version of oemcrypto usage tables. It is used for
// devices that upgrade from v12 to v13 in the field, and need to convert from

View File

@@ -23,7 +23,6 @@
#include "file_store.h"
#include "log.h"
#include "oemcrypto_engine_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_session.h"
#include "oemcrypto_usage_table_ref.h"
#include "string_conversions.h"
@@ -58,9 +57,6 @@ typedef struct {
} WrappedRSAKey;
extern "C" OEMCryptoResult OEMCrypto_Initialize(void) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("------------------------- OEMCrypto_Initialize(void)\n");
}
if (crypto_engine) {
LOGE("------------------------- Calling Initialize without Terminate\n");
delete crypto_engine;
@@ -75,17 +71,10 @@ extern "C" OEMCryptoResult OEMCrypto_Initialize(void) {
LOGE("[OEMCrypto_Initialize(): failed]");
return OEMCrypto_ERROR_INIT_FAILED;
}
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_Initialize(): success]");
}
return OEMCrypto_SUCCESS;
}
extern "C" OEMCryptoResult OEMCrypto_Terminate(void) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("----------------- OEMCryptoResult OEMCrypto_Terminate(void)\n");
}
if (!crypto_engine) {
LOGE("[OEMCrypto_Terminate(): not initialized]");
return OEMCrypto_ERROR_TERMINATE_FAILED;
@@ -94,18 +83,10 @@ extern "C" OEMCryptoResult OEMCrypto_Terminate(void) {
delete crypto_engine;
crypto_engine = NULL;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_Terminate(): success]");
}
return OEMCrypto_SUCCESS;
}
extern "C" OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI(
"-- OEMCryptoResult OEMCrypto_OpenSession"
"(OEMCrypto_SESSION *session)\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_OpenSession: OEMCrypto not initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -115,33 +96,19 @@ extern "C" OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) {
LOGE("[OEMCrypto_OpenSession(): failed due to too many sessions]");
return OEMCrypto_ERROR_TOO_MANY_SESSIONS;
}
SessionId sid = crypto_engine->CreateSession();
SessionId sid = crypto_engine->OpenSession();
*session = (OEMCrypto_SESSION)sid;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_OpenSession(): SID=%08x]", sid);
}
return OEMCrypto_SUCCESS;
}
extern "C" OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI(
"-- OEMCryptoResult OEMCrypto_CloseSession"
"(OEMCrypto_SESSION session)\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_CloseSession: OEMCrypto not initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!crypto_engine->DestroySession((SessionId)session)) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_CloseSession(SID=%08X): failed]", session);
}
return OEMCrypto_ERROR_CLOSE_SESSION_FAILED;
} else {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_CloseSession(SID=%08X): success]", session);
}
return OEMCrypto_SUCCESS;
}
}
@@ -150,15 +117,6 @@ extern "C" 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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GenerateDerivedKeys(\n");
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("mac_key_context", mac_key_context,
(size_t)mac_key_context_length);
dump_hex("enc_key_context", enc_key_context,
(size_t)enc_key_context_length);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_GenerateDerivedKeys: OEMCrypto not initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -187,16 +145,6 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
enc_ctx_str)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("mac_key_server", &session_ctx->mac_key_server()[0],
session_ctx->mac_key_server().size());
dump_hex("mac_key_client", &session_ctx->mac_key_client()[0],
session_ctx->mac_key_client().size());
dump_hex("enc_key", &session_ctx->encryption_key()[0],
session_ctx->encryption_key().size());
}
}
return OEMCrypto_SUCCESS;
}
@@ -209,11 +157,6 @@ static uint64_t TimeStamp(void) {
extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
uint32_t* nonce) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI(
"-- OEMCryptoResult OEMCrypto_GenerateNonce"
"(OEMCrypto_SESSION session,\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_GenerateNonce: OEMCrypto not initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -252,21 +195,12 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
}
session_ctx->AddNonce(nonce_value);
*nonce = nonce_value;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("nonce = %08x\n", nonce_value);
}
return OEMCrypto_SUCCESS;
}
extern "C" OEMCryptoResult OEMCrypto_GenerateSignature(
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
uint8_t* signature, size_t* signature_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GenerateSignature(\n");
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("message", message, message_length);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_GenerateSignature: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -291,11 +225,6 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateSignature(
if (session_ctx->GenerateSignature(message, message_length, signature,
signature_length)) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("signature", signature, *signature_length);
}
}
return OEMCrypto_SUCCESS;
}
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -319,49 +248,20 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
LOGE("OEMCrypto_LoadKeys: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session,\n");
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("message", message, message_length);
dump_hex("signature", signature, signature_length);
dump_hex("enc_mac_key_iv", enc_mac_key_iv, wvoec::KEY_IV_SIZE);
dump_hex("enc_mac_keys", enc_mac_keys, 2 * wvoec::MAC_KEY_SIZE);
dump_hex("pst", pst, pst_length);
dump_hex("srm_requirement", srm_requirement, wvoec::KEY_CONTROL_SIZE);
for (size_t i = 0; i < num_keys; i++) {
LOGV("key_array[%zu].key_id_length=%zu;\n", i,
key_array[i].key_id_length);
dump_array_part("key_array", i, "key_id", key_array[i].key_id,
key_array[i].key_id_length);
dump_array_part("key_array", i, "key_data_iv", key_array[i].key_data_iv,
wvoec::KEY_IV_SIZE);
dump_array_part("key_array", i, "key_data", key_array[i].key_data,
key_array[i].key_data_length);
dump_array_part("key_array", i, "key_control_iv",
key_array[i].key_control_iv, wvoec::KEY_IV_SIZE);
dump_array_part("key_array", i, "key_control", key_array[i].key_control,
wvoec::KEY_IV_SIZE);
}
}
}
if (!crypto_engine->ValidRootOfTrust()) {
LOGE("[OEMCrypto_LoadKeys(): ERROR_KEYBOX_INVALID]");
return OEMCrypto_ERROR_KEYBOX_INVALID;
}
SessionContext* session_ctx = crypto_engine->FindSession(session);
if (!session_ctx || !session_ctx->isValid()) {
LOGE("[OEMCrypto_LoadKeys(): ERROR_INVALID_SESSION]");
return OEMCrypto_ERROR_INVALID_SESSION;
}
if (message == NULL || message_length == 0 || signature == NULL ||
signature_length == 0 || key_array == NULL || num_keys == 0) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
// Later on, we use pst_length to verify the the pst is valid. This makes
// sure that we aren't given a null string but told it has postiive length.
if (pst == NULL && pst_length > 0) {
@@ -434,9 +334,6 @@ extern "C" 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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_RefreshKeys(num_keys=%zu)\n", num_keys);
}
if (!crypto_engine) {
LOGE("OEMCrypto_RefreshKeys: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -524,10 +421,6 @@ extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
extern "C" 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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_QueryKeyControl(%d, id=%s)", session,
wvcdm::HexEncode(key_id, key_id_length).c_str());
}
if (!crypto_engine) {
LOGE("OEMCrypto_QueryKeyControl: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -563,10 +456,6 @@ extern "C" OEMCryptoResult OEMCrypto_QueryKeyControl(
extern "C" OEMCryptoResult OEMCrypto_SelectKey(
const OEMCrypto_SESSION session, const uint8_t* key_id,
size_t key_id_length, OEMCryptoCipherMode cipher_mode) {
if (LogCategoryEnabled(kLoggingTraceDecryptCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_SelectKey(%d, id=%s)", session,
wvcdm::HexEncode(key_id, key_id_length).c_str());
}
#ifndef NDEBUG
if (!crypto_engine->ValidRootOfTrust()) {
LOGE("[OEMCrypto_SelectKey(): ERROR_KEYBOX_INVALID]");
@@ -590,9 +479,6 @@ extern "C" 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 (LogCategoryEnabled(kLoggingTraceDecryptCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_DecryptCENC(%d)", session);
}
if (!crypto_engine) {
LOGE("OEMCrypto_DecryptCENC: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -638,9 +524,6 @@ extern "C" OEMCryptoResult OEMCrypto_DecryptCENC(
extern "C" OEMCryptoResult OEMCrypto_CopyBuffer(
const uint8_t* data_addr, size_t data_length,
OEMCrypto_DestBufferDesc* out_buffer, uint8_t subsample_flags) {
if (LogCategoryEnabled(kLoggingTraceDecryptCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CopyBuffer(..)\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_CopyBuffer: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -660,20 +543,15 @@ extern "C" OEMCryptoResult OEMCrypto_CopyBuffer(
crypto_engine->SetDestination(out_buffer, data_length, subsample_flags);
if (status != OEMCrypto_SUCCESS) return status;
if (crypto_engine->destination() != NULL) {
memcpy(crypto_engine->destination(), data_addr, data_length);
memmove(crypto_engine->destination(), data_addr, data_length);
}
return crypto_engine->PushDestination(out_buffer, subsample_flags);
}
extern "C" OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox,
size_t keyBoxLength,
uint8_t* wrappedKeybox,
size_t* wrappedKeyBoxLength,
const uint8_t* transportKey,
size_t transportKeyLength) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox,\n");
}
extern "C" OEMCryptoResult OEMCrypto_WrapKeyboxOrOEMCert(
const uint8_t* keybox, size_t keyBoxLength, uint8_t* wrappedKeybox,
size_t* wrappedKeyBoxLength, const uint8_t* transportKey,
size_t transportKeyLength) {
if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) {
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
@@ -687,13 +565,10 @@ extern "C" OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox,
return OEMCrypto_SUCCESS;
}
extern "C" OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox,
size_t keyBoxLength) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t *keybox,\n");
}
extern "C" OEMCryptoResult OEMCrypto_InstallKeyboxOrOEMCert(
const uint8_t* keybox, size_t keyBoxLength) {
if (!crypto_engine) {
LOGE("OEMCrypto_InstallKeybox: OEMCrypto Not Initialized.");
LOGE("OEMCrypto_InstallKeyboxOrOEMCert: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) {
@@ -707,9 +582,6 @@ extern "C" OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox,
extern "C" OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer,
size_t length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadTestKeybox()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_LoadTestKeybox: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -721,34 +593,39 @@ extern "C" OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer,
return OEMCrypto_SUCCESS;
}
extern "C" OEMCryptoResult OEMCrypto_IsKeyboxValid(void) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_IsKeyboxValid(void) {\n");
}
extern "C" OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void) {
if (!crypto_engine) {
LOGE("OEMCrypto_IsKeyboxValid: OEMCrypto Not Initialized.");
LOGE("OEMCrypto_IsKeyboxOrOEMCertValid: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) {
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
switch (crypto_engine->ValidateKeybox()) {
case NO_ERROR:
switch (crypto_engine->config_provisioning_method()) {
case OEMCrypto_DrmCertificate:
return OEMCrypto_SUCCESS;
case BAD_CRC:
return OEMCrypto_ERROR_BAD_CRC;
case BAD_MAGIC:
return OEMCrypto_ERROR_BAD_MAGIC;
case OEMCrypto_Keybox:
switch (crypto_engine->ValidateKeybox()) {
case NO_ERROR:
return OEMCrypto_SUCCESS;
case BAD_CRC:
return OEMCrypto_ERROR_BAD_CRC;
case BAD_MAGIC:
return OEMCrypto_ERROR_BAD_MAGIC;
default:
case OTHER_ERROR:
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
break;
case OEMCrypto_OEMCertificate:
// TODO(fredgc): verify that the certificate exists and is valid.
return OEMCrypto_SUCCESS;
break;
default:
case OTHER_ERROR:
LOGE("Invalid provisioning method: %d.",
crypto_engine->config_provisioning_method());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
extern "C" OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod()");
}
if (!crypto_engine) {
LOGE("OEMCrypto_GetProvisioningMethod: OEMCrypto Not Initialized.");
return OEMCrypto_ProvisioningError;
@@ -759,10 +636,6 @@ extern "C" OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod() {
extern "C" OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(
OEMCrypto_SESSION session, uint8_t* public_cert,
size_t* public_cert_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(%d) {\n",
session);
}
if (!crypto_engine) {
LOGE("OEMCrypto_GetOEMPublicCertificate: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -783,9 +656,6 @@ extern "C" OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(
extern "C" OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
size_t* idLength) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_GetDeviceID: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -810,17 +680,11 @@ extern "C" OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
memset(deviceID, 0, *idLength);
memcpy(deviceID, &dev_id_string[0], dev_id_len);
*idLength = dev_id_len;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_GetDeviceId(): success]");
}
return OEMCrypto_SUCCESS;
}
extern "C" OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
size_t* keyDataLength) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_GetKeyData: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -845,17 +709,11 @@ extern "C" OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
memset(keyData, 0, *keyDataLength);
memcpy(keyData, crypto_engine->DeviceRootToken(), length);
*keyDataLength = length;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_GetKeyData(): success]");
}
return OEMCrypto_SUCCESS;
}
extern "C" OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
size_t dataLength) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetRandom");
}
if (!randomData) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
@@ -872,20 +730,8 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
const uint8_t* enc_rsa_key_iv, uint8_t* wrapped_rsa_key,
size_t* wrapped_rsa_key_length) {
uint32_t nonce = unaligned_dereference_uint32(unaligned_nonce);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls | kLoggingTraceNonce)) {
LOGI("-- OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(%d)\n", session);
if (unaligned_nonce != NULL) {
LOGI("nonce = %08X;\n", nonce);
} else {
LOGI("nonce = NULL;\n");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("encrypted_message_key", encrypted_message_key,
encrypted_message_key_length);
dump_hex("enc_rsa_key", enc_rsa_key, enc_rsa_key_length);
dump_hex("enc_rsa_key_iv", enc_rsa_key_iv, wvoec::KEY_IV_SIZE);
}
if (unaligned_nonce == NULL) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (!crypto_engine) {
LOGE("OEMCrypto_RewrapDeviceRSAKey30: OEMCrypto Not Initialized.");
@@ -902,9 +748,6 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey);
if (wrapped_rsa_key == NULL || *wrapped_rsa_key_length < buffer_size) {
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGW("[OEMCrypto_RewrapDeviceRSAKey30(): Wrapped Keybox Short Buffer]");
}
*wrapped_rsa_key_length = buffer_size;
return OEMCrypto_ERROR_SHORT_BUFFER;
}
@@ -988,24 +831,12 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
// The wrapped keybox must be signed with the same key we verify with. I'll
// pick the server key, so I don't have to modify LoadRSAKey.
unsigned int sig_length = sizeof(wrapped->signature);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message verified with HMAC and mac_key_server, key = " +
wvcdm::b2a_hex(session_ctx->mac_key_server()))
.c_str());
}
if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0],
session_ctx->mac_key_server().size(), wrapped->context,
buffer_size - sizeof(wrapped->signature), wrapped->signature,
&sig_length)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("wrapped_rsa_key", wrapped_rsa_key, *wrapped_rsa_key_length);
dump_hex("context", wrapped->context, sizeof(wrapped->context));
dump_hex("iv", wrapped->iv, sizeof(wrapped->iv));
}
}
return OEMCrypto_SUCCESS;
}
@@ -1016,23 +847,9 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
size_t enc_rsa_key_length, const uint8_t* enc_rsa_key_iv,
uint8_t* wrapped_rsa_key, size_t* wrapped_rsa_key_length) {
uint32_t nonce = unaligned_dereference_uint32(unaligned_nonce);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls | kLoggingTraceNonce)) {
LOGI("-- OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(%d)\n", session);
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("message", message, message_length);
dump_hex("signature", signature, signature_length);
}
if (unaligned_nonce != NULL) {
LOGI("nonce = %08X;\n", nonce);
} else {
LOGI("nonce = NULL;\n");
if (unaligned_nonce == NULL) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("enc_rsa_key", enc_rsa_key, enc_rsa_key_length);
dump_hex("enc_rsa_key_iv", enc_rsa_key_iv, wvoec::KEY_IV_SIZE);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_RewrapDeviceRSAKey: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1051,9 +868,6 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey);
if (wrapped_rsa_key == NULL || *wrapped_rsa_key_length < buffer_size) {
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGW("[OEMCrypto_RewrapDeviceRSAKey(): Wrapped Keybox Short Buffer]");
}
*wrapped_rsa_key_length = buffer_size;
return OEMCrypto_ERROR_SHORT_BUFFER;
}
@@ -1137,25 +951,12 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
// The wrapped keybox must be signed with the same key we verify with. I'll
// pick the server key, so I don't have to modify LoadRSAKey.
unsigned int sig_length = sizeof(wrapped->signature);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message verified with HMAC and mac_key_server, key = " +
wvcdm::b2a_hex(session_ctx->mac_key_server()))
.c_str());
}
if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0],
session_ctx->mac_key_server().size(), wrapped->context,
buffer_size - sizeof(wrapped->signature), wrapped->signature,
&sig_length)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("wrapped_rsa_key", wrapped_rsa_key, *wrapped_rsa_key_length);
dump_hex("signature", wrapped->signature, sizeof(wrapped->signature));
dump_hex("context", wrapped->context, sizeof(wrapped->context));
dump_hex("iv", wrapped->iv, sizeof(wrapped->iv));
}
}
return OEMCrypto_SUCCESS;
}
@@ -1184,15 +985,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(
}
const WrappedRSAKey* wrapped =
reinterpret_cast<const WrappedRSAKey*>(wrapped_rsa_key);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadDeviceRSAKey()\n");
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("wrapped_rsa_key", wrapped_rsa_key, wrapped_rsa_key_length);
dump_hex("signature", wrapped->signature, sizeof(wrapped->signature));
dump_hex("context", wrapped->context, sizeof(wrapped->context));
dump_hex("iv", wrapped->iv, sizeof(wrapped->iv));
}
}
if (!crypto_engine->ValidRootOfTrust()) {
LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]");
return OEMCrypto_ERROR_KEYBOX_INVALID;
@@ -1238,9 +1030,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(
}
extern "C" OEMCryptoResult OEMCrypto_LoadTestRSAKey() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadTestRSAKey()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_LoadTestRSAKey: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1253,13 +1042,6 @@ extern "C" 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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GenerateRSASignature()\n");
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("message", message, message_length);
dump_hex("message", message, message_length);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_GenerateRSASignature: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1290,13 +1072,6 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
OEMCryptoResult sts = session_ctx->GenerateRSASignature(
message, message_length, signature, signature_length, padding_scheme);
if (sts == OEMCrypto_SUCCESS) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("signature", signature, *signature_length);
}
}
}
return sts;
}
@@ -1305,16 +1080,6 @@ extern "C" 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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(\n");
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("enc_session_key", enc_session_key, enc_session_key_length);
dump_hex("mac_key_context", mac_key_context,
(size_t)mac_key_context_length);
dump_hex("enc_key_context", enc_key_context,
(size_t)enc_key_context_length);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_DeriveKeysFromSessionKey: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1346,16 +1111,6 @@ extern "C" OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
if (!session_ctx->RSADeriveKeys(ssn_key_str, mac_ctx_str, enc_ctx_str)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("mac_key_server", &session_ctx->mac_key_server()[0],
session_ctx->mac_key_server().size());
dump_hex("mac_key", &session_ctx->mac_key_client()[0],
session_ctx->mac_key_client().size());
dump_hex("enc_key", &session_ctx->encryption_key()[0],
session_ctx->encryption_key().size());
}
}
return OEMCrypto_SUCCESS;
}
@@ -1363,28 +1118,16 @@ extern "C" uint32_t OEMCrypto_APIVersion() { return 14; }
extern "C" uint8_t OEMCrypto_Security_Patch_Level() {
uint8_t security_patch_level = crypto_engine->config_security_patch_level();
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- uint8_t OEMCrypto_Security_Patch_Level(); // returns %d.\n",
security_patch_level);
}
return security_patch_level;
}
extern "C" const char* OEMCrypto_SecurityLevel() {
const char* security_level = crypto_engine->config_security_level();
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- const char* OEMCrypto_SecurityLevel(); // returns %s.\n",
security_level);
}
return security_level;
}
extern "C" OEMCryptoResult OEMCrypto_GetHDCPCapability(
OEMCrypto_HDCP_Capability* current, OEMCrypto_HDCP_Capability* maximum) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetHDCPCapability(%p, %p)\n", current,
maximum);
}
if (!crypto_engine) {
LOGE("OEMCrypto_GetHDCPCapability: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1393,30 +1136,27 @@ extern "C" OEMCryptoResult OEMCrypto_GetHDCPCapability(
if (maximum == NULL) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
*current = crypto_engine->config_current_hdcp_capability();
*maximum = crypto_engine->config_maximum_hdcp_capability();
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- current_hdcp=%d, max_hdcp=%d\n", *current, *maximum);
}
return OEMCrypto_SUCCESS;
}
extern "C" uint32_t OEMCrypto_GetAnalogOutputFlags() {
// TODO(b/69867568, fredgc): parameterize this.
return 0;
if (!crypto_engine) {
LOGE("OEMCrypto_GetAnalogOutputFlags: OEMCrypto Not Initialized.");
return 0;
}
return crypto_engine->analog_output_flags();
}
extern "C" bool OEMCrypto_SupportsUsageTable() {
bool supports_usage = crypto_engine->config_supports_usage_table();
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- bool OEMCrypto_SupportsUsageTable(); // returns %s.\n",
(supports_usage ? "true" : "false"));
if (!crypto_engine) {
LOGE("OEMCrypto_SupportsUsageTable: OEMCrypto Not Initialized.");
return 0;
}
bool supports_usage = crypto_engine->config_supports_usage_table();
return supports_usage;
}
extern "C" OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* count) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(%p)\n", count);
}
if (!crypto_engine) {
LOGE("OEMCrypto_GetNumberOfOpenSessions: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1427,9 +1167,6 @@ extern "C" OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* count) {
}
extern "C" OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(size_t* maximum) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(%p)\n", maximum);
}
if (!crypto_engine) {
LOGE("OEMCrypto_GetMaxNumberOfSessions: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1443,10 +1180,6 @@ extern "C" bool OEMCrypto_IsAntiRollbackHwPresent() {
bool anti_rollback_hw_present =
crypto_engine->config_is_anti_rollback_hw_present();
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- bool OEMCrypto_IsAntiRollbackHwPresent(): %d\n",
anti_rollback_hw_present);
}
return anti_rollback_hw_present;
}
@@ -1465,14 +1198,6 @@ extern "C" uint32_t OEMCrypto_SupportedCertificates() {
extern "C" 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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_Generic_Encrypt( algorithm=%d\n",
algorithm);
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("in_buffer", in_buffer, buffer_length);
dump_hex("iv", iv, wvoec::KEY_IV_SIZE);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_Generic_Encrypt: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1493,25 +1218,12 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Encrypt(
}
OEMCryptoResult sts = session_ctx->Generic_Encrypt(in_buffer, buffer_length,
iv, algorithm, out_buffer);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("out_buffer", out_buffer, buffer_length);
}
}
return sts;
}
extern "C" 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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_Generic_Decrypt( algorithm=%d\n",
algorithm);
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("in_buffer", in_buffer, buffer_length);
dump_hex("iv", iv, wvoec::KEY_IV_SIZE);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_Generic_Decrypt: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1532,11 +1244,6 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Decrypt(
}
OEMCryptoResult sts = session_ctx->Generic_Decrypt(in_buffer, buffer_length,
iv, algorithm, out_buffer);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("out_buffer", out_buffer, buffer_length);
}
}
return sts;
}
@@ -1546,13 +1253,6 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session,
OEMCrypto_Algorithm algorithm,
uint8_t* signature,
size_t* signature_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_Generic_Sign( algorithm=%d\n",
algorithm);
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("in_buffer", in_buffer, buffer_length);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_Generic_Sign: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1576,11 +1276,6 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session,
}
OEMCryptoResult sts = session_ctx->Generic_Sign(
in_buffer, buffer_length, algorithm, signature, signature_length);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("signature", signature, *signature_length);
}
}
return sts;
}
@@ -1588,14 +1283,6 @@ extern "C" 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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_Generic_Verify( algorithm=%d\n",
algorithm);
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("in_buffer", in_buffer, buffer_length);
dump_hex("signature", signature, signature_length);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_Generic_Verify: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1622,20 +1309,11 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Verify(
// TODO(fredgc): remove this.
extern "C" OEMCryptoResult OEMCrypto_UpdateUsageTable() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_UpdateUsageTable();\n");
}
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
extern "C" OEMCryptoResult OEMCrypto_DeactivateUsageEntry(
OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_DeactivateUsageEntry(\n");
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("pst", pst, pst_length);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_DeactivateUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1657,12 +1335,6 @@ extern "C" OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
size_t pst_length,
uint8_t* buffer,
size_t* buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_ReportUsage(\n");
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("pst", pst, pst_length);
}
}
if (!crypto_engine) {
LOGE("OEMCrypto_ReportUsage: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1680,11 +1352,6 @@ extern "C" OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
}
std::vector<uint8_t> pstv(pst, pst + pst_length);
OEMCryptoResult sts = session_ctx->ReportUsage(pstv, buffer, buffer_length);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("usage buffer", buffer, *buffer_length);
}
}
return sts;
}
@@ -1703,9 +1370,6 @@ extern "C" OEMCryptoResult OEMCrypto_ForceDeleteUsageEntry(const uint8_t*,
}
extern "C" OEMCryptoResult OEMCrypto_DeleteOldUsageTable() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_DeleteOldUsageTable()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_DeleteOldUsageTable: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1717,25 +1381,15 @@ extern "C" OEMCryptoResult OEMCrypto_DeleteOldUsageTable() {
}
extern "C" bool OEMCrypto_IsSRMUpdateSupported() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_IsSRMUpdateSupported()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_IsSRMUpdateSupported: OEMCrypto Not Initialized.");
return false;
}
bool result = crypto_engine->srm_update_supported();
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_IsSRMUpdateSupported returning %s\n",
result ? "TRUE" : "FALSE");
}
return result;
}
extern "C" OEMCryptoResult OEMCrypto_GetCurrentSRMVersion(uint16_t* version) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetCurrentSRMVersion()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_GetCurrentSRMVersion: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1744,19 +1398,11 @@ extern "C" OEMCryptoResult OEMCrypto_GetCurrentSRMVersion(uint16_t* version) {
return OEMCrypto_LOCAL_DISPLAY_ONLY;
}
OEMCryptoResult result = crypto_engine->current_srm_version(version);
if (result == OEMCrypto_SUCCESS &&
LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetCurrentSRMVersion returning %d\n",
*version);
}
return result;
}
extern "C" OEMCryptoResult OEMCrypto_LoadSRM(const uint8_t* buffer,
size_t buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadSRM(length=%d)\n", buffer_length);
}
if (!crypto_engine) {
LOGE("OEMCrypto_LoadSRM: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1765,9 +1411,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadSRM(const uint8_t* buffer,
}
extern "C" OEMCryptoResult OEMCrypto_RemoveSRM() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_RemoveSRM()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_RemoveSRM: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1777,9 +1420,6 @@ extern "C" OEMCryptoResult OEMCrypto_RemoveSRM() {
extern "C" OEMCryptoResult OEMCrypto_CreateUsageTableHeader(
uint8_t* header_buffer, size_t* header_buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CreateUsageTableHeader()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_CreateUsageTableHeader: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1794,9 +1434,6 @@ extern "C" OEMCryptoResult OEMCrypto_CreateUsageTableHeader(
extern "C" OEMCryptoResult OEMCrypto_LoadUsageTableHeader(
const uint8_t* buffer, size_t buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadUsageTableHeader()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_LoadUsageTableHeader: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1814,9 +1451,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadUsageTableHeader(
extern "C" OEMCryptoResult OEMCrypto_CreateNewUsageEntry(
OEMCrypto_SESSION session, uint32_t* usage_entry_number) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CreateNewUsageEntry(\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_CreateNewUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1833,9 +1467,6 @@ extern "C" OEMCryptoResult OEMCrypto_CreateNewUsageEntry(
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
OEMCryptoResult sts = session_ctx->CreateNewUsageEntry(usage_entry_number);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- usage_entry_number = %d", *usage_entry_number);
}
return sts;
}
@@ -1843,9 +1474,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadUsageEntry(OEMCrypto_SESSION session,
uint32_t index,
const uint8_t* buffer,
size_t buffer_size) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadUsageEntry(\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_LoadUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1870,9 +1498,6 @@ extern "C" 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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_UpdateUsageEntry(\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_UpdateUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1895,9 +1520,6 @@ extern "C" OEMCryptoResult OEMCrypto_UpdateUsageEntry(
extern "C" OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader(
uint32_t new_table_size, uint8_t* header_buffer,
size_t* header_buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_ShrinkUsageTableHeader: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1911,9 +1533,6 @@ extern "C" OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader(
extern "C" OEMCryptoResult OEMCrypto_MoveEntry(OEMCrypto_SESSION session,
uint32_t new_index) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_MoveEntry(\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_MoveEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1931,9 +1550,6 @@ extern "C" OEMCryptoResult OEMCrypto_MoveEntry(OEMCrypto_SESSION session,
extern "C" OEMCryptoResult OEMCrypto_CopyOldUsageEntry(
OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CopyOldUsageEntry(\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_CopyOldUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1955,9 +1571,6 @@ extern "C" 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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CreateOldUsageEntry()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_CreateOldUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_rsa_key_shared.h"
@@ -14,7 +14,7 @@
#include <openssl/sha.h>
#include <openssl/x509.h>
#include "oemcrypto_logging.h"
#include "log.h"
namespace wvoec_ref {

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#ifndef OEMCRYPTO_RSA_KEY_SHARED_H_
#define OEMCRYPTO_RSA_KEY_SHARED_H_

View File

@@ -1,3 +1,6 @@
// 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.
#ifndef OEMCRYPTO_SCOPED_PTR_H_
#define OEMCRYPTO_SCOPED_PTR_H_
@@ -17,6 +20,7 @@ class scoped_ptr {
public:
explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
T* get() const { return ptr_.get(); }
void reset(T* p = NULL) { ptr_.reset(p); }
private:
std::auto_ptr<T> ptr_;
@@ -32,7 +36,7 @@ class scoped_ptr {
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_.get(); }
T* get() const { return ptr_.get(); }
void reset(T* p = NULL) { ptr_.reset(); }
void reset(T* p = NULL) { ptr_.reset(p); }
private:
std::unique_ptr<T> ptr_;

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_session.h"
@@ -28,7 +28,6 @@
#include "log.h"
#include "oemcrypto_engine_ref.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_rsa_key_shared.h"
#include "oemcrypto_types.h"
#include "disallow_copy_and_assign.h"
@@ -248,14 +247,6 @@ bool SessionContext::DeriveKeys(const std::vector<uint8_t>& master_key,
return false;
}
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI((" mac_key_context = " + wvcdm::b2a_hex(mac_key_context)).c_str());
LOGI((" enc_key_context = " + wvcdm::b2a_hex(enc_key_context)).c_str());
LOGI((" mac_key_server = " + wvcdm::b2a_hex(mac_key_server)).c_str());
LOGI((" mac_key_client = " + wvcdm::b2a_hex(mac_key_client)).c_str());
LOGI((" enc_key = " + wvcdm::b2a_hex(enc_key)).c_str());
}
set_mac_key_server(mac_key_server);
set_mac_key_client(mac_key_client);
set_encryption_key(enc_key);
@@ -316,25 +307,6 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
return false;
}
bool using_usage_entry_mac_key_client = false;
std::vector<uint8_t> usage_entry_mac_key_client;
if (usage_entry_status_ == kUsageEntryLoaded) {
usage_entry_mac_key_client.assign(
usage_entry_->mac_key_client(),
usage_entry_->mac_key_client() + wvoec::MAC_KEY_SIZE * sizeof(uint8_t));
using_usage_entry_mac_key_client =
mac_key_client_ == usage_entry_mac_key_client;
}
if (using_usage_entry_mac_key_client &&
LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message signed with HMAC and usage_entry_'s mac_key_client, "
"mac_key_client = " +
wvcdm::b2a_hex(usage_entry_mac_key_client)).c_str());
} else if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message signed with HMAC and mac_key_client_, mac_key_client_ = " +
wvcdm::b2a_hex(mac_key_client_)).c_str());
}
unsigned int md_len = *signature_length;
if (HMAC(EVP_sha256(), &mac_key_client_[0], wvoec::MAC_KEY_SIZE, message,
message_length, signature, &md_len)) {
@@ -432,10 +404,6 @@ bool SessionContext::ValidateMessage(const uint8_t* given_message,
uint8_t computed_signature[SHA256_DIGEST_LENGTH];
memset(computed_signature, 0, SHA256_DIGEST_LENGTH);
unsigned int md_len = SHA256_DIGEST_LENGTH;
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message verified with HMAC and mac_key_server, key = " +
wvcdm::b2a_hex(mac_key_server_)).c_str());
}
if (!HMAC(EVP_sha256(), &mac_key_server_[0], mac_key_server_.size(),
given_message, message_length, computed_signature, &md_len)) {
LOGE("ValidateMessage: Could not compute signature.");
@@ -652,10 +620,6 @@ OEMCryptoResult SessionContext::LoadKeys(
LOGE("LoadKeys: Usage table can't set keys.\n");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("usage_entry_'s mac_key_client_ has changed to = " +
wvcdm::b2a_hex(mac_key_client_)).c_str());
}
break;
case kUsageEntryLoaded:
if (!usage_entry_->VerifyPST(pst, pst_length)) {
@@ -732,14 +696,6 @@ OEMCryptoResult SessionContext::InstallKey(
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (LogCategoryEnabled(kLoggingDumpContentKeys)) {
LOGI((" InstallKey: key_id = " + wvcdm::b2a_hex(key_id)).c_str());
LOGI(
(" InstallKey: content_key = " + wvcdm::b2a_hex(content_key)).c_str());
LOGI((" InstallKey: key_control = " + wvcdm::b2a_hex(key_control_str))
.c_str());
}
// Key control must be supplied by license server
if (key_control.empty()) {
LOGE("[Installkey(): WARNING: No Key Control]");
@@ -755,9 +711,6 @@ OEMCryptoResult SessionContext::InstallKey(
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Key ID: %s", wvcdm::b2a_hex(key_id).c_str());
}
KeyControlBlock key_control_block(key_control_str);
if (!key_control_block.valid()) {
LOGE("Error parsing key control.");
@@ -855,16 +808,11 @@ OEMCryptoResult SessionContext::RefreshKey(
Key* content_key = session_keys_->Find(key_id);
if (NULL == content_key) {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Error: no matching content key.");
}
LOGE("Key ID not found.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (key_control.empty()) {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Error: no key_control.");
}
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
@@ -873,33 +821,21 @@ OEMCryptoResult SessionContext::RefreshKey(
// Decrypt encrypted key control block
std::vector<uint8_t> control;
if (key_control_iv.empty()) {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Key control block is NOT encrypted.");
}
control = key_control;
} else {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Key control block is encrypted.");
}
if (!DecryptMessage(content_key_value, key_control_iv, key_control,
&control, 128 /* key size */)) {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Error decrypting key control block.");
}
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
KeyControlBlock key_control_block(control);
if (!key_control_block.valid()) {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Parse key control error.");
}
LOGE("Error parsing key control.");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if ((key_control_block.control_bits() & wvoec::kControlNonceEnabled) &&
(!CheckNonce(key_control_block.nonce()))) {
LOGE("KCB: BAD Nonce");
return OEMCrypto_ERROR_INVALID_NONCE;
}
content_key->UpdateDuration(key_control_block);
@@ -981,8 +917,7 @@ OEMCryptoResult SessionContext::CheckKeyUse(const std::string& log_string,
}
}
if (!ce_->config_local_display_only()) {
// Only look at HDCP and Analog restrictions if the display can be
// non-local.
// Only look at HDCP restrictions if the display can be non-local.
if (control.control_bits() & wvoec::kControlHDCPRequired) {
uint8_t required_hdcp =
(control.control_bits() & wvoec::kControlHDCPVersionMask) >>
@@ -998,10 +933,24 @@ OEMCryptoResult SessionContext::CheckKeyUse(const std::string& log_string,
}
}
}
if (!ce_->config_local_display_only() ||
buffer_type == OEMCrypto_BufferType_Clear) {
if (control.control_bits() & wvoec::kControlDisableAnalogOutput) {
LOGE("[%s(): control bit says disable analog.", log_string.c_str());
// If the output buffer is clear, then we cannot control whether the output is
// an active analog display. In that case, return an error if analog displays
// should be disabled.
if ((control.control_bits() & wvoec::kControlDisableAnalogOutput) &&
(ce_->analog_display_active() ||
(buffer_type == OEMCrypto_BufferType_Clear))) {
LOGE("[%s(): control bit says disable analog.", log_string.c_str());
return OEMCrypto_ERROR_ANALOG_OUTPUT;
}
// Check if CGMS is required.
if (control.control_bits() & wvoec::kControlCGMSMask) {
// We can't control CGMS for a clear buffer.
if (buffer_type == OEMCrypto_BufferType_Clear) {
LOGE("[%s(): CGMS required, but buffer is clear.", log_string.c_str());
return OEMCrypto_ERROR_ANALOG_OUTPUT;
}
if ( ce_->analog_display_active() && !ce_->cgms_a_active()) {
LOGE("[%s(): control bit says CGMS required.", log_string.c_str());
return OEMCrypto_ERROR_ANALOG_OUTPUT;
}
}
@@ -1179,10 +1128,6 @@ bool SessionContext::UpdateMacKeys(const std::vector<uint8_t>& enc_mac_keys,
mac_keys.begin(), mac_keys.begin() + wvoec::MAC_KEY_SIZE);
mac_key_client_ = std::vector<uint8_t>(mac_keys.begin() + wvoec::MAC_KEY_SIZE,
mac_keys.end());
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("mac_key_client_ has been updated to = " +
wvcdm::b2a_hex(mac_key_client_)).c_str());
}
return true;
}
@@ -1191,15 +1136,6 @@ bool SessionContext::QueryKeyControlBlock(const KeyId& key_id, uint32_t* data) {
return false;
}
const Key* content_key = session_keys_->Find(key_id);
if (LogCategoryEnabled(kLoggingTraceDecryption)) {
LOGI(("Select Key: key_id = " + wvcdm::b2a_hex(key_id)).c_str());
if (content_key) {
LOGI(("Select Key: key = " + wvcdm::b2a_hex(content_key->value()))
.c_str());
} else {
LOGI("Select Key: key = null.");
}
}
if (NULL == content_key) {
LOGE("[QueryKeyControlBlock(): No key matches key id]");
return false;
@@ -1213,23 +1149,14 @@ bool SessionContext::QueryKeyControlBlock(const KeyId& key_id, uint32_t* data) {
OEMCryptoResult SessionContext::SelectContentKey(
const KeyId& key_id, OEMCryptoCipherMode cipher_mode) {
if (LogCategoryEnabled(kLoggingTraceDecryption)) {
LOGI(" Select Key: key_id = %s", wvcdm::b2a_hex(key_id).c_str());
LOGI(" Select Key: cipher_mode = %s",
(cipher_mode == OEMCrypto_CipherMode_CTR) ? "CTR" : "CBC");
}
if (!session_keys_) {
LOGE("Select Key: no session keys.");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
Key* content_key = session_keys_->Find(key_id);
if (NULL == content_key) {
LOGE("[SelectContentKey(): No key matches key id]");
return OEMCrypto_ERROR_NO_CONTENT_KEY;
}
if (LogCategoryEnabled(kLoggingTraceDecryption)) {
LOGI((" Select Key: key = " + wvcdm::b2a_hex(content_key->value()))
.c_str());
LOGE("No key matches key id");
return OEMCrypto_KEY_NOT_LOADED;
}
content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR);
current_content_key_ = content_key;
@@ -1281,10 +1208,6 @@ OEMCryptoResult SessionContext::LoadUsageEntry(
mac_key_client_ = std::vector<uint8_t>(
usage_entry_->mac_key_client(),
usage_entry_->mac_key_client() + wvoec::MAC_KEY_SIZE);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("mac_key_client_ has been updated to = " +
wvcdm::b2a_hex(mac_key_client_)).c_str());
}
}
return result;
}
@@ -1355,8 +1278,8 @@ OEMCryptoResult SessionContext::DecryptCENC(
// If the data is clear, we do not need a current key selected.
if (!is_encrypted) {
if (buffer_type != OEMCrypto_BufferType_Direct) {
memcpy(reinterpret_cast<uint8_t*>(clear_data), cipher_data,
cipher_data_length);
memmove(reinterpret_cast<uint8_t*>(clear_data), cipher_data,
cipher_data_length);
return OEMCrypto_SUCCESS;
}
// For reference implementation, we quietly drop the clear direct video.
@@ -1421,7 +1344,7 @@ OEMCryptoResult SessionContext::DecryptCBC(
pattern_offset = (pattern_offset + 1) % pattern_length;
}
if (skip_block || (size < AES_BLOCK_SIZE)) {
memcpy(&clear_data[l], &cipher_data[l], size);
memmove(&clear_data[l], &cipher_data[l], size);
} else {
uint8_t aes_output[AES_BLOCK_SIZE];
// Save the iv for the next block, in case cipher_data is in the same
@@ -1459,7 +1382,7 @@ OEMCryptoResult SessionContext::PatternDecryptCTR(
pattern_offset = (pattern_offset + 1) % pattern_length;
}
if (skip_block) {
memcpy(&clear_data[l], &cipher_data[l], size);
memmove(&clear_data[l], &cipher_data[l], size);
} else {
uint8_t aes_output[AES_BLOCK_SIZE];
AES_encrypt(iv, aes_output, &aes_key);

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#ifndef REF_OEMCRYPTO_SESSION_H_
#define REF_OEMCRYPTO_SESSION_H_
@@ -14,14 +14,14 @@
#include <openssl/rsa.h>
#include "OEMCryptoCENC.h" // Needed for enums only.
#include "OEMCryptoCENC.h"
#include "oemcrypto_auth_ref.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_nonce_table.h"
#include "oemcrypto_rsa_key_shared.h"
#include "oemcrypto_session_key_table.h"
#include "oemcrypto_usage_table_ref.h"
#include "oemcrypto_types.h"
#include "oemcrypto_usage_table_ref.h"
namespace wvoec_ref {
@@ -74,26 +74,25 @@ class SessionContext {
usage_entry_(NULL),
srm_requirements_status_(NoSRMVersion),
usage_entry_status_(kNoUsageEntry) {}
~SessionContext();
virtual ~SessionContext();
bool isValid() { return valid_; }
bool DeriveKeys(const std::vector<uint8_t>& master_key,
const std::vector<uint8_t>& mac_context,
const std::vector<uint8_t>& enc_context);
bool RSADeriveKeys(const std::vector<uint8_t>& enc_session_key,
const std::vector<uint8_t>& mac_context,
const std::vector<uint8_t>& enc_context);
bool GenerateSignature(const uint8_t* message, size_t message_length,
uint8_t* signature, size_t* signature_length);
virtual bool DeriveKeys(const std::vector<uint8_t>& master_key,
const std::vector<uint8_t>& mac_context,
const std::vector<uint8_t>& enc_context);
virtual bool RSADeriveKeys(const std::vector<uint8_t>& enc_session_key,
const std::vector<uint8_t>& mac_context,
const std::vector<uint8_t>& enc_context);
virtual bool GenerateSignature(const uint8_t* message, size_t message_length,
uint8_t* signature, size_t* signature_length);
size_t RSASignatureSize();
OEMCryptoResult GenerateRSASignature(const uint8_t* message,
size_t message_length,
uint8_t* signature,
size_t* signature_length,
RSA_Padding_Scheme padding_scheme);
bool ValidateMessage(const uint8_t* message, size_t message_length,
const uint8_t* signature, size_t signature_length);
virtual OEMCryptoResult GenerateRSASignature(
const uint8_t* message, size_t message_length, uint8_t* signature,
size_t* signature_length, RSA_Padding_Scheme padding_scheme);
virtual bool ValidateMessage(const uint8_t* message, size_t message_length,
const uint8_t* signature,
size_t signature_length);
OEMCryptoResult DecryptCENC(const uint8_t* iv, size_t block_offset,
const OEMCrypto_CENCEncryptPatternDesc* pattern,
const uint8_t* cipher_data,
@@ -118,7 +117,7 @@ class SessionContext {
size_t signature_length);
void StartTimer();
uint32_t CurrentTimer(); // (seconds).
OEMCryptoResult LoadKeys(
virtual OEMCryptoResult LoadKeys(
const uint8_t* message, size_t message_length, const uint8_t* signature,
size_t signature_length, const uint8_t* enc_mac_key_iv,
const uint8_t* enc_mac_keys, size_t num_keys,
@@ -126,14 +125,13 @@ class SessionContext {
size_t pst_length, const uint8_t* srm_requirement,
OEMCrypto_LicenseType license_type);
OEMCryptoResult LoadEntitledContentKeys(
size_t num_keys,
const OEMCrypto_EntitledContentKeyObject* key_array);
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);
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);
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,
@@ -141,14 +139,14 @@ class SessionContext {
bool EncryptRSAKey(const uint8_t* pkcs8_rsa_key, size_t enc_rsa_key_length,
const uint8_t* enc_rsa_key_iv, uint8_t* enc_rsa_key);
bool LoadRSAKey(const uint8_t* pkcs8_rsa_key, size_t rsa_key_length);
OEMCryptoResult RefreshKey(const KeyId& key_id,
const std::vector<uint8_t>& key_control,
const std::vector<uint8_t>& key_control_iv);
bool UpdateMacKeys(const std::vector<uint8_t>& mac_keys,
const std::vector<uint8_t>& iv);
bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data);
OEMCryptoResult SelectContentKey(const KeyId& key_id,
OEMCryptoCipherMode cipher_mode);
virtual OEMCryptoResult RefreshKey(
const KeyId& key_id, const std::vector<uint8_t>& key_control,
const std::vector<uint8_t>& key_control_iv);
virtual bool UpdateMacKeys(const std::vector<uint8_t>& mac_keys,
const std::vector<uint8_t>& iv);
virtual bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data);
virtual OEMCryptoResult SelectContentKey(const KeyId& key_id,
OEMCryptoCipherMode cipher_mode);
const Key* current_content_key(void) { return current_content_key_; }
void set_mac_key_server(const std::vector<uint8_t>& mac_key_server) {
mac_key_server_ = mac_key_server;
@@ -169,20 +167,20 @@ class SessionContext {
bool CheckNonce(uint32_t nonce);
void FlushNonces();
OEMCryptoResult CreateNewUsageEntry(uint32_t* usage_entry_number);
OEMCryptoResult LoadUsageEntry(uint32_t index,
const std::vector<uint8_t>& buffer);
OEMCryptoResult UpdateUsageEntry(uint8_t* header_buffer,
size_t* header_buffer_length,
uint8_t* entry_buffer,
size_t* entry_buffer_length);
OEMCryptoResult DeactivateUsageEntry(const std::vector<uint8_t>& pst);
OEMCryptoResult ReportUsage(const std::vector<uint8_t>& pst, uint8_t* buffer,
size_t* buffer_length);
virtual OEMCryptoResult CreateNewUsageEntry(uint32_t* usage_entry_number);
virtual OEMCryptoResult LoadUsageEntry(uint32_t index,
const std::vector<uint8_t>& buffer);
virtual OEMCryptoResult UpdateUsageEntry(uint8_t* header_buffer,
size_t* header_buffer_length,
uint8_t* entry_buffer,
size_t* entry_buffer_length);
virtual OEMCryptoResult DeactivateUsageEntry(const std::vector<uint8_t>& pst);
virtual OEMCryptoResult ReportUsage(const std::vector<uint8_t>& pst,
uint8_t* buffer, size_t* buffer_length);
OEMCryptoResult MoveEntry(uint32_t new_index);
OEMCryptoResult CopyOldUsageEntry(const std::vector<uint8_t>& pst);
private:
protected:
bool DeriveKey(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& context, int counter,
std::vector<uint8_t>* out);

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_session_key_table.h"

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#ifndef REF_OEMCRYPTO_SESSION_KEY_TABLE_H_
#define REF_OEMCRYPTO_SESSION_KEY_TABLE_H_

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_usage_table_ref.h"
@@ -20,7 +20,6 @@
#include "file_store.h"
#include "log.h"
#include "oemcrypto_engine_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_old_usage_table_ref.h"
// TODO(fredgc): Setting the device files base bath is currently broken as
// wvcdm::Properties is no longer used by the reference code.
@@ -160,15 +159,6 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
pst_report.set_pst_length(data_.pst_length);
memcpy(pst_report.pst(), data_.pst, data_.pst_length);
unsigned int md_len = SHA_DIGEST_LENGTH;
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
std::vector<uint8_t> mac_key_client(
data_.mac_key_client,
data_.mac_key_client + wvoec::MAC_KEY_SIZE * sizeof(uint8_t));
LOGI(("message signed with HMAC and data_.mac_key_client, "
"mac_key_client = " +
wvcdm::b2a_hex(mac_key_client))
.c_str());
}
if (!HMAC(EVP_sha1(), data_.mac_key_client, wvoec::MAC_KEY_SIZE,
buffer + SHA_DIGEST_LENGTH, length_needed - SHA_DIGEST_LENGTH,
pst_report.signature(), &md_len)) {
@@ -206,8 +196,7 @@ OEMCryptoResult UsageTableEntry::SaveData(CryptoEngine* ce,
// This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox key.
const bool override_to_real = true;
const std::vector<uint8_t>& key = ce->DeviceRootKey(override_to_real);
const std::vector<uint8_t>& key = ce->DeviceRootKey();
// Encrypt the entry.
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
@@ -245,8 +234,7 @@ OEMCryptoResult UsageTableEntry::LoadData(CryptoEngine* ce, uint32_t index,
// This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox key.
const bool override_to_real = true;
const std::vector<uint8_t>& key = ce->DeviceRootKey(override_to_real);
const std::vector<uint8_t>& key = ce->DeviceRootKey();
// Verify the signature of the usage entry. Sign encrypted into clear buffer.
unsigned int sig_length = SHA256_DIGEST_LENGTH;
@@ -319,13 +307,6 @@ OEMCryptoResult UsageTableEntry::CopyOldUsageEntry(
} else {
memcpy(data_.mac_key_client, &(old_entry->mac_key_client_[0]),
wvoec::MAC_KEY_SIZE);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
std::vector<uint8_t> mac_key_client(
data_.mac_key_client,
data_.mac_key_client + wvoec::MAC_KEY_SIZE * sizeof(uint8_t));
LOGI(("data_.mac_key_client has changed to = " +
wvcdm::b2a_hex(mac_key_client)).c_str());
}
}
if (pst.size() > kMaxPSTLength) {
LOGE("CopyOldEntry: PST Length was too large. Truncating.");
@@ -385,6 +366,10 @@ OEMCryptoResult UsageTable::UpdateUsageEntry(SessionContext* session,
return result;
}
UsageTableEntry* UsageTable::MakeEntry(uint32_t index) {
return new UsageTableEntry(this, index, master_generation_number_);
}
OEMCryptoResult UsageTable::CreateNewUsageEntry(SessionContext* session,
UsageTableEntry** entry,
uint32_t* usage_entry_number) {
@@ -395,8 +380,12 @@ OEMCryptoResult UsageTable::CreateNewUsageEntry(SessionContext* session,
if (!entry) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
if (!usage_entry_number) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
uint32_t index = generation_numbers_.size();
UsageTableEntry* new_entry =
new UsageTableEntry(this, index, master_generation_number_);
size_t max = ce_->max_usage_table_size();
if (max > 0 && index >= max) {
LOGE("Too many usage entries: %d/%d", index, max);
return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES;
}
UsageTableEntry* new_entry = MakeEntry(index);
generation_numbers_.push_back(master_generation_number_);
sessions_.push_back(session);
master_generation_number_++;
@@ -420,8 +409,12 @@ OEMCryptoResult UsageTable::LoadUsageEntry(SessionContext* session,
LOGE("LoadUsageEntry: index %d used by other session.", index);
return OEMCrypto_ERROR_INVALID_SESSION;
}
UsageTableEntry* new_entry =
new UsageTableEntry(this, index, master_generation_number_);
size_t max = ce_->max_usage_table_size();
if (max > 0 && index >= max) {
LOGE("Too many usage entries: %d/%d", index, max);
return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES;
}
UsageTableEntry* new_entry = MakeEntry(index);
OEMCryptoResult status = new_entry->LoadData(ce_, index, buffer);
if (status != OEMCrypto_SUCCESS) {
@@ -500,8 +493,7 @@ OEMCryptoResult UsageTable::SaveUsageTableHeader(uint8_t* signed_buffer,
// This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox key.
const bool override_to_real = true;
const std::vector<uint8_t>& key = ce_->DeviceRootKey(override_to_real);
const std::vector<uint8_t>& key = ce_->DeviceRootKey();
// Encrypt the entry.
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
@@ -530,6 +522,12 @@ OEMCryptoResult UsageTable::LoadUsageTableHeader(
if (!LoadGenerationNumber(false)) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
if (buffer.size() < SignedHeaderSize(0)) return OEMCrypto_ERROR_SHORT_BUFFER;
size_t max = ce_->max_usage_table_size();
if (max > 0 && buffer.size() > SignedHeaderSize(max)) {
LOGE("Header too big: %zd bytes/%zd bytes",
buffer.size(), SignedHeaderSize(max));
return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES;
}
std::vector<uint8_t> clear_buffer(buffer.size());
SignedHeaderBlock* clear =
reinterpret_cast<SignedHeaderBlock*>(&clear_buffer[0]);
@@ -538,8 +536,7 @@ OEMCryptoResult UsageTable::LoadUsageTableHeader(
// This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox key.
const bool override_to_real = true;
const std::vector<uint8_t>& key = ce_->DeviceRootKey(override_to_real);
const std::vector<uint8_t>& key = ce_->DeviceRootKey();
// Verify the signature of the usage entry. Sign encrypted into clear buffer.
unsigned int sig_length = SHA256_DIGEST_LENGTH;

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Ref implementation of OEMCrypto APIs
// Reference implementation of OEMCrypto APIs
//
#ifndef OEMCRYPTO_USAGE_TABLE_REF_H_
#define OEMCRYPTO_USAGE_TABLE_REF_H_
@@ -42,8 +42,7 @@ struct StoredUsageEntry {
class UsageTableEntry {
public:
UsageTableEntry(UsageTable* table, uint32_t index, int64_t generation);
// owner_(owner), session_(session), loaded_(false) {}
~UsageTableEntry(); // Free memory, remove reference in header.
virtual ~UsageTableEntry(); // Free memory, remove reference in header.
bool Inactive() { return data_.status >= kInactive; }
OEMCryptoResult SetPST(const uint8_t* pst, size_t pst_length);
bool VerifyPST(const uint8_t* pst, size_t pst_length);
@@ -56,14 +55,14 @@ class UsageTableEntry {
// for update.
bool CheckForUse();
void Deactivate(const std::vector<uint8_t>& pst);
OEMCryptoResult ReportUsage(const std::vector<uint8_t>& pst, uint8_t* buffer,
size_t* buffer_length);
void UpdateAndIncrement();
virtual OEMCryptoResult ReportUsage(const std::vector<uint8_t>& pst,
uint8_t* buffer, size_t* buffer_length);
virtual void UpdateAndIncrement();
OEMCryptoResult SaveData(CryptoEngine* ce, SessionContext* session,
uint8_t* signed_buffer, size_t buffer_size);
OEMCryptoResult LoadData(CryptoEngine* ce, uint32_t index,
const std::vector<uint8_t>& buffer);
OEMCryptoResult CopyOldUsageEntry(const std::vector<uint8_t>& pst);
virtual OEMCryptoResult CopyOldUsageEntry(const std::vector<uint8_t>& pst);
int64_t generation_number() { return data_.generation_number; }
void set_generation_number(int64_t value) { data_.generation_number = value; }
void set_index(int32_t index) { data_.index = index; }
@@ -72,7 +71,7 @@ class UsageTableEntry {
const uint8_t* mac_key_server() { return data_.mac_key_server; }
const uint8_t* mac_key_client() { return data_.mac_key_client; }
private:
protected:
UsageTable* usage_table_; // Owner of this object.
bool recent_decrypt_;
bool forbid_report_;
@@ -82,8 +81,8 @@ class UsageTableEntry {
class UsageTable {
public:
explicit UsageTable(CryptoEngine* ce)
: ce_(ce), header_loaded_(false), old_table_(NULL){};
~UsageTable();
: ce_(ce), header_loaded_(false), old_table_(NULL) {};
virtual ~UsageTable();
OEMCryptoResult CreateNewUsageEntry(SessionContext* session,
UsageTableEntry** entry,
@@ -113,23 +112,23 @@ class UsageTable {
uint64_t time_since_first_decrypt,
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);
uint8_t* server_mac_key,
uint8_t* client_mac_key,
const uint8_t* pst, size_t pst_length);
private:
OEMCryptoResult SaveUsageTableHeader(uint8_t* signed_buffer,
size_t buffer_size);
bool SaveGenerationNumber();
bool LoadGenerationNumber(bool or_make_new_one);
protected:
virtual UsageTableEntry* MakeEntry(uint32_t index);
virtual OEMCryptoResult SaveUsageTableHeader(uint8_t* signed_buffer,
size_t buffer_size);
virtual bool SaveGenerationNumber();
virtual bool LoadGenerationNumber(bool or_make_new_one);
CryptoEngine* ce_;
bool header_loaded_;
int64_t master_generation_number_;
std::vector<int64_t> generation_numbers_;
std::vector<SessionContext*> sessions_;
OldUsageTable *old_table_;
OldUsageTable* old_table_;
};
} // namespace wvoec_ref

View File

@@ -143,6 +143,7 @@ std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
if (api_version < 12) FilterOut(&filter, "*API12*");
if (api_version < 13) FilterOut(&filter, "*API13*");
if (api_version < 14) FilterOut(&filter, "*API14*");
if (api_version < 15) FilterOut(&filter, "*API15*");
// Some tests may require root access. If user is not root, filter these tests
// out.
if (getuid()) {

View File

@@ -1094,9 +1094,14 @@ void Session::InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key) {
GenerateDerivedKeysFromSessionKey();
}
void Session::CreateNewUsageEntry() {
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_CreateNewUsageEntry(session_id(), &usage_entry_number_));
void Session::CreateNewUsageEntry(OEMCryptoResult* status) {
OEMCryptoResult result =
OEMCrypto_CreateNewUsageEntry(session_id(), &usage_entry_number_);
if (status) {
*status = result;
return;
}
ASSERT_EQ(OEMCrypto_SUCCESS, result);
}
void Session::UpdateUsageEntry(std::vector<uint8_t>* header_buffer) {

View File

@@ -290,7 +290,9 @@ class Session {
// GenerateDerivedKeysFromSessionKey to install known encryption and mac keys.
void InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key);
// Creates a new usage entry, and keeps track of the index.
void CreateNewUsageEntry();
// If status is null, we expect success, otherwise status is set to the
// return value.
void CreateNewUsageEntry(OEMCryptoResult *status = NULL);
// Copy encrypted usage entry from other session, and then load it.
// This session must already be open.
void LoadUsageEntry(uint32_t index, const vector<uint8_t>& buffer);

View File

@@ -463,6 +463,112 @@ static const uint8_t kTestRSAPKCS8PrivateKeyInfo3_3072[] = {
0x7f, 0xad, 0x7d, 0xcd, 0x22, 0x06
};
// A 2048 bit RSA key in PKCS#8 PrivateKeyInfo format.
// This is a different key from the one above.
static const uint8_t kTestRSAPKCS8PrivateKeyInfo4_2048[] = {
0x30, 0x82, 0x04, 0xbd, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
0x04, 0xa7, 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
0x01, 0x00, 0xc7, 0xfd, 0xa7, 0xca, 0x67, 0x15, 0xd1, 0x29, 0xea, 0xbc,
0x42, 0x9b, 0x02, 0x37, 0xbb, 0xfb, 0xb4, 0x72, 0x86, 0x76, 0x05, 0x20,
0x05, 0xcb, 0x94, 0x58, 0x79, 0x4a, 0x79, 0x68, 0xfe, 0xb4, 0x1d, 0x27,
0x87, 0x97, 0x22, 0xeb, 0x13, 0xb2, 0xb6, 0xed, 0xda, 0xb3, 0xc0, 0x63,
0x32, 0xd9, 0x31, 0x29, 0xb1, 0xb9, 0x97, 0x17, 0x67, 0x65, 0xd3, 0x9b,
0x8d, 0xf2, 0x73, 0x1c, 0x70, 0x08, 0xe5, 0x64, 0x9f, 0xcf, 0x5b, 0x52,
0x9e, 0x47, 0x51, 0xb0, 0xeb, 0x21, 0x81, 0xb4, 0x24, 0xc8, 0xd0, 0x42,
0xf3, 0xd4, 0x77, 0x1e, 0x96, 0x12, 0x2f, 0x74, 0xab, 0x06, 0xb2, 0x2e,
0xfa, 0xcd, 0x83, 0xcc, 0xbf, 0x02, 0x14, 0x34, 0x3c, 0x2c, 0x79, 0x7f,
0x60, 0x60, 0xd0, 0x68, 0x7e, 0x70, 0x32, 0xd4, 0x34, 0x73, 0x0a, 0x42,
0x7b, 0xbc, 0x69, 0xc0, 0xf8, 0xa6, 0xdc, 0x8f, 0x10, 0xda, 0x1c, 0xd4,
0x9d, 0x59, 0x23, 0xb4, 0x05, 0x32, 0xac, 0xcc, 0x54, 0xff, 0x35, 0xb3,
0x3f, 0x22, 0x1b, 0x8d, 0x9b, 0x6d, 0x76, 0xd7, 0xe5, 0xd1, 0xaa, 0x54,
0x01, 0xd9, 0x53, 0x88, 0x40, 0xb4, 0x7a, 0x3c, 0x2b, 0x47, 0x09, 0xcc,
0x50, 0xfa, 0x7a, 0x87, 0x56, 0x44, 0x28, 0x4b, 0x47, 0xc4, 0xee, 0x2e,
0x2a, 0xaa, 0xe7, 0x7a, 0xd6, 0x7f, 0xd3, 0xc5, 0xf8, 0x70, 0x14, 0x97,
0x64, 0x1c, 0x62, 0xdc, 0x42, 0xed, 0x90, 0x7d, 0x18, 0x36, 0xc2, 0xfa,
0xd2, 0xdf, 0xd5, 0x23, 0x5c, 0x5a, 0xfb, 0x84, 0xe1, 0xe3, 0x5d, 0x3a,
0x6a, 0x4e, 0x6a, 0x4b, 0xd9, 0x2d, 0xbd, 0xea, 0x88, 0x95, 0xc0, 0xb5,
0xf2, 0xd3, 0x37, 0x1f, 0xfe, 0xc7, 0x0a, 0x62, 0x33, 0x5b, 0x98, 0x36,
0x9d, 0x8d, 0x1a, 0x8e, 0x3a, 0xc5, 0x69, 0xe3, 0x2b, 0x95, 0x6e, 0xa6,
0xf6, 0x00, 0xc0, 0x9d, 0xa7, 0x39, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
0x82, 0x01, 0x00, 0x3e, 0x5b, 0x16, 0x80, 0x03, 0x58, 0x48, 0x19, 0x3b,
0xb9, 0x6b, 0x43, 0x0d, 0x93, 0xf7, 0x26, 0xea, 0x02, 0x73, 0x6e, 0x44,
0xf6, 0xd1, 0x17, 0xc2, 0xaf, 0x3b, 0x52, 0x3f, 0x3c, 0xbf, 0x7d, 0xc5,
0x41, 0x58, 0x03, 0x85, 0xbd, 0xaa, 0x2c, 0xa4, 0xe0, 0xd0, 0xba, 0x0f,
0x18, 0x5e, 0xf8, 0x5d, 0x5d, 0xd4, 0xae, 0x3b, 0x2f, 0xee, 0xeb, 0x4e,
0xe9, 0x47, 0x7e, 0xfa, 0xe9, 0x38, 0xfd, 0x6d, 0x18, 0xcc, 0xc3, 0x48,
0x84, 0x20, 0x19, 0xb8, 0x9c, 0xe3, 0x13, 0x55, 0x6f, 0xa7, 0xb0, 0x7d,
0x4f, 0x02, 0xdb, 0x92, 0x30, 0x95, 0x36, 0x22, 0x59, 0xcc, 0x21, 0x90,
0x59, 0x19, 0x96, 0x0e, 0xac, 0x3e, 0x3a, 0x15, 0xb6, 0x9b, 0xb4, 0x7a,
0x45, 0x7e, 0xf5, 0x70, 0xc5, 0xc3, 0xf6, 0x93, 0xc2, 0x9a, 0x7f, 0xec,
0x09, 0x02, 0xaf, 0xa2, 0x81, 0xaa, 0x85, 0xcc, 0x6b, 0x47, 0x23, 0x4d,
0x65, 0x7e, 0xd7, 0xa9, 0x0c, 0x37, 0x48, 0x83, 0xc8, 0x40, 0x60, 0x88,
0xfd, 0xeb, 0x31, 0xea, 0x65, 0xe3, 0xf6, 0xc5, 0x1d, 0x7b, 0xbd, 0xbc,
0x4b, 0x60, 0x27, 0xcb, 0xf1, 0xe2, 0xd9, 0x09, 0x03, 0xf3, 0xfe, 0xd8,
0x5c, 0xc1, 0x70, 0xdb, 0x0e, 0xdc, 0xc3, 0x7a, 0xb2, 0x41, 0x07, 0xf6,
0x85, 0x26, 0x31, 0xed, 0xa3, 0x36, 0x80, 0x08, 0x4f, 0xf7, 0x02, 0x37,
0x6e, 0x06, 0x9b, 0x1a, 0x76, 0x47, 0x62, 0x86, 0xdc, 0x33, 0xab, 0xcc,
0x88, 0x77, 0x1c, 0x15, 0x43, 0xac, 0x72, 0x46, 0x73, 0x6e, 0x77, 0x28,
0x82, 0x75, 0xa0, 0x2f, 0xd4, 0x96, 0x1b, 0x1e, 0x2e, 0x63, 0x66, 0x6c,
0x75, 0x4f, 0xaa, 0xd0, 0x2c, 0xcc, 0xd3, 0x65, 0x85, 0xbe, 0x87, 0x6a,
0x8e, 0x72, 0x65, 0x57, 0x64, 0xb5, 0x79, 0x71, 0x92, 0x7f, 0xe9, 0x80,
0x08, 0xa3, 0xa3, 0x2d, 0xc0, 0x49, 0x89, 0x02, 0x81, 0x81, 0x00, 0xee,
0x13, 0x86, 0xc3, 0x48, 0xb1, 0x4c, 0x7d, 0xe2, 0x31, 0x6c, 0x16, 0x37,
0x72, 0x6f, 0x33, 0x9d, 0x17, 0xe4, 0x20, 0x91, 0xa3, 0x75, 0x42, 0x19,
0xc1, 0xdb, 0x60, 0x90, 0x00, 0x4f, 0x04, 0x33, 0x88, 0xe1, 0xb8, 0x6f,
0xdf, 0xde, 0x71, 0x34, 0xb1, 0xc8, 0x45, 0x16, 0x20, 0xac, 0x83, 0xd2,
0xfe, 0x4c, 0x87, 0xb8, 0xdb, 0xfa, 0x42, 0x8e, 0xf5, 0x08, 0x03, 0x77,
0xb3, 0x07, 0x17, 0xb2, 0x9b, 0xd1, 0x8c, 0xe8, 0xdc, 0x61, 0xb8, 0x82,
0xf1, 0xe2, 0xa5, 0x46, 0xb1, 0xc1, 0x62, 0x1a, 0x9d, 0xf7, 0x44, 0x65,
0xda, 0xe3, 0xa0, 0xe5, 0xd5, 0x30, 0xca, 0x28, 0x07, 0x2f, 0xd7, 0xba,
0x99, 0x9f, 0x2a, 0x16, 0xc7, 0xe8, 0x98, 0x00, 0x7e, 0xd5, 0x53, 0x3c,
0x29, 0x8a, 0x52, 0xd0, 0x93, 0xbe, 0xf7, 0xa9, 0x3a, 0x6e, 0x07, 0x28,
0x44, 0x15, 0x6f, 0x20, 0x22, 0x52, 0xe3, 0x02, 0x81, 0x81, 0x00, 0xd7,
0x0c, 0x1a, 0x8e, 0x0a, 0x11, 0x60, 0x12, 0xb0, 0x62, 0xfb, 0x71, 0x21,
0xc0, 0x92, 0x65, 0x3d, 0xa4, 0x44, 0x1b, 0xbf, 0x17, 0x50, 0x45, 0xe6,
0x19, 0x5f, 0x95, 0xda, 0x56, 0x12, 0x79, 0xc7, 0xcd, 0x8f, 0x07, 0x31,
0x51, 0x93, 0xb7, 0x31, 0xd7, 0xc3, 0x09, 0x46, 0x8f, 0xfc, 0xd2, 0x1c,
0xcd, 0x3c, 0xbc, 0x87, 0x54, 0x9d, 0xe8, 0xa4, 0xc1, 0xb6, 0xa4, 0x68,
0x5e, 0xfd, 0x03, 0x78, 0xef, 0x69, 0xac, 0xd9, 0x0e, 0x00, 0x6f, 0x29,
0xe8, 0x2b, 0x54, 0x62, 0x7f, 0x83, 0xe5, 0x5f, 0x9d, 0x83, 0xe2, 0x01,
0x33, 0x33, 0x28, 0x39, 0x8f, 0x83, 0xaf, 0x6d, 0x60, 0xd5, 0x6f, 0xec,
0xdb, 0x74, 0x5b, 0x87, 0x6e, 0x32, 0xe5, 0x51, 0x95, 0xbe, 0x08, 0xa5,
0x8a, 0xf8, 0x92, 0x09, 0xe8, 0xae, 0xca, 0x95, 0x16, 0x44, 0x95, 0x84,
0x52, 0xd8, 0x67, 0x1d, 0x31, 0x8c, 0x33, 0x02, 0x81, 0x81, 0x00, 0xe7,
0x34, 0x05, 0x52, 0xce, 0xdc, 0x87, 0xf9, 0x54, 0x5a, 0x44, 0xaa, 0x8a,
0xac, 0x52, 0x3b, 0xe0, 0x9a, 0x9c, 0x0b, 0xd9, 0x03, 0xd1, 0xd3, 0x20,
0xaa, 0x77, 0xbe, 0x9d, 0xf9, 0xfe, 0xc2, 0x88, 0xbd, 0xac, 0xdf, 0x6d,
0x9e, 0x0e, 0x2b, 0x08, 0x4e, 0x82, 0xbc, 0x3d, 0x11, 0xfc, 0x17, 0x85,
0x27, 0x3a, 0xf1, 0x2f, 0x60, 0x49, 0xf8, 0xab, 0x56, 0x60, 0xb2, 0xe5,
0x62, 0xf2, 0x47, 0x5c, 0x48, 0x20, 0x47, 0xe4, 0xb8, 0x69, 0x1a, 0x43,
0xe8, 0x5d, 0xff, 0xbd, 0xd8, 0xd0, 0x81, 0xd2, 0x71, 0x87, 0xf9, 0x5f,
0xa5, 0x24, 0x1c, 0x54, 0x37, 0x26, 0xcb, 0x9b, 0xf5, 0xe6, 0xcb, 0x6d,
0x46, 0xd5, 0x20, 0x8d, 0xc1, 0x14, 0x2b, 0xd1, 0x87, 0x5a, 0xea, 0x1b,
0x6a, 0x08, 0x10, 0x06, 0xc9, 0x04, 0xd3, 0x05, 0x00, 0x5e, 0x6c, 0x0a,
0xf9, 0x9b, 0x8b, 0x30, 0xbc, 0xc4, 0x9b, 0x02, 0x81, 0x80, 0x20, 0x16,
0x83, 0x43, 0xdc, 0x86, 0xb9, 0x32, 0x30, 0xb5, 0xa4, 0x55, 0x3e, 0x37,
0x10, 0xe1, 0x20, 0x70, 0x89, 0x65, 0x26, 0x7f, 0x61, 0x0f, 0xfd, 0x04,
0x9e, 0x39, 0xab, 0x09, 0x9a, 0xda, 0x27, 0x11, 0x2a, 0x1d, 0x65, 0xa3,
0x89, 0x8a, 0x15, 0x5a, 0xdf, 0x94, 0x5b, 0xbe, 0x12, 0x78, 0x7b, 0xa9,
0xb8, 0x3d, 0x5d, 0x68, 0x27, 0xe3, 0xd5, 0xe9, 0xbd, 0xca, 0x0c, 0x74,
0xd8, 0x06, 0x13, 0x9e, 0x8d, 0xc3, 0x27, 0xe4, 0x29, 0xf6, 0x6c, 0x67,
0x63, 0x47, 0xc5, 0x26, 0xc7, 0xd4, 0x8b, 0x0e, 0xe2, 0xe5, 0xef, 0x4d,
0xe7, 0x7d, 0x42, 0x11, 0x83, 0x11, 0xc3, 0x1d, 0x66, 0xdb, 0xbb, 0x99,
0x07, 0x64, 0xbc, 0xf1, 0x99, 0x90, 0x94, 0x3a, 0xe6, 0xcf, 0x3d, 0x7c,
0x5e, 0x18, 0xd4, 0x77, 0xae, 0xd5, 0x35, 0xa7, 0xcb, 0xf6, 0x0f, 0x77,
0x99, 0x28, 0xd1, 0xb7, 0x59, 0xf7, 0x02, 0x81, 0x80, 0x43, 0x4d, 0xf6,
0xfe, 0x87, 0x20, 0xfb, 0x31, 0xc4, 0x00, 0x83, 0xa2, 0x66, 0x63, 0xa9,
0xed, 0x4c, 0xff, 0x79, 0xd3, 0xdc, 0x5d, 0x9d, 0xad, 0xa2, 0x03, 0x66,
0x1b, 0x97, 0xe0, 0x44, 0xd0, 0xc0, 0x5e, 0xf4, 0x5d, 0xe4, 0xc9, 0x2a,
0xa0, 0x6e, 0x1d, 0x2e, 0xb0, 0x23, 0xf4, 0x7b, 0x1c, 0xaa, 0x5d, 0x86,
0xb9, 0xf1, 0x93, 0xf8, 0x32, 0x09, 0x74, 0x53, 0xfe, 0x90, 0x24, 0xfc,
0x35, 0x1e, 0x7a, 0x0e, 0x4a, 0x3b, 0x1e, 0x58, 0x49, 0x3e, 0x7e, 0xc8,
0x8a, 0xb1, 0x1c, 0xb0, 0xe1, 0x35, 0x1b, 0x9e, 0xc5, 0x59, 0x7c, 0x32,
0x3a, 0xab, 0x24, 0x5a, 0xb7, 0x70, 0x27, 0xf9, 0x62, 0x4b, 0x89, 0x35,
0x20, 0x0d, 0x10, 0xea, 0x76, 0x24, 0x91, 0xe6, 0x64, 0x02, 0xbc, 0xba,
0xf7, 0x59, 0x16, 0xc7, 0x41, 0xc0, 0xb7, 0xa4, 0x6d, 0xa4, 0xb9, 0xe6,
0x61, 0x66, 0x42, 0xbf, 0xf0};
// This is an RSA key where e*d != 1 mod phi. Instead, it uses the carmicahel
// totient. That means e*d = 1 mod lambda, where lambda = lcm(p-1, q-1).
static const uint8_t kTestKeyRSACarmichael_2048[] = {

View File

@@ -24,6 +24,7 @@
#include <iostream>
#include <map>
#include <string>
#include <sstream>
#include <utility>
#include <vector>
@@ -36,25 +37,21 @@
#include "oemcrypto_types.h"
#include "string_conversions.h"
#ifdef CDM_TESTS
#include "properties.h"
#endif
using ::testing::Bool;
using ::testing::Combine;
using ::testing::Range;
using ::testing::Values;
using ::testing::WithParamInterface;
using ::testing::tuple;
using namespace std;
using std::tr1::tuple;
namespace std { // GTest wants PrintTo to be in the std namespace.
void PrintTo(const tuple<OEMCrypto_CENCEncryptPatternDesc, OEMCryptoCipherMode,
bool>& param,
ostream* os) {
OEMCrypto_CENCEncryptPatternDesc pattern = std::tr1::get<0>(param);
OEMCryptoCipherMode mode = std::tr1::get<1>(param);
bool decrypt_inplace = std::tr1::get<2>(param);
OEMCrypto_CENCEncryptPatternDesc pattern = ::testing::get<0>(param);
OEMCryptoCipherMode mode = ::testing::get<1>(param);
bool decrypt_inplace = ::testing::get<2>(param);
*os << ((mode == OEMCrypto_CipherMode_CTR) ? "CTR mode" : "CBC mode")
<< ", encrypt=" << pattern.encrypt << ", skip=" << pattern.skip
<< ", decrypt in place = " << (decrypt_inplace ? "true" : "false");
@@ -76,9 +73,6 @@ class OEMCryptoClientTest : public ::testing::Test, public SessionUtil {
virtual void SetUp() {
::testing::Test::SetUp();
#ifdef CDM_TESTS
wvcdm::Properties::Init();
#endif
wvcdm::g_cutoff = wvcdm::LOG_INFO;
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
@@ -451,7 +445,21 @@ TEST_F(OEMCryptoClientTest, CanLoadTestKeys) {
<< "Session tests cannot run with out a test keybox or RSA cert.";
}
class OEMCryptoKeyboxTest : public OEMCryptoClientTest {};
class OEMCryptoKeyboxTest : public OEMCryptoClientTest {
virtual void SetUp() {
OEMCryptoClientTest::SetUp();
OEMCryptoResult sts = OEMCrypto_IsKeyboxValid();
// If the production keybox is valid, use it for these tests. Most of the
// other tests will use a test keybox anyway, but it's nice to check the
// device ID for the real keybox if we can.
if (sts == OEMCrypto_SUCCESS) return;
printf("Production keybox is NOT valid. All tests use test keybox.\n");
ASSERT_EQ(
OEMCrypto_SUCCESS,
OEMCrypto_LoadTestKeybox(reinterpret_cast<const uint8_t*>(&kTestKeybox),
sizeof(kTestKeybox)));
}
};
TEST_F(OEMCryptoKeyboxTest, NormalGetDeviceId) {
OEMCryptoResult sts;
@@ -530,6 +538,11 @@ TEST_F(OEMCryptoProv30Test, DeviceClaimsOEMCertificate) {
ASSERT_EQ(OEMCrypto_OEMCertificate, OEMCrypto_GetProvisioningMethod());
}
// The OEM certificate must be valid.
TEST_F(OEMCryptoProv30Test, CertValidAPI15) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxOrOEMCertValid());
}
TEST_F(OEMCryptoProv30Test, OEMCertValid) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
@@ -1654,9 +1667,9 @@ class OEMCryptoSessionTestsDecryptTests
protected:
virtual void SetUp() {
OEMCryptoSessionTests::SetUp();
pattern_ = std::tr1::get<0>(GetParam());
cipher_mode_ = std::tr1::get<1>(GetParam());
decrypt_inplace_ = std::tr1::get<2>(GetParam());
pattern_ = ::testing::get<0>(GetParam());
cipher_mode_ = ::testing::get<1>(GetParam());
decrypt_inplace_ = ::testing::get<2>(GetParam());
}
void FindTotalSize() {
@@ -1849,9 +1862,9 @@ class OEMCryptoSessionTestsPartialBlockTests
: public OEMCryptoSessionTestsDecryptTests {};
TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) {
// This subsample size should be larger a few encrypt/skip patterns. Most
// This subsample size is larger than a few encrypt/skip patterns. Most
// test cases use a pattern length of 160, so we'll run through at least two
// full patterns.
// full patterns if we have more than 320 -- round up to 400.
subsample_size_.push_back(SampleSize(0, 400));
FindTotalSize();
vector<uint8_t> unencryptedData(total_size_);
@@ -2030,6 +2043,21 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptLargeBuffer) {
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
}
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptSmallBuffer) {
// There are probably no frames this small, but we should handle them anyway.
subsample_size_.push_back(SampleSize(5, 5));
FindTotalSize();
vector<uint8_t> unencryptedData(total_size_);
vector<uint8_t> encryptedData(total_size_);
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
vector<uint8_t> key(AES_BLOCK_SIZE);
EXPECT_EQ(1, GetRandBytes(&encryptionIv[0], AES_BLOCK_SIZE));
EXPECT_EQ(1, GetRandBytes(&key[0], AES_BLOCK_SIZE));
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
}
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptUnencrypted) {
subsample_size_.push_back(SampleSize(256, 0));
FindTotalSize();
@@ -2515,6 +2543,41 @@ TEST_F(OEMCryptoLoadsCertificate, TestCarmichaelRSAKey) {
ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR());
}
// This tests that two sessions can use different RSA keys simultaneously.
TEST_F(OEMCryptoLoadsCertificate, TestMultipleRSAKeys) {
CreateWrappedRSAKey(kSign_RSASSA_PSS, true);
Session s1; // Session s1 loads the default rsa key, but doesn't use it
// until after s2 uses its key.
ASSERT_NO_FATAL_FAILURE(s1.open());
ASSERT_NO_FATAL_FAILURE(s1.PreparePublicKey(&encoded_rsa_key_[0],
encoded_rsa_key_.size()));
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_LoadDeviceRSAKey(s1.session_id(), &wrapped_rsa_key_[0],
wrapped_rsa_key_.size()));
Session s2; // Session s2 uses a different rsa key.
encoded_rsa_key_.assign(kTestRSAPKCS8PrivateKeyInfo4_2048,
kTestRSAPKCS8PrivateKeyInfo4_2048 +
sizeof(kTestRSAPKCS8PrivateKeyInfo4_2048));
CreateWrappedRSAKey(kSign_RSASSA_PSS, true);
ASSERT_NO_FATAL_FAILURE(s2.open());
ASSERT_NO_FATAL_FAILURE(s2.PreparePublicKey(&encoded_rsa_key_[0],
encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(s2.InstallRSASessionTestKey(wrapped_rsa_key_));
ASSERT_NO_FATAL_FAILURE(s2.FillSimpleMessage(kDuration, 0, 0));
ASSERT_NO_FATAL_FAILURE(s2.EncryptAndSign());
ASSERT_NO_FATAL_FAILURE(s2.LoadTestKeys());
ASSERT_NO_FATAL_FAILURE(s2.TestDecryptCTR());
s2.close();
// After s2 has loaded its rsa key, we continue using s1's key.
ASSERT_NO_FATAL_FAILURE(s1.GenerateDerivedKeysFromSessionKey());
ASSERT_NO_FATAL_FAILURE(s1.FillSimpleMessage(kDuration, 0, 0));
ASSERT_NO_FATAL_FAILURE(s1.EncryptAndSign());
ASSERT_NO_FATAL_FAILURE(s1.LoadTestKeys());
ASSERT_NO_FATAL_FAILURE(s1.TestDecryptCTR());
}
// Devices that load certificates, should at least support RSA 2048 keys.
TEST_F(OEMCryptoLoadsCertificate, SupportsCertificatesAPI13) {
ASSERT_NE(0u,
@@ -4528,6 +4591,30 @@ TEST_P(UsageTableTestWithMAC, OnlineLicense) {
s.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
}
TEST_P(UsageTableTestWithMAC, OnlineLicenseUnused) {
std::string pst = "my_pst";
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage(
0, wvoec::kControlNonceEnabled | wvoec::kControlNonceRequired,
s.get_nonce(), pst));
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
ASSERT_NO_FATAL_FAILURE(s.CreateNewUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_));
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
// No decrypt. We do not use this license.
ASSERT_NO_FATAL_FAILURE(s.GenerateVerifyReport(pst, kUnused));
// Flag the entry as inactive.
ASSERT_NO_FATAL_FAILURE(s.DeactivateUsageEntry(pst));
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
// It should report as inactive.
ASSERT_NO_FATAL_FAILURE(s.GenerateVerifyReport(pst, kInactiveUnused));
// Decrypt should fail.
ASSERT_NO_FATAL_FAILURE(
s.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
}
TEST_P(UsageTableTestWithMAC, ForbidReportWithNoUpdate) {
std::string pst = "my_pst";
Session s;
@@ -4657,65 +4744,6 @@ TEST_F(UsageTableTest, OnlineMissingEntry) {
ASSERT_NO_FATAL_FAILURE(s.close());
}
TEST_F(UsageTableTest, TwoHundredEntries) {
Session s1;
ASSERT_NO_FATAL_FAILURE(s1.open());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s1));
std::string pst1 = "pst saved";
ASSERT_NO_FATAL_FAILURE(s1.FillSimpleMessage(
0, wvoec::kControlNonceEnabled | wvoec::kControlNonceRequired,
s1.get_nonce(), pst1));
ASSERT_NO_FATAL_FAILURE(s1.EncryptAndSign());
ASSERT_NO_FATAL_FAILURE(s1.CreateNewUsageEntry());
ASSERT_EQ(0u, s1.usage_entry_number());
time_t start = time(NULL);
ASSERT_NO_FATAL_FAILURE(s1.LoadTestKeys(pst1, new_mac_keys_));
ASSERT_NO_FATAL_FAILURE(s1.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(s1.close());
const size_t ENTRY_COUNT = 200; // API says should hold at least 200 entries.
vector<Session> sessions(ENTRY_COUNT);
for (size_t i = 0; i < ENTRY_COUNT; i++) {
ASSERT_NO_FATAL_FAILURE(sessions[i].open());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&sessions[i]));
std::string pst = "pst ";
char c1 = 'A' + (i/26);
char c2 = 'A' + (i%26);
pst = pst + c1 + c2;
ASSERT_NO_FATAL_FAILURE(sessions[i].FillSimpleMessage(
0, wvoec::kControlNonceOrEntry, sessions[i].get_nonce(), pst));
ASSERT_NO_FATAL_FAILURE(sessions[i].EncryptAndSign());
ASSERT_NO_FATAL_FAILURE(sessions[i].CreateNewUsageEntry());
ASSERT_EQ(sessions[i].usage_entry_number(), i + 1);
ASSERT_NO_FATAL_FAILURE(sessions[i].LoadTestKeys(pst, new_mac_keys_));
ASSERT_NO_FATAL_FAILURE(
sessions[i].UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(sessions[i].close());
}
sleep(kShortSleep);
for (size_t i = 0; i < ENTRY_COUNT; i++) {
ASSERT_NO_FATAL_FAILURE(sessions[i].open());
std::string pst = "pst ";
char c1 = 'A' + (i/26);
char c2 = 'A' + (i%26);
pst = pst + c1 + c2;
// Reuse license message created above.
ASSERT_NO_FATAL_FAILURE(sessions[i].ReloadUsageEntry());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&sessions[i]));
ASSERT_NO_FATAL_FAILURE(sessions[i].LoadTestKeys(pst, new_mac_keys_))
<< "Failed to reload license " << i << " with pst = " << pst;
ASSERT_NO_FATAL_FAILURE(
sessions[i].UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(sessions[i].close());
}
// Make sure s1's entry is still in the table.
ASSERT_NO_FATAL_FAILURE(s1.open());
ASSERT_NO_FATAL_FAILURE(s1.ReloadUsageEntry());
ASSERT_NO_FATAL_FAILURE(s1.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(s1.GenerateVerifyReport(pst1, kUnused, start));
ASSERT_NO_FATAL_FAILURE(s1.close());
}
TEST_P(UsageTableTestWithMAC, GenericCryptoEncrypt) {
std::string pst = "A PST";
uint32_t nonce = session_.get_nonce();
@@ -5122,6 +5150,49 @@ TEST_P(UsageTableTestWithMAC, DeactivateOfflineLicense) {
EXPECT_EQ(kInactiveUsed, s3.pst_report().status());
}
TEST_P(UsageTableTestWithMAC, DeactivateOfflineLicenseUnused) {
std::string pst = "my_pst";
Session s1;
ASSERT_NO_FATAL_FAILURE(LoadOfflineLicense(s1, pst));
ASSERT_NO_FATAL_FAILURE(s1.open());
ASSERT_NO_FATAL_FAILURE(s1.ReloadUsageEntry());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s1));
ASSERT_NO_FATAL_FAILURE(
s1.LoadTestKeys(pst, new_mac_keys_)); // Reload the license
// No Decrypt. This license is unused.
ASSERT_NO_FATAL_FAILURE(s1.DeactivateUsageEntry(pst)); // Then deactivate.
// After deactivate, should not be able to decrypt.
ASSERT_NO_FATAL_FAILURE(
s1.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
ASSERT_NO_FATAL_FAILURE(s1.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(s1.GenerateVerifyReport(pst, kInactiveUnused));
ASSERT_NO_FATAL_FAILURE(s1.close());
Session s2;
ASSERT_NO_FATAL_FAILURE(s2.open());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s2));
ASSERT_NO_FATAL_FAILURE(s2.LoadUsageEntry(s1));
// Offline license can not be reused if it has been deactivated.
uint8_t* pst_ptr = s1.encrypted_license().pst;
EXPECT_NE(
OEMCrypto_SUCCESS,
OEMCrypto_LoadKeys(s2.session_id(), s1.message_ptr(), s1.message_size(),
&s1.signature()[0], s1.signature().size(),
s1.encrypted_license().mac_key_iv,
s1.encrypted_license().mac_keys, s1.num_keys(),
s1.key_array(), pst_ptr, pst.length(), NULL,
OEMCrypto_ContentLicense));
s2.close();
// But we can still generate a report.
Session s3;
ASSERT_NO_FATAL_FAILURE(s3.open());
ASSERT_NO_FATAL_FAILURE(s3.LoadUsageEntry(s1));
ASSERT_NO_FATAL_FAILURE(s3.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(s3.GenerateReport(pst, OEMCrypto_SUCCESS, &s1));
EXPECT_EQ(kInactiveUnused, s3.pst_report().status());
}
TEST_P(UsageTableTestWithMAC, BadRange) {
std::string pst = "my_pst";
Session s;
@@ -5347,6 +5418,95 @@ TEST_F(UsageTableDefragTest, ReloadUsageEntryBadData) {
&data[0], data.size()));
}
static std::string MakePST(size_t n) {
std::stringstream stream;
stream << "pst-" << n;
return stream.str();
}
TEST_F(UsageTableDefragTest, TwoHundredEntries) {
// OEMCrypto is required to store at least 200 entries in the usage table
// header, but it is allowed to store more. This test verifies that if we keep
// adding entries, the error indicates a resource limit. It then verifies
// that all of the successful entries are still valid after we throw out the
// last invalid entry.
const size_t ENTRY_COUNT = 2000;
vector<Session> sessions(ENTRY_COUNT);
size_t successful_count = 0;
for (size_t i = 0; i < ENTRY_COUNT; i++) {
if (i % 50 == 0) LOGD("Creating license %zd", i);
ASSERT_NO_FATAL_FAILURE(sessions[i].open());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&sessions[i]));
std::string pst = MakePST(i);
ASSERT_NO_FATAL_FAILURE(sessions[i].FillSimpleMessage(
0, wvoec::kControlNonceOrEntry, sessions[i].get_nonce(), pst));
ASSERT_NO_FATAL_FAILURE(sessions[i].EncryptAndSign());
// We attempt to create a new usage table entry for this session.
OEMCryptoResult status;
ASSERT_NO_FATAL_FAILURE(sessions[i].CreateNewUsageEntry(&status));
if (status == OEMCrypto_SUCCESS) {
ASSERT_EQ(sessions[i].usage_entry_number(), i);
ASSERT_NO_FATAL_FAILURE(sessions[i].LoadTestKeys(pst, new_mac_keys_));
ASSERT_NO_FATAL_FAILURE(
sessions[i].UpdateUsageEntry(&encrypted_usage_header_));
successful_count++;
} else {
// If we failed to create this many entries because of limited resources,
// then the error returned should be insufficient resources.
EXPECT_EQ(OEMCrypto_ERROR_INSUFFICIENT_RESOURCES, status)
<< "Failed to create license " << i << " with pst = " << pst;
break;
}
ASSERT_NO_FATAL_FAILURE(sessions[i].close());
}
LOGD("successful_count = %d", successful_count);
EXPECT_GE(successful_count, 200u);
sleep(kShortSleep);
// Now we will loop through each valid entry, and verify that we can still
// reload the license and perform a decrypt.
for (size_t i = 0; i < successful_count; i++) {
if (i % 50 == 0) LOGD("Reloading license %zd", i);
ASSERT_NO_FATAL_FAILURE(sessions[i].open());
std::string pst = MakePST(i);
// Reuse license message created above.
ASSERT_NO_FATAL_FAILURE(sessions[i].ReloadUsageEntry());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&sessions[i]));
ASSERT_NO_FATAL_FAILURE(sessions[i].LoadTestKeys(pst, new_mac_keys_))
<< "Failed to reload license " << i << " with pst = " << pst;
ASSERT_NO_FATAL_FAILURE(
sessions[i].UpdateUsageEntry(&encrypted_usage_header_))
<< "Failed to update license " << i << " with pst = " << pst;
ASSERT_NO_FATAL_FAILURE(sessions[i].TestDecryptCTR())
<< "Failed to use license " << i << " with pst = " << pst;
ASSERT_NO_FATAL_FAILURE(
sessions[i].UpdateUsageEntry(&encrypted_usage_header_))
<< "Failed to update license " << i << " with pst = " << pst;
ASSERT_NO_FATAL_FAILURE(sessions[i].close());
}
// We also need to verify that a full table can be shrunk, and the remaining
// licenses still work.
size_t smaller_size = 10u; // 10 is smaller than 200.
ASSERT_NO_FATAL_FAILURE(ShrinkHeader(smaller_size));
for (size_t i = 0; i < smaller_size; i++) {
ASSERT_NO_FATAL_FAILURE(sessions[i].open());
std::string pst = MakePST(i);
// Reuse license message created above.
ASSERT_NO_FATAL_FAILURE(sessions[i].ReloadUsageEntry());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&sessions[i]));
ASSERT_NO_FATAL_FAILURE(sessions[i].LoadTestKeys(pst, new_mac_keys_))
<< "Failed to reload license " << i << " with pst = " << pst;
ASSERT_NO_FATAL_FAILURE(
sessions[i].UpdateUsageEntry(&encrypted_usage_header_))
<< "Failed to update license " << i << " with pst = " << pst;
ASSERT_NO_FATAL_FAILURE(sessions[i].TestDecryptCTR())
<< "Failed to use license " << i << " with pst = " << pst;
ASSERT_NO_FATAL_FAILURE(
sessions[i].UpdateUsageEntry(&encrypted_usage_header_))
<< "Failed to update license " << i << " with pst = " << pst;
ASSERT_NO_FATAL_FAILURE(sessions[i].close());
}
}
TEST_F(UsageTableTest, CopyOldEntries) {
// First create three old entries. We open sessions first to force creation
// of the mac keys.

View File

@@ -40,6 +40,12 @@ TEST_F(OEMCryptoAndroidLMPTest, GetKeyDataImplemented) {
}
}
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);
@@ -142,10 +148,10 @@ TEST_F(OEMCryptoAndroidOCTest, MinVersionNumber13) {
ASSERT_GE(version, 13u);
}
// These tests are required for Pi MR1 Android devices.
class OEMCryptoAndroidPiMR1Test : public OEMCryptoAndroidOCTest {};
// These tests are required for Q Android devices.
class OEMCryptoAndroidQTest : public OEMCryptoAndroidOCTest {};
TEST_F(OEMCryptoAndroidPiMR1Test, MinVersionNumber14) {
TEST_F(OEMCryptoAndroidQTest, MinVersionNumber14) {
uint32_t version = OEMCrypto_APIVersion();
ASSERT_GE(version, 14u);
}

View File

@@ -4,9 +4,6 @@
#include "OEMCryptoCENC.h"
#include "log.h"
#include "oec_device_features.h"
#ifdef CDM_TESTS
#include "properties.h"
#endif
static void acknowledge_cast() {
std::cout
@@ -17,9 +14,6 @@ static void acknowledge_cast() {
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
#ifdef CDM_TESTS
wvcdm::Properties::Init();
#endif
wvcdm::g_cutoff = wvcdm::LOG_INFO;
bool is_cast_receiver = false;
bool force_load_test_keybox = false;

View File

@@ -1,4 +1,6 @@
// Copyright 2013 Google Inc. All Rights Reserved.
// 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.
//
// Clock - Platform independent interface for a time library
//

View File

@@ -1,4 +1,6 @@
// Copyright 2018 Google Inc. All Rights Reserved.
// 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.
#ifndef WVCDM_UTIL_DISALLOW_COPY_AND_ASSIGN_H_
#define WVCDM_UTIL_DISALLOW_COPY_AND_ASSIGN_H_

View File

@@ -1,4 +1,6 @@
// Copyright 2013 Google Inc. All Rights Reserved.
// 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.
//
// File - Platform independent interface for a File class
//

View File

@@ -1,4 +1,6 @@
// Copyright 2013 Google Inc. All Rights Reserved.
// 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.
//
// Lock - Platform independent interface for a Mutex class
//

View File

@@ -1,4 +1,6 @@
// Copyright 2013 Google Inc. All Rights Reserved.
// 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.
//
// Log - Platform independent interface for a Logging class
//

View File

@@ -1,4 +1,6 @@
// Copyright 2013 Google Inc. All Rights Reserved.
// 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.
#ifndef WVCDM_UTIL_STRING_CONVERSIONS_H_
#define WVCDM_UTIL_STRING_CONVERSIONS_H_

View File

@@ -1,4 +1,6 @@
// Copyright 2013 Google Inc. All Rights Reserved.
// 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 "string_conversions.h"