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

View File

@@ -1,5 +1,5 @@
# Reference OEMCrypto # Reference OEMCrypto
This directory contains a testing-only implementation of OEMCrypto. **This 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.** on devices.**

View File

@@ -31,8 +31,6 @@
'<(oemcrypto_dir)/ref/src/wvcrc.cpp', '<(oemcrypto_dir)/ref/src/wvcrc.cpp',
# TODO(fredgc) remove these: # 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', '<(oemcrypto_dir)/ref/src/oemcrypto_engine_device_properties.cpp',
], ],
'dependencies': [ 'dependencies': [

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#include "oemcrypto_auth_ref.h" #include "oemcrypto_auth_ref.h"
@@ -10,14 +10,13 @@
#include "keys.h" #include "keys.h"
#include "log.h" #include "log.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_rsa_key_shared.h" #include "oemcrypto_rsa_key_shared.h"
namespace { namespace {
// A 2048 bit RSA key in PKCS#8 PrivateKeyInfo format // 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[] = { static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = {
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 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 // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#ifndef OEMCRYPTO_AUTH_REF_H_ #ifndef OEMCRYPTO_AUTH_REF_H_
#define OEMCRYPTO_AUTH_REF_H_ #define OEMCRYPTO_AUTH_REF_H_
@@ -67,7 +67,7 @@ class AuthenticationRoot {
WvKeybox& real_keybox() { return keybox_; } WvKeybox& real_keybox() { return keybox_; }
WvKeybox keybox_; WvKeybox keybox_;
WvTestKeybox test_keybox_; WvKeybox test_keybox_;
bool use_test_keybox_; bool use_test_keybox_;
RSA_shared_ptr rsa_key_; // If no keybox, this is baked in certificate. 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 // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#include "oemcrypto_engine_ref.h" #include "oemcrypto_engine_ref.h"

View File

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

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
// This file contains oemcrypto engine properties that would be for a device // This file contains oemcrypto engine properties that would be for a device
// that does not have persistant storage or a keybox. // 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 // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
// This file contains oemcrypto engine properties that would be for a // This file contains oemcrypto engine properties that would be for a
// level 2 device that does not have persistant storage or a keybox. // 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 // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#include "oemcrypto_engine_ref.h" #include "oemcrypto_engine_ref.h"
@@ -30,7 +30,7 @@ namespace wvoec_ref {
CryptoEngine::CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system) CryptoEngine::CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system)
: root_of_trust_(config_provisioning_method()), : root_of_trust_(config_provisioning_method()),
file_system_(file_system), file_system_(file_system),
usage_table_(this) { usage_table_(NULL) {
ERR_load_crypto_strings(); ERR_load_crypto_strings();
} }
@@ -44,16 +44,25 @@ CryptoEngine::~CryptoEngine() {
ERR_free_strings(); ERR_free_strings();
} }
SessionId CryptoEngine::CreateSession() { bool CryptoEngine::Initialize() {
wvcdm::AutoLock lock(session_table_lock_); usage_table_.reset(MakeUsageTable());
static int unique_id = 1; return true;
SessionId sid = (SessionId)++unique_id;
SessionContext* sctx =
new SessionContext(this, sid, root_of_trust_.SharedRsaKey());
sessions_[sid] = sctx;
return sid;
} }
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) { bool CryptoEngine::DestroySession(SessionId sid) {
SessionContext* sctx = FindSession(sid); SessionContext* sctx = FindSession(sid);
wvcdm::AutoLock lock(session_table_lock_); wvcdm::AutoLock lock(session_table_lock_);

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#ifndef REF_OEMCRYPTO_ENGINE_REF_H_ #ifndef REF_OEMCRYPTO_ENGINE_REF_H_
#define REF_OEMCRYPTO_ENGINE_REF_H_ #define REF_OEMCRYPTO_ENGINE_REF_H_
@@ -15,7 +15,7 @@
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include "OEMCryptoCENC.h" // Needed for enums only. #include "OEMCryptoCENC.h"
#include "file_store.h" #include "file_store.h"
#include "lock.h" #include "lock.h"
#include "oemcrypto_auth_ref.h" #include "oemcrypto_auth_ref.h"
@@ -42,7 +42,7 @@ class CryptoEngine {
virtual ~CryptoEngine(); virtual ~CryptoEngine();
virtual bool Initialize() { return true; } virtual bool Initialize();
bool ValidRootOfTrust() { return root_of_trust_.Validate(); } bool ValidRootOfTrust() { return root_of_trust_.Validate(); }
@@ -58,8 +58,8 @@ class CryptoEngine {
KeyboxError ValidateKeybox() { return root_of_trust_.ValidateKeybox(); } KeyboxError ValidateKeybox() { return root_of_trust_.ValidateKeybox(); }
const std::vector<uint8_t>& DeviceRootKey(bool override_to_real = false) { const std::vector<uint8_t>& DeviceRootKey() {
return root_of_trust_.DeviceKey(override_to_real); return root_of_trust_.DeviceKey();
} }
const std::vector<uint8_t>& DeviceRootId() { const std::vector<uint8_t>& DeviceRootId() {
@@ -74,7 +74,7 @@ class CryptoEngine {
virtual void Terminate() {} virtual void Terminate() {}
SessionId CreateSession(); virtual SessionId OpenSession();
bool DestroySession(SessionId sid); bool DestroySession(SessionId sid);
@@ -94,7 +94,21 @@ class CryptoEngine {
// Returns the max HDCP version supported. // Returns the max HDCP version supported.
virtual OEMCrypto_HDCP_Capability config_maximum_hdcp_capability(); 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(); } wvcdm::FileSystem* file_system() { return file_system_.get(); }
// If config_local_display_only() returns true, we pretend we are using a // 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. // Rate limit for nonce generation. Default to 20 nonce/second.
virtual int nonce_flood_count() { return 20; } 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. // Set destination pointer based on the output destination description.
OEMCryptoResult SetDestination(OEMCrypto_DestBufferDesc* out_description, OEMCryptoResult SetDestination(OEMCrypto_DestBufferDesc* out_description,
size_t data_length, uint8_t subsample_flags); size_t data_length, uint8_t subsample_flags);
@@ -172,14 +190,14 @@ class CryptoEngine {
protected: protected:
explicit CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system); explicit CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system);
virtual SessionContext* MakeSession(SessionId sid);
virtual UsageTable* MakeUsageTable();
uint8_t* destination_; uint8_t* destination_;
private:
ActiveSessions sessions_; ActiveSessions sessions_;
AuthenticationRoot root_of_trust_; AuthenticationRoot root_of_trust_;
wvcdm::Lock session_table_lock_; wvcdm::Lock session_table_lock_;
scoped_ptr<wvcdm::FileSystem> file_system_; scoped_ptr<wvcdm::FileSystem> file_system_;
UsageTable usage_table_; scoped_ptr<UsageTable> usage_table_;
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine); CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
}; };

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#include "oemcrypto_key_ref.h" #include "oemcrypto_key_ref.h"
#include "oemcrypto_types.h" #include "oemcrypto_types.h"
@@ -11,7 +11,6 @@
#include <vector> #include <vector>
#include "log.h" #include "log.h"
#include "oemcrypto_logging.h"
namespace wvoec_ref { namespace wvoec_ref {
@@ -55,61 +54,6 @@ KeyControlBlock::KeyControlBlock(
duration_ = ExtractField(key_control_string, 1); duration_ = ExtractField(key_control_string, 1);
nonce_ = ExtractField(key_control_string, 2); nonce_ = ExtractField(key_control_string, 2);
control_bits_ = ExtractField(key_control_string, 3); 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(); Validate();
} }

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#ifndef OEMCRYPTO_KEY_REF_H_ #ifndef OEMCRYPTO_KEY_REF_H_
#define 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 // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#include "oemcrypto_keybox_ref.h" #include "oemcrypto_keybox_ref.h"
@@ -10,54 +10,17 @@
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <string> #include <string>
#include "log.h" #include "log.h"
#include "oemcrypto_types.h" #include "oemcrypto_types.h"
#include "wvcrc32.h" #include "wvcrc32.h"
namespace wvoec_ref { namespace wvoec_ref {
namespace { WvKeybox::WvKeybox() : loaded_(false) {}
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();
}
KeyboxError WvKeybox::Validate() { KeyboxError WvKeybox::Validate() {
if (!valid_) { if (!loaded_) {
LOGE("[KEYBOX NOT LOADED]"); LOGE("[KEYBOX NOT LOADED]");
return OTHER_ERROR; return OTHER_ERROR;
} }
@@ -67,7 +30,7 @@ KeyboxError WvKeybox::Validate() {
} }
uint32_t crc_computed; uint32_t crc_computed;
uint32_t crc_stored; 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_)); memcpy(crc_stored_bytes, crc_, sizeof(crc_));
wvoec::WidevineKeybox keybox; wvoec::WidevineKeybox keybox;
memset(&keybox, 0, sizeof(keybox)); memset(&keybox, 0, sizeof(keybox));
@@ -90,25 +53,18 @@ bool WvKeybox::InstallKeybox(const uint8_t* buffer, size_t keyBoxLength) {
if (keyBoxLength != 128) { if (keyBoxLength != 128) {
return false; return false;
} }
const wvoec::WidevineKeybox* keybox =
const wvoec::WidevineKeybox* keybox reinterpret_cast<const wvoec::WidevineKeybox*>(buffer);
= reinterpret_cast<const wvoec::WidevineKeybox*>(buffer); size_t device_id_length =
size_t device_id_length strnlen(reinterpret_cast<const char*>(keybox->device_id_), 32);
= strnlen(reinterpret_cast<const char*>(keybox->device_id_), 32); device_id_.assign(keybox->device_id_, keybox->device_id_ + device_id_length);
device_id_.assign(keybox->device_id_,
keybox->device_id_ + device_id_length);
device_key_.assign(keybox->device_key_, device_key_.assign(keybox->device_key_,
keybox->device_key_ + sizeof(keybox->device_key_)); keybox->device_key_ + sizeof(keybox->device_key_));
memcpy(key_data_, keybox->data_, sizeof(keybox->data_)); memcpy(key_data_, keybox->data_, sizeof(keybox->data_));
memcpy(magic_, keybox->magic_, sizeof(keybox->magic_)); memcpy(magic_, keybox->magic_, sizeof(keybox->magic_));
memcpy(crc_, keybox->crc_, sizeof(keybox->crc_)); memcpy(crc_, keybox->crc_, sizeof(keybox->crc_));
loaded_ = true;
return true; return true;
} }
WvTestKeybox::WvTestKeybox() {
InstallKeybox(reinterpret_cast<const uint8_t*>(&kTestKeybox),
sizeof(kTestKeybox));
}
} // namespace wvoec_ref } // namespace wvoec_ref

View File

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

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#ifndef REF_OEMCRYPTO_NONCE_TABLE_H_ #ifndef REF_OEMCRYPTO_NONCE_TABLE_H_
#define 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 // source code may only be used and distributed under the Widevine Master
// License Agreement. // 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 // 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 // devices that upgrade from v12 to v13 in the field, and need to convert from
@@ -23,7 +23,6 @@
#include "file_store.h" #include "file_store.h"
#include "log.h" #include "log.h"
#include "oemcrypto_engine_ref.h" #include "oemcrypto_engine_ref.h"
#include "oemcrypto_logging.h"
// TODO(fredgc): Setting the device files base bath is currently broken as // TODO(fredgc): Setting the device files base bath is currently broken as
// wvcdm::Properties is no longer used by the reference code. // wvcdm::Properties is no longer used by the reference code.
//#include "properties.h" //#include "properties.h"
@@ -72,9 +71,6 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
}*/ }*/
std::string filename = path + "UsageTable.dat"; std::string filename = path + "UsageTable.dat";
if (!file_system->Exists(filename)) { if (!file_system->Exists(filename)) {
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
LOGI("OldUsageTable: No saved usage table. Creating new table.");
}
return; return;
} }
@@ -98,8 +94,7 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
// This should be encrypted and signed with a device specific key. // This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox 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();
const std::vector<uint8_t> &key = ce_->DeviceRootKey(override_to_real);
uint8_t computed_signature[SHA256_DIGEST_LENGTH]; uint8_t computed_signature[SHA256_DIGEST_LENGTH];
unsigned int sig_length = sizeof(computed_signature); 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->Read(reinterpret_cast<char *>(&generation_), sizeof(int64_t));
file->Close(); file->Close();
if (stored_table->generation == generation_ + 1) { if ((stored_table->generation > generation_ + 1) ||
if (LogCategoryEnabled(kLoggingTraceUsageTable)) { (stored_table->generation < generation_ - 1)) {
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_) {
LOGE("OldUsageTable: Rollback detected. Clearing Usage Table. %lx -> %lx", LOGE("OldUsageTable: Rollback detected. Clearing Usage Table. %lx -> %lx",
generation_, stored_table->generation); generation_, stored_table->generation);
table_.clear(); table_.clear();
@@ -168,9 +155,6 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
new OldUsageTableEntry(&stored_table->entries[i].entry); new OldUsageTableEntry(&stored_table->entries[i].entry);
table_[entry->pst_hash()] = 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) { 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 // source code may only be used and distributed under the Widevine Master
// License Agreement. // 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 // 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 // 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 "file_store.h"
#include "log.h" #include "log.h"
#include "oemcrypto_engine_ref.h" #include "oemcrypto_engine_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_session.h" #include "oemcrypto_session.h"
#include "oemcrypto_usage_table_ref.h" #include "oemcrypto_usage_table_ref.h"
#include "string_conversions.h" #include "string_conversions.h"
@@ -58,9 +57,6 @@ typedef struct {
} WrappedRSAKey; } WrappedRSAKey;
extern "C" OEMCryptoResult OEMCrypto_Initialize(void) { extern "C" OEMCryptoResult OEMCrypto_Initialize(void) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("------------------------- OEMCrypto_Initialize(void)\n");
}
if (crypto_engine) { if (crypto_engine) {
LOGE("------------------------- Calling Initialize without Terminate\n"); LOGE("------------------------- Calling Initialize without Terminate\n");
delete crypto_engine; delete crypto_engine;
@@ -75,17 +71,10 @@ extern "C" OEMCryptoResult OEMCrypto_Initialize(void) {
LOGE("[OEMCrypto_Initialize(): failed]"); LOGE("[OEMCrypto_Initialize(): failed]");
return OEMCrypto_ERROR_INIT_FAILED; return OEMCrypto_ERROR_INIT_FAILED;
} }
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_Initialize(): success]");
}
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
extern "C" OEMCryptoResult OEMCrypto_Terminate(void) { extern "C" OEMCryptoResult OEMCrypto_Terminate(void) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("----------------- OEMCryptoResult OEMCrypto_Terminate(void)\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("[OEMCrypto_Terminate(): not initialized]"); LOGE("[OEMCrypto_Terminate(): not initialized]");
return OEMCrypto_ERROR_TERMINATE_FAILED; return OEMCrypto_ERROR_TERMINATE_FAILED;
@@ -94,18 +83,10 @@ extern "C" OEMCryptoResult OEMCrypto_Terminate(void) {
delete crypto_engine; delete crypto_engine;
crypto_engine = NULL; crypto_engine = NULL;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_Terminate(): success]");
}
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
extern "C" OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) { extern "C" OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI(
"-- OEMCryptoResult OEMCrypto_OpenSession"
"(OEMCrypto_SESSION *session)\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_OpenSession: OEMCrypto not initialized."); LOGE("OEMCrypto_OpenSession: OEMCrypto not initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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]"); LOGE("[OEMCrypto_OpenSession(): failed due to too many sessions]");
return OEMCrypto_ERROR_TOO_MANY_SESSIONS; return OEMCrypto_ERROR_TOO_MANY_SESSIONS;
} }
SessionId sid = crypto_engine->CreateSession(); SessionId sid = crypto_engine->OpenSession();
*session = (OEMCrypto_SESSION)sid; *session = (OEMCrypto_SESSION)sid;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_OpenSession(): SID=%08x]", sid);
}
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
extern "C" OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session) { extern "C" OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI(
"-- OEMCryptoResult OEMCrypto_CloseSession"
"(OEMCrypto_SESSION session)\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_CloseSession: OEMCrypto not initialized."); LOGE("OEMCrypto_CloseSession: OEMCrypto not initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
} }
if (!crypto_engine->DestroySession((SessionId)session)) { if (!crypto_engine->DestroySession((SessionId)session)) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_CloseSession(SID=%08X): failed]", session);
}
return OEMCrypto_ERROR_CLOSE_SESSION_FAILED; return OEMCrypto_ERROR_CLOSE_SESSION_FAILED;
} else { } else {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_CloseSession(SID=%08X): success]", session);
}
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
} }
@@ -150,15 +117,6 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
OEMCrypto_SESSION session, const uint8_t* mac_key_context, OEMCrypto_SESSION session, const uint8_t* mac_key_context,
uint32_t mac_key_context_length, const uint8_t* enc_key_context, uint32_t mac_key_context_length, const uint8_t* enc_key_context,
uint32_t enc_key_context_length) { 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) { if (!crypto_engine) {
LOGE("OEMCrypto_GenerateDerivedKeys: OEMCrypto not initialized."); LOGE("OEMCrypto_GenerateDerivedKeys: OEMCrypto not initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -187,16 +145,6 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
enc_ctx_str)) { enc_ctx_str)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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; return OEMCrypto_SUCCESS;
} }
@@ -209,11 +157,6 @@ static uint64_t TimeStamp(void) {
extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session, extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
uint32_t* nonce) { uint32_t* nonce) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI(
"-- OEMCryptoResult OEMCrypto_GenerateNonce"
"(OEMCrypto_SESSION session,\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_GenerateNonce: OEMCrypto not initialized."); LOGE("OEMCrypto_GenerateNonce: OEMCrypto not initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -252,21 +195,12 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
} }
session_ctx->AddNonce(nonce_value); session_ctx->AddNonce(nonce_value);
*nonce = nonce_value; *nonce = nonce_value;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("nonce = %08x\n", nonce_value);
}
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
extern "C" OEMCryptoResult OEMCrypto_GenerateSignature( extern "C" OEMCryptoResult OEMCrypto_GenerateSignature(
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
uint8_t* signature, size_t* signature_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) { if (!crypto_engine) {
LOGE("OEMCrypto_GenerateSignature: OEMCrypto Not Initialized."); LOGE("OEMCrypto_GenerateSignature: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -291,11 +225,6 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateSignature(
if (session_ctx->GenerateSignature(message, message_length, signature, if (session_ctx->GenerateSignature(message, message_length, signature,
signature_length)) { signature_length)) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("signature", signature, *signature_length);
}
}
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -319,49 +248,20 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
LOGE("OEMCrypto_LoadKeys: OEMCrypto Not Initialized."); LOGE("OEMCrypto_LoadKeys: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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()) { if (!crypto_engine->ValidRootOfTrust()) {
LOGE("[OEMCrypto_LoadKeys(): ERROR_KEYBOX_INVALID]"); LOGE("[OEMCrypto_LoadKeys(): ERROR_KEYBOX_INVALID]");
return OEMCrypto_ERROR_KEYBOX_INVALID; return OEMCrypto_ERROR_KEYBOX_INVALID;
} }
SessionContext* session_ctx = crypto_engine->FindSession(session); SessionContext* session_ctx = crypto_engine->FindSession(session);
if (!session_ctx || !session_ctx->isValid()) { if (!session_ctx || !session_ctx->isValid()) {
LOGE("[OEMCrypto_LoadKeys(): ERROR_INVALID_SESSION]"); LOGE("[OEMCrypto_LoadKeys(): ERROR_INVALID_SESSION]");
return OEMCrypto_ERROR_INVALID_SESSION; return OEMCrypto_ERROR_INVALID_SESSION;
} }
if (message == NULL || message_length == 0 || signature == NULL || if (message == NULL || message_length == 0 || signature == NULL ||
signature_length == 0 || key_array == NULL || num_keys == 0) { signature_length == 0 || key_array == NULL || num_keys == 0) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT; return OEMCrypto_ERROR_INVALID_CONTEXT;
} }
// Later on, we use pst_length to verify the the pst is valid. This makes // 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. // sure that we aren't given a null string but told it has postiive length.
if (pst == NULL && pst_length > 0) { 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, OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
const uint8_t* signature, size_t signature_length, size_t num_keys, const uint8_t* signature, size_t signature_length, size_t num_keys,
const OEMCrypto_KeyRefreshObject* key_array) { const OEMCrypto_KeyRefreshObject* key_array) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_RefreshKeys(num_keys=%zu)\n", num_keys);
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_RefreshKeys: OEMCrypto Not Initialized."); LOGE("OEMCrypto_RefreshKeys: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -524,10 +421,6 @@ extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
extern "C" OEMCryptoResult OEMCrypto_QueryKeyControl( extern "C" OEMCryptoResult OEMCrypto_QueryKeyControl(
OEMCrypto_SESSION session, const uint8_t* key_id, size_t key_id_length, OEMCrypto_SESSION session, const uint8_t* key_id, size_t key_id_length,
uint8_t* key_control_block, size_t* key_control_block_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) { if (!crypto_engine) {
LOGE("OEMCrypto_QueryKeyControl: OEMCrypto Not Initialized."); LOGE("OEMCrypto_QueryKeyControl: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -563,10 +456,6 @@ extern "C" OEMCryptoResult OEMCrypto_QueryKeyControl(
extern "C" OEMCryptoResult OEMCrypto_SelectKey( extern "C" OEMCryptoResult OEMCrypto_SelectKey(
const OEMCrypto_SESSION session, const uint8_t* key_id, const OEMCrypto_SESSION session, const uint8_t* key_id,
size_t key_id_length, OEMCryptoCipherMode cipher_mode) { 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 #ifndef NDEBUG
if (!crypto_engine->ValidRootOfTrust()) { if (!crypto_engine->ValidRootOfTrust()) {
LOGE("[OEMCrypto_SelectKey(): ERROR_KEYBOX_INVALID]"); 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, bool is_encrypted, const uint8_t* iv, size_t block_offset,
OEMCrypto_DestBufferDesc* out_buffer, OEMCrypto_DestBufferDesc* out_buffer,
const OEMCrypto_CENCEncryptPatternDesc* pattern, uint8_t subsample_flags) { const OEMCrypto_CENCEncryptPatternDesc* pattern, uint8_t subsample_flags) {
if (LogCategoryEnabled(kLoggingTraceDecryptCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_DecryptCENC(%d)", session);
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_DecryptCENC: OEMCrypto Not Initialized."); LOGE("OEMCrypto_DecryptCENC: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -638,9 +524,6 @@ extern "C" OEMCryptoResult OEMCrypto_DecryptCENC(
extern "C" OEMCryptoResult OEMCrypto_CopyBuffer( extern "C" OEMCryptoResult OEMCrypto_CopyBuffer(
const uint8_t* data_addr, size_t data_length, const uint8_t* data_addr, size_t data_length,
OEMCrypto_DestBufferDesc* out_buffer, uint8_t subsample_flags) { OEMCrypto_DestBufferDesc* out_buffer, uint8_t subsample_flags) {
if (LogCategoryEnabled(kLoggingTraceDecryptCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CopyBuffer(..)\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_CopyBuffer: OEMCrypto Not Initialized."); LOGE("OEMCrypto_CopyBuffer: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -660,20 +543,15 @@ extern "C" OEMCryptoResult OEMCrypto_CopyBuffer(
crypto_engine->SetDestination(out_buffer, data_length, subsample_flags); crypto_engine->SetDestination(out_buffer, data_length, subsample_flags);
if (status != OEMCrypto_SUCCESS) return status; if (status != OEMCrypto_SUCCESS) return status;
if (crypto_engine->destination() != NULL) { 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); return crypto_engine->PushDestination(out_buffer, subsample_flags);
} }
extern "C" OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox, extern "C" OEMCryptoResult OEMCrypto_WrapKeyboxOrOEMCert(
size_t keyBoxLength, const uint8_t* keybox, size_t keyBoxLength, uint8_t* wrappedKeybox,
uint8_t* wrappedKeybox, size_t* wrappedKeyBoxLength, const uint8_t* transportKey,
size_t* wrappedKeyBoxLength, size_t transportKeyLength) {
const uint8_t* transportKey,
size_t transportKeyLength) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox,\n");
}
if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) {
return OEMCrypto_ERROR_NOT_IMPLEMENTED; return OEMCrypto_ERROR_NOT_IMPLEMENTED;
} }
@@ -687,13 +565,10 @@ extern "C" OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox,
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
extern "C" OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox, extern "C" OEMCryptoResult OEMCrypto_InstallKeyboxOrOEMCert(
size_t keyBoxLength) { const uint8_t* keybox, size_t keyBoxLength) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t *keybox,\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_InstallKeybox: OEMCrypto Not Initialized."); LOGE("OEMCrypto_InstallKeyboxOrOEMCert: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
} }
if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { 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, extern "C" OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer,
size_t length) { size_t length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadTestKeybox()\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_LoadTestKeybox: OEMCrypto Not Initialized."); LOGE("OEMCrypto_LoadTestKeybox: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -721,34 +593,39 @@ extern "C" OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer,
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
extern "C" OEMCryptoResult OEMCrypto_IsKeyboxValid(void) { extern "C" OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_IsKeyboxValid(void) {\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_IsKeyboxValid: OEMCrypto Not Initialized."); LOGE("OEMCrypto_IsKeyboxOrOEMCertValid: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
} }
if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { switch (crypto_engine->config_provisioning_method()) {
return OEMCrypto_ERROR_NOT_IMPLEMENTED; case OEMCrypto_DrmCertificate:
}
switch (crypto_engine->ValidateKeybox()) {
case NO_ERROR:
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
case BAD_CRC: case OEMCrypto_Keybox:
return OEMCrypto_ERROR_BAD_CRC; switch (crypto_engine->ValidateKeybox()) {
case BAD_MAGIC: case NO_ERROR:
return OEMCrypto_ERROR_BAD_MAGIC; 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: default:
case OTHER_ERROR: LOGE("Invalid provisioning method: %d.",
crypto_engine->config_provisioning_method());
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
} }
} }
extern "C" OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod() { extern "C" OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod()");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_GetProvisioningMethod: OEMCrypto Not Initialized."); LOGE("OEMCrypto_GetProvisioningMethod: OEMCrypto Not Initialized.");
return OEMCrypto_ProvisioningError; return OEMCrypto_ProvisioningError;
@@ -759,10 +636,6 @@ extern "C" OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod() {
extern "C" OEMCryptoResult OEMCrypto_GetOEMPublicCertificate( extern "C" OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(
OEMCrypto_SESSION session, uint8_t* public_cert, OEMCrypto_SESSION session, uint8_t* public_cert,
size_t* public_cert_length) { size_t* public_cert_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(%d) {\n",
session);
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_GetOEMPublicCertificate: OEMCrypto Not Initialized."); LOGE("OEMCrypto_GetOEMPublicCertificate: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -783,9 +656,6 @@ extern "C" OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(
extern "C" OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, extern "C" OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
size_t* idLength) { size_t* idLength) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_GetDeviceID: OEMCrypto Not Initialized."); LOGE("OEMCrypto_GetDeviceID: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -810,17 +680,11 @@ extern "C" OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
memset(deviceID, 0, *idLength); memset(deviceID, 0, *idLength);
memcpy(deviceID, &dev_id_string[0], dev_id_len); memcpy(deviceID, &dev_id_string[0], dev_id_len);
*idLength = dev_id_len; *idLength = dev_id_len;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_GetDeviceId(): success]");
}
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
extern "C" OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData, extern "C" OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
size_t* keyDataLength) { size_t* keyDataLength) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_GetKeyData: OEMCrypto Not Initialized."); LOGE("OEMCrypto_GetKeyData: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -845,17 +709,11 @@ extern "C" OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
memset(keyData, 0, *keyDataLength); memset(keyData, 0, *keyDataLength);
memcpy(keyData, crypto_engine->DeviceRootToken(), length); memcpy(keyData, crypto_engine->DeviceRootToken(), length);
*keyDataLength = length; *keyDataLength = length;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_GetKeyData(): success]");
}
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
extern "C" OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, extern "C" OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
size_t dataLength) { size_t dataLength) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetRandom");
}
if (!randomData) { if (!randomData) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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, const uint8_t* enc_rsa_key_iv, uint8_t* wrapped_rsa_key,
size_t* wrapped_rsa_key_length) { size_t* wrapped_rsa_key_length) {
uint32_t nonce = unaligned_dereference_uint32(unaligned_nonce); uint32_t nonce = unaligned_dereference_uint32(unaligned_nonce);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls | kLoggingTraceNonce)) { if (unaligned_nonce == NULL) {
LOGI("-- OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(%d)\n", session); return OEMCrypto_ERROR_INVALID_CONTEXT;
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 (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_RewrapDeviceRSAKey30: OEMCrypto Not Initialized."); 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); size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey);
if (wrapped_rsa_key == NULL || *wrapped_rsa_key_length < buffer_size) { 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; *wrapped_rsa_key_length = buffer_size;
return OEMCrypto_ERROR_SHORT_BUFFER; 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 // 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. // pick the server key, so I don't have to modify LoadRSAKey.
unsigned int sig_length = sizeof(wrapped->signature); 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], if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0],
session_ctx->mac_key_server().size(), wrapped->context, session_ctx->mac_key_server().size(), wrapped->context,
buffer_size - sizeof(wrapped->signature), wrapped->signature, buffer_size - sizeof(wrapped->signature), wrapped->signature,
&sig_length)) { &sig_length)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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; 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, size_t enc_rsa_key_length, const uint8_t* enc_rsa_key_iv,
uint8_t* wrapped_rsa_key, size_t* wrapped_rsa_key_length) { uint8_t* wrapped_rsa_key, size_t* wrapped_rsa_key_length) {
uint32_t nonce = unaligned_dereference_uint32(unaligned_nonce); uint32_t nonce = unaligned_dereference_uint32(unaligned_nonce);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls | kLoggingTraceNonce)) { if (unaligned_nonce == NULL) {
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");
return OEMCrypto_ERROR_INVALID_CONTEXT; 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) { if (!crypto_engine) {
LOGE("OEMCrypto_RewrapDeviceRSAKey: OEMCrypto Not Initialized."); LOGE("OEMCrypto_RewrapDeviceRSAKey: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1051,9 +868,6 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey); size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey);
if (wrapped_rsa_key == NULL || *wrapped_rsa_key_length < buffer_size) { 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; *wrapped_rsa_key_length = buffer_size;
return OEMCrypto_ERROR_SHORT_BUFFER; 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 // 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. // pick the server key, so I don't have to modify LoadRSAKey.
unsigned int sig_length = sizeof(wrapped->signature); 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], if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0],
session_ctx->mac_key_server().size(), wrapped->context, session_ctx->mac_key_server().size(), wrapped->context,
buffer_size - sizeof(wrapped->signature), wrapped->signature, buffer_size - sizeof(wrapped->signature), wrapped->signature,
&sig_length)) { &sig_length)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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; return OEMCrypto_SUCCESS;
} }
@@ -1184,15 +985,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(
} }
const WrappedRSAKey* wrapped = const WrappedRSAKey* wrapped =
reinterpret_cast<const WrappedRSAKey*>(wrapped_rsa_key); 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()) { if (!crypto_engine->ValidRootOfTrust()) {
LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]");
return OEMCrypto_ERROR_KEYBOX_INVALID; return OEMCrypto_ERROR_KEYBOX_INVALID;
@@ -1238,9 +1030,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(
} }
extern "C" OEMCryptoResult OEMCrypto_LoadTestRSAKey() { extern "C" OEMCryptoResult OEMCrypto_LoadTestRSAKey() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadTestRSAKey()\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_LoadTestRSAKey: OEMCrypto Not Initialized."); LOGE("OEMCrypto_LoadTestRSAKey: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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, OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
uint8_t* signature, size_t* signature_length, uint8_t* signature, size_t* signature_length,
RSA_Padding_Scheme padding_scheme) { 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) { if (!crypto_engine) {
LOGE("OEMCrypto_GenerateRSASignature: OEMCrypto Not Initialized."); LOGE("OEMCrypto_GenerateRSASignature: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1290,13 +1072,6 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
OEMCryptoResult sts = session_ctx->GenerateRSASignature( OEMCryptoResult sts = session_ctx->GenerateRSASignature(
message, message_length, signature, signature_length, padding_scheme); 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; 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 enc_session_key_length, const uint8_t* mac_key_context,
size_t mac_key_context_length, const uint8_t* enc_key_context, size_t mac_key_context_length, const uint8_t* enc_key_context,
size_t enc_key_context_length) { 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) { if (!crypto_engine) {
LOGE("OEMCrypto_DeriveKeysFromSessionKey: OEMCrypto Not Initialized."); LOGE("OEMCrypto_DeriveKeysFromSessionKey: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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)) { if (!session_ctx->RSADeriveKeys(ssn_key_str, mac_ctx_str, enc_ctx_str)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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; return OEMCrypto_SUCCESS;
} }
@@ -1363,28 +1118,16 @@ extern "C" uint32_t OEMCrypto_APIVersion() { return 14; }
extern "C" uint8_t OEMCrypto_Security_Patch_Level() { extern "C" uint8_t OEMCrypto_Security_Patch_Level() {
uint8_t security_patch_level = crypto_engine->config_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; return security_patch_level;
} }
extern "C" const char* OEMCrypto_SecurityLevel() { extern "C" const char* OEMCrypto_SecurityLevel() {
const char* security_level = crypto_engine->config_security_level(); 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; return security_level;
} }
extern "C" OEMCryptoResult OEMCrypto_GetHDCPCapability( extern "C" OEMCryptoResult OEMCrypto_GetHDCPCapability(
OEMCrypto_HDCP_Capability* current, OEMCrypto_HDCP_Capability* maximum) { OEMCrypto_HDCP_Capability* current, OEMCrypto_HDCP_Capability* maximum) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetHDCPCapability(%p, %p)\n", current,
maximum);
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_GetHDCPCapability: OEMCrypto Not Initialized."); LOGE("OEMCrypto_GetHDCPCapability: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1393,30 +1136,27 @@ extern "C" OEMCryptoResult OEMCrypto_GetHDCPCapability(
if (maximum == NULL) return OEMCrypto_ERROR_UNKNOWN_FAILURE; if (maximum == NULL) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
*current = crypto_engine->config_current_hdcp_capability(); *current = crypto_engine->config_current_hdcp_capability();
*maximum = crypto_engine->config_maximum_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; return OEMCrypto_SUCCESS;
} }
extern "C" uint32_t OEMCrypto_GetAnalogOutputFlags() { extern "C" uint32_t OEMCrypto_GetAnalogOutputFlags() {
// TODO(b/69867568, fredgc): parameterize this. if (!crypto_engine) {
return 0; LOGE("OEMCrypto_GetAnalogOutputFlags: OEMCrypto Not Initialized.");
return 0;
}
return crypto_engine->analog_output_flags();
} }
extern "C" bool OEMCrypto_SupportsUsageTable() { extern "C" bool OEMCrypto_SupportsUsageTable() {
bool supports_usage = crypto_engine->config_supports_usage_table(); if (!crypto_engine) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) { LOGE("OEMCrypto_SupportsUsageTable: OEMCrypto Not Initialized.");
LOGI("-- bool OEMCrypto_SupportsUsageTable(); // returns %s.\n", return 0;
(supports_usage ? "true" : "false"));
} }
bool supports_usage = crypto_engine->config_supports_usage_table();
return supports_usage; return supports_usage;
} }
extern "C" OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* count) { extern "C" OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* count) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(%p)\n", count);
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_GetNumberOfOpenSessions: OEMCrypto Not Initialized."); LOGE("OEMCrypto_GetNumberOfOpenSessions: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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) { extern "C" OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(size_t* maximum) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(%p)\n", maximum);
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_GetMaxNumberOfSessions: OEMCrypto Not Initialized."); LOGE("OEMCrypto_GetMaxNumberOfSessions: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1443,10 +1180,6 @@ extern "C" bool OEMCrypto_IsAntiRollbackHwPresent() {
bool anti_rollback_hw_present = bool anti_rollback_hw_present =
crypto_engine->config_is_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; return anti_rollback_hw_present;
} }
@@ -1465,14 +1198,6 @@ extern "C" uint32_t OEMCrypto_SupportedCertificates() {
extern "C" OEMCryptoResult OEMCrypto_Generic_Encrypt( extern "C" OEMCryptoResult OEMCrypto_Generic_Encrypt(
OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length, OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer) { 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) { if (!crypto_engine) {
LOGE("OEMCrypto_Generic_Encrypt: OEMCrypto Not Initialized."); LOGE("OEMCrypto_Generic_Encrypt: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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, OEMCryptoResult sts = session_ctx->Generic_Encrypt(in_buffer, buffer_length,
iv, algorithm, out_buffer); iv, algorithm, out_buffer);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("out_buffer", out_buffer, buffer_length);
}
}
return sts; return sts;
} }
extern "C" OEMCryptoResult OEMCrypto_Generic_Decrypt( extern "C" OEMCryptoResult OEMCrypto_Generic_Decrypt(
OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length, OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer) { 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) { if (!crypto_engine) {
LOGE("OEMCrypto_Generic_Decrypt: OEMCrypto Not Initialized."); LOGE("OEMCrypto_Generic_Decrypt: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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, OEMCryptoResult sts = session_ctx->Generic_Decrypt(in_buffer, buffer_length,
iv, algorithm, out_buffer); iv, algorithm, out_buffer);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("out_buffer", out_buffer, buffer_length);
}
}
return sts; return sts;
} }
@@ -1546,13 +1253,6 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session,
OEMCrypto_Algorithm algorithm, OEMCrypto_Algorithm algorithm,
uint8_t* signature, uint8_t* signature,
size_t* signature_length) { 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) { if (!crypto_engine) {
LOGE("OEMCrypto_Generic_Sign: OEMCrypto Not Initialized."); LOGE("OEMCrypto_Generic_Sign: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1576,11 +1276,6 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session,
} }
OEMCryptoResult sts = session_ctx->Generic_Sign( OEMCryptoResult sts = session_ctx->Generic_Sign(
in_buffer, buffer_length, algorithm, signature, signature_length); 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; 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_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
OEMCrypto_Algorithm algorithm, const uint8_t* signature, OEMCrypto_Algorithm algorithm, const uint8_t* signature,
size_t signature_length) { 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) { if (!crypto_engine) {
LOGE("OEMCrypto_Generic_Verify: OEMCrypto Not Initialized."); LOGE("OEMCrypto_Generic_Verify: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1622,20 +1309,11 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Verify(
// TODO(fredgc): remove this. // TODO(fredgc): remove this.
extern "C" OEMCryptoResult OEMCrypto_UpdateUsageTable() { extern "C" OEMCryptoResult OEMCrypto_UpdateUsageTable() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_UpdateUsageTable();\n");
}
return OEMCrypto_ERROR_NOT_IMPLEMENTED; return OEMCrypto_ERROR_NOT_IMPLEMENTED;
} }
extern "C" OEMCryptoResult OEMCrypto_DeactivateUsageEntry( extern "C" OEMCryptoResult OEMCrypto_DeactivateUsageEntry(
OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length) { 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) { if (!crypto_engine) {
LOGE("OEMCrypto_DeactivateUsageEntry: OEMCrypto Not Initialized."); LOGE("OEMCrypto_DeactivateUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1657,12 +1335,6 @@ extern "C" OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
size_t pst_length, size_t pst_length,
uint8_t* buffer, uint8_t* buffer,
size_t* buffer_length) { 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) { if (!crypto_engine) {
LOGE("OEMCrypto_ReportUsage: OEMCrypto Not Initialized."); LOGE("OEMCrypto_ReportUsage: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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); std::vector<uint8_t> pstv(pst, pst + pst_length);
OEMCryptoResult sts = session_ctx->ReportUsage(pstv, buffer, buffer_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; return sts;
} }
@@ -1703,9 +1370,6 @@ extern "C" OEMCryptoResult OEMCrypto_ForceDeleteUsageEntry(const uint8_t*,
} }
extern "C" OEMCryptoResult OEMCrypto_DeleteOldUsageTable() { extern "C" OEMCryptoResult OEMCrypto_DeleteOldUsageTable() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_DeleteOldUsageTable()\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_DeleteOldUsageTable: OEMCrypto Not Initialized."); LOGE("OEMCrypto_DeleteOldUsageTable: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1717,25 +1381,15 @@ extern "C" OEMCryptoResult OEMCrypto_DeleteOldUsageTable() {
} }
extern "C" bool OEMCrypto_IsSRMUpdateSupported() { extern "C" bool OEMCrypto_IsSRMUpdateSupported() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_IsSRMUpdateSupported()\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_IsSRMUpdateSupported: OEMCrypto Not Initialized."); LOGE("OEMCrypto_IsSRMUpdateSupported: OEMCrypto Not Initialized.");
return false; return false;
} }
bool result = crypto_engine->srm_update_supported(); bool result = crypto_engine->srm_update_supported();
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_IsSRMUpdateSupported returning %s\n",
result ? "TRUE" : "FALSE");
}
return result; return result;
} }
extern "C" OEMCryptoResult OEMCrypto_GetCurrentSRMVersion(uint16_t* version) { extern "C" OEMCryptoResult OEMCrypto_GetCurrentSRMVersion(uint16_t* version) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetCurrentSRMVersion()\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_GetCurrentSRMVersion: OEMCrypto Not Initialized."); LOGE("OEMCrypto_GetCurrentSRMVersion: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1744,19 +1398,11 @@ extern "C" OEMCryptoResult OEMCrypto_GetCurrentSRMVersion(uint16_t* version) {
return OEMCrypto_LOCAL_DISPLAY_ONLY; return OEMCrypto_LOCAL_DISPLAY_ONLY;
} }
OEMCryptoResult result = crypto_engine->current_srm_version(version); OEMCryptoResult result = crypto_engine->current_srm_version(version);
if (result == OEMCrypto_SUCCESS &&
LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GetCurrentSRMVersion returning %d\n",
*version);
}
return result; return result;
} }
extern "C" OEMCryptoResult OEMCrypto_LoadSRM(const uint8_t* buffer, extern "C" OEMCryptoResult OEMCrypto_LoadSRM(const uint8_t* buffer,
size_t buffer_length) { size_t buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadSRM(length=%d)\n", buffer_length);
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_LoadSRM: OEMCrypto Not Initialized."); LOGE("OEMCrypto_LoadSRM: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1765,9 +1411,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadSRM(const uint8_t* buffer,
} }
extern "C" OEMCryptoResult OEMCrypto_RemoveSRM() { extern "C" OEMCryptoResult OEMCrypto_RemoveSRM() {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_RemoveSRM()\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_RemoveSRM: OEMCrypto Not Initialized."); LOGE("OEMCrypto_RemoveSRM: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1777,9 +1420,6 @@ extern "C" OEMCryptoResult OEMCrypto_RemoveSRM() {
extern "C" OEMCryptoResult OEMCrypto_CreateUsageTableHeader( extern "C" OEMCryptoResult OEMCrypto_CreateUsageTableHeader(
uint8_t* header_buffer, size_t* header_buffer_length) { uint8_t* header_buffer, size_t* header_buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CreateUsageTableHeader()\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_CreateUsageTableHeader: OEMCrypto Not Initialized."); LOGE("OEMCrypto_CreateUsageTableHeader: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1794,9 +1434,6 @@ extern "C" OEMCryptoResult OEMCrypto_CreateUsageTableHeader(
extern "C" OEMCryptoResult OEMCrypto_LoadUsageTableHeader( extern "C" OEMCryptoResult OEMCrypto_LoadUsageTableHeader(
const uint8_t* buffer, size_t buffer_length) { const uint8_t* buffer, size_t buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadUsageTableHeader()\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_LoadUsageTableHeader: OEMCrypto Not Initialized."); LOGE("OEMCrypto_LoadUsageTableHeader: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1814,9 +1451,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadUsageTableHeader(
extern "C" OEMCryptoResult OEMCrypto_CreateNewUsageEntry( extern "C" OEMCryptoResult OEMCrypto_CreateNewUsageEntry(
OEMCrypto_SESSION session, uint32_t* usage_entry_number) { OEMCrypto_SESSION session, uint32_t* usage_entry_number) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CreateNewUsageEntry(\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_CreateNewUsageEntry: OEMCrypto Not Initialized."); LOGE("OEMCrypto_CreateNewUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1833,9 +1467,6 @@ extern "C" OEMCryptoResult OEMCrypto_CreateNewUsageEntry(
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
} }
OEMCryptoResult sts = session_ctx->CreateNewUsageEntry(usage_entry_number); OEMCryptoResult sts = session_ctx->CreateNewUsageEntry(usage_entry_number);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- usage_entry_number = %d", *usage_entry_number);
}
return sts; return sts;
} }
@@ -1843,9 +1474,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadUsageEntry(OEMCrypto_SESSION session,
uint32_t index, uint32_t index,
const uint8_t* buffer, const uint8_t* buffer,
size_t buffer_size) { size_t buffer_size) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadUsageEntry(\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_LoadUsageEntry: OEMCrypto Not Initialized."); LOGE("OEMCrypto_LoadUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1870,9 +1498,6 @@ extern "C" OEMCryptoResult OEMCrypto_UpdateUsageEntry(
OEMCrypto_SESSION session, uint8_t* header_buffer, OEMCrypto_SESSION session, uint8_t* header_buffer,
size_t* header_buffer_length, uint8_t* entry_buffer, size_t* header_buffer_length, uint8_t* entry_buffer,
size_t* entry_buffer_length) { size_t* entry_buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_UpdateUsageEntry(\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_UpdateUsageEntry: OEMCrypto Not Initialized."); LOGE("OEMCrypto_UpdateUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1895,9 +1520,6 @@ extern "C" OEMCryptoResult OEMCrypto_UpdateUsageEntry(
extern "C" OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader( extern "C" OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader(
uint32_t new_table_size, uint8_t* header_buffer, uint32_t new_table_size, uint8_t* header_buffer,
size_t* header_buffer_length) { size_t* header_buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader()\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_ShrinkUsageTableHeader: OEMCrypto Not Initialized."); LOGE("OEMCrypto_ShrinkUsageTableHeader: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1911,9 +1533,6 @@ extern "C" OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader(
extern "C" OEMCryptoResult OEMCrypto_MoveEntry(OEMCrypto_SESSION session, extern "C" OEMCryptoResult OEMCrypto_MoveEntry(OEMCrypto_SESSION session,
uint32_t new_index) { uint32_t new_index) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_MoveEntry(\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_MoveEntry: OEMCrypto Not Initialized."); LOGE("OEMCrypto_MoveEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1931,9 +1550,6 @@ extern "C" OEMCryptoResult OEMCrypto_MoveEntry(OEMCrypto_SESSION session,
extern "C" OEMCryptoResult OEMCrypto_CopyOldUsageEntry( extern "C" OEMCryptoResult OEMCrypto_CopyOldUsageEntry(
OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length) { OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CopyOldUsageEntry(\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_CopyOldUsageEntry: OEMCrypto Not Initialized."); LOGE("OEMCrypto_CopyOldUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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, 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, uint8_t* server_mac_key, uint8_t* client_mac_key, const uint8_t* pst,
size_t pst_length) { size_t pst_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CreateOldUsageEntry()\n");
}
if (!crypto_engine) { if (!crypto_engine) {
LOGE("OEMCrypto_CreateOldUsageEntry: OEMCrypto Not Initialized."); LOGE("OEMCrypto_CreateOldUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;

View File

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

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#ifndef OEMCRYPTO_RSA_KEY_SHARED_H_ #ifndef OEMCRYPTO_RSA_KEY_SHARED_H_
#define 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_ #ifndef OEMCRYPTO_SCOPED_PTR_H_
#define OEMCRYPTO_SCOPED_PTR_H_ #define OEMCRYPTO_SCOPED_PTR_H_
@@ -17,6 +20,7 @@ class scoped_ptr {
public: public:
explicit scoped_ptr(T* p = NULL) : ptr_(p) {} explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
T* get() const { return ptr_.get(); } T* get() const { return ptr_.get(); }
void reset(T* p = NULL) { ptr_.reset(p); }
private: private:
std::auto_ptr<T> ptr_; std::auto_ptr<T> ptr_;
@@ -32,7 +36,7 @@ class scoped_ptr {
T& operator*() const { return *ptr_; } T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_.get(); } T* operator->() const { return ptr_.get(); }
T* get() 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: private:
std::unique_ptr<T> ptr_; std::unique_ptr<T> ptr_;

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#include "oemcrypto_session.h" #include "oemcrypto_session.h"
@@ -28,7 +28,6 @@
#include "log.h" #include "log.h"
#include "oemcrypto_engine_ref.h" #include "oemcrypto_engine_ref.h"
#include "oemcrypto_key_ref.h" #include "oemcrypto_key_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_rsa_key_shared.h" #include "oemcrypto_rsa_key_shared.h"
#include "oemcrypto_types.h" #include "oemcrypto_types.h"
#include "disallow_copy_and_assign.h" #include "disallow_copy_and_assign.h"
@@ -248,14 +247,6 @@ bool SessionContext::DeriveKeys(const std::vector<uint8_t>& master_key,
return false; 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_server(mac_key_server);
set_mac_key_client(mac_key_client); set_mac_key_client(mac_key_client);
set_encryption_key(enc_key); set_encryption_key(enc_key);
@@ -316,25 +307,6 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
return false; 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; unsigned int md_len = *signature_length;
if (HMAC(EVP_sha256(), &mac_key_client_[0], wvoec::MAC_KEY_SIZE, message, if (HMAC(EVP_sha256(), &mac_key_client_[0], wvoec::MAC_KEY_SIZE, message,
message_length, signature, &md_len)) { message_length, signature, &md_len)) {
@@ -432,10 +404,6 @@ bool SessionContext::ValidateMessage(const uint8_t* given_message,
uint8_t computed_signature[SHA256_DIGEST_LENGTH]; uint8_t computed_signature[SHA256_DIGEST_LENGTH];
memset(computed_signature, 0, SHA256_DIGEST_LENGTH); memset(computed_signature, 0, SHA256_DIGEST_LENGTH);
unsigned int md_len = 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(), if (!HMAC(EVP_sha256(), &mac_key_server_[0], mac_key_server_.size(),
given_message, message_length, computed_signature, &md_len)) { given_message, message_length, computed_signature, &md_len)) {
LOGE("ValidateMessage: Could not compute signature."); LOGE("ValidateMessage: Could not compute signature.");
@@ -652,10 +620,6 @@ OEMCryptoResult SessionContext::LoadKeys(
LOGE("LoadKeys: Usage table can't set keys.\n"); LOGE("LoadKeys: Usage table can't set keys.\n");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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; break;
case kUsageEntryLoaded: case kUsageEntryLoaded:
if (!usage_entry_->VerifyPST(pst, pst_length)) { if (!usage_entry_->VerifyPST(pst, pst_length)) {
@@ -732,14 +696,6 @@ OEMCryptoResult SessionContext::InstallKey(
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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 // Key control must be supplied by license server
if (key_control.empty()) { if (key_control.empty()) {
LOGE("[Installkey(): WARNING: No Key Control]"); LOGE("[Installkey(): WARNING: No Key Control]");
@@ -755,9 +711,6 @@ OEMCryptoResult SessionContext::InstallKey(
return OEMCrypto_ERROR_UNKNOWN_FAILURE; 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); KeyControlBlock key_control_block(key_control_str);
if (!key_control_block.valid()) { if (!key_control_block.valid()) {
LOGE("Error parsing key control."); LOGE("Error parsing key control.");
@@ -855,16 +808,11 @@ OEMCryptoResult SessionContext::RefreshKey(
Key* content_key = session_keys_->Find(key_id); Key* content_key = session_keys_->Find(key_id);
if (NULL == content_key) { if (NULL == content_key) {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) { LOGE("Key ID not found.");
LOGD("Error: no matching content key.");
}
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
} }
if (key_control.empty()) { if (key_control.empty()) {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Error: no key_control.");
}
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
} }
@@ -873,33 +821,21 @@ OEMCryptoResult SessionContext::RefreshKey(
// Decrypt encrypted key control block // Decrypt encrypted key control block
std::vector<uint8_t> control; std::vector<uint8_t> control;
if (key_control_iv.empty()) { if (key_control_iv.empty()) {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Key control block is NOT encrypted.");
}
control = key_control; control = key_control;
} else { } else {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Key control block is encrypted.");
}
if (!DecryptMessage(content_key_value, key_control_iv, key_control, if (!DecryptMessage(content_key_value, key_control_iv, key_control,
&control, 128 /* key size */)) { &control, 128 /* key size */)) {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("Error decrypting key control block.");
}
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
} }
} }
KeyControlBlock key_control_block(control); KeyControlBlock key_control_block(control);
if (!key_control_block.valid()) { if (!key_control_block.valid()) {
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) { LOGE("Error parsing key control.");
LOGD("Parse key control error.");
}
return OEMCrypto_ERROR_INVALID_CONTEXT; return OEMCrypto_ERROR_INVALID_CONTEXT;
} }
if ((key_control_block.control_bits() & wvoec::kControlNonceEnabled) && if ((key_control_block.control_bits() & wvoec::kControlNonceEnabled) &&
(!CheckNonce(key_control_block.nonce()))) { (!CheckNonce(key_control_block.nonce()))) {
LOGE("KCB: BAD Nonce");
return OEMCrypto_ERROR_INVALID_NONCE; return OEMCrypto_ERROR_INVALID_NONCE;
} }
content_key->UpdateDuration(key_control_block); content_key->UpdateDuration(key_control_block);
@@ -981,8 +917,7 @@ OEMCryptoResult SessionContext::CheckKeyUse(const std::string& log_string,
} }
} }
if (!ce_->config_local_display_only()) { if (!ce_->config_local_display_only()) {
// Only look at HDCP and Analog restrictions if the display can be // Only look at HDCP restrictions if the display can be non-local.
// non-local.
if (control.control_bits() & wvoec::kControlHDCPRequired) { if (control.control_bits() & wvoec::kControlHDCPRequired) {
uint8_t required_hdcp = uint8_t required_hdcp =
(control.control_bits() & wvoec::kControlHDCPVersionMask) >> (control.control_bits() & wvoec::kControlHDCPVersionMask) >>
@@ -998,10 +933,24 @@ OEMCryptoResult SessionContext::CheckKeyUse(const std::string& log_string,
} }
} }
} }
if (!ce_->config_local_display_only() || // If the output buffer is clear, then we cannot control whether the output is
buffer_type == OEMCrypto_BufferType_Clear) { // an active analog display. In that case, return an error if analog displays
if (control.control_bits() & wvoec::kControlDisableAnalogOutput) { // should be disabled.
LOGE("[%s(): control bit says disable analog.", log_string.c_str()); 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; 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_keys.begin(), mac_keys.begin() + wvoec::MAC_KEY_SIZE);
mac_key_client_ = std::vector<uint8_t>(mac_keys.begin() + wvoec::MAC_KEY_SIZE, mac_key_client_ = std::vector<uint8_t>(mac_keys.begin() + wvoec::MAC_KEY_SIZE,
mac_keys.end()); mac_keys.end());
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("mac_key_client_ has been updated to = " +
wvcdm::b2a_hex(mac_key_client_)).c_str());
}
return true; return true;
} }
@@ -1191,15 +1136,6 @@ bool SessionContext::QueryKeyControlBlock(const KeyId& key_id, uint32_t* data) {
return false; return false;
} }
const Key* content_key = session_keys_->Find(key_id); 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) { if (NULL == content_key) {
LOGE("[QueryKeyControlBlock(): No key matches key id]"); LOGE("[QueryKeyControlBlock(): No key matches key id]");
return false; return false;
@@ -1213,23 +1149,14 @@ bool SessionContext::QueryKeyControlBlock(const KeyId& key_id, uint32_t* data) {
OEMCryptoResult SessionContext::SelectContentKey( OEMCryptoResult SessionContext::SelectContentKey(
const KeyId& key_id, OEMCryptoCipherMode cipher_mode) { 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_) { if (!session_keys_) {
LOGE("Select Key: no session keys."); LOGE("Select Key: no session keys.");
return OEMCrypto_ERROR_INVALID_CONTEXT; return OEMCrypto_ERROR_INVALID_CONTEXT;
} }
Key* content_key = session_keys_->Find(key_id); Key* content_key = session_keys_->Find(key_id);
if (NULL == content_key) { if (NULL == content_key) {
LOGE("[SelectContentKey(): No key matches key id]"); LOGE("No key matches key id");
return OEMCrypto_ERROR_NO_CONTENT_KEY; return OEMCrypto_KEY_NOT_LOADED;
}
if (LogCategoryEnabled(kLoggingTraceDecryption)) {
LOGI((" Select Key: key = " + wvcdm::b2a_hex(content_key->value()))
.c_str());
} }
content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR); content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR);
current_content_key_ = content_key; current_content_key_ = content_key;
@@ -1281,10 +1208,6 @@ OEMCryptoResult SessionContext::LoadUsageEntry(
mac_key_client_ = std::vector<uint8_t>( mac_key_client_ = std::vector<uint8_t>(
usage_entry_->mac_key_client(), usage_entry_->mac_key_client(),
usage_entry_->mac_key_client() + wvoec::MAC_KEY_SIZE); 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; return result;
} }
@@ -1355,8 +1278,8 @@ OEMCryptoResult SessionContext::DecryptCENC(
// If the data is clear, we do not need a current key selected. // If the data is clear, we do not need a current key selected.
if (!is_encrypted) { if (!is_encrypted) {
if (buffer_type != OEMCrypto_BufferType_Direct) { if (buffer_type != OEMCrypto_BufferType_Direct) {
memcpy(reinterpret_cast<uint8_t*>(clear_data), cipher_data, memmove(reinterpret_cast<uint8_t*>(clear_data), cipher_data,
cipher_data_length); cipher_data_length);
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
// For reference implementation, we quietly drop the clear direct video. // For reference implementation, we quietly drop the clear direct video.
@@ -1421,7 +1344,7 @@ OEMCryptoResult SessionContext::DecryptCBC(
pattern_offset = (pattern_offset + 1) % pattern_length; pattern_offset = (pattern_offset + 1) % pattern_length;
} }
if (skip_block || (size < AES_BLOCK_SIZE)) { if (skip_block || (size < AES_BLOCK_SIZE)) {
memcpy(&clear_data[l], &cipher_data[l], size); memmove(&clear_data[l], &cipher_data[l], size);
} else { } else {
uint8_t aes_output[AES_BLOCK_SIZE]; uint8_t aes_output[AES_BLOCK_SIZE];
// Save the iv for the next block, in case cipher_data is in the same // 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; pattern_offset = (pattern_offset + 1) % pattern_length;
} }
if (skip_block) { if (skip_block) {
memcpy(&clear_data[l], &cipher_data[l], size); memmove(&clear_data[l], &cipher_data[l], size);
} else { } else {
uint8_t aes_output[AES_BLOCK_SIZE]; uint8_t aes_output[AES_BLOCK_SIZE];
AES_encrypt(iv, aes_output, &aes_key); 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 // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#ifndef REF_OEMCRYPTO_SESSION_H_ #ifndef REF_OEMCRYPTO_SESSION_H_
#define REF_OEMCRYPTO_SESSION_H_ #define REF_OEMCRYPTO_SESSION_H_
@@ -14,14 +14,14 @@
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include "OEMCryptoCENC.h" // Needed for enums only. #include "OEMCryptoCENC.h"
#include "oemcrypto_auth_ref.h" #include "oemcrypto_auth_ref.h"
#include "oemcrypto_key_ref.h" #include "oemcrypto_key_ref.h"
#include "oemcrypto_nonce_table.h" #include "oemcrypto_nonce_table.h"
#include "oemcrypto_rsa_key_shared.h" #include "oemcrypto_rsa_key_shared.h"
#include "oemcrypto_session_key_table.h" #include "oemcrypto_session_key_table.h"
#include "oemcrypto_usage_table_ref.h"
#include "oemcrypto_types.h" #include "oemcrypto_types.h"
#include "oemcrypto_usage_table_ref.h"
namespace wvoec_ref { namespace wvoec_ref {
@@ -74,26 +74,25 @@ class SessionContext {
usage_entry_(NULL), usage_entry_(NULL),
srm_requirements_status_(NoSRMVersion), srm_requirements_status_(NoSRMVersion),
usage_entry_status_(kNoUsageEntry) {} usage_entry_status_(kNoUsageEntry) {}
~SessionContext(); virtual ~SessionContext();
bool isValid() { return valid_; } bool isValid() { return valid_; }
bool DeriveKeys(const std::vector<uint8_t>& master_key, virtual bool DeriveKeys(const std::vector<uint8_t>& master_key,
const std::vector<uint8_t>& mac_context, const std::vector<uint8_t>& mac_context,
const std::vector<uint8_t>& enc_context); const std::vector<uint8_t>& enc_context);
bool RSADeriveKeys(const std::vector<uint8_t>& enc_session_key, virtual bool RSADeriveKeys(const std::vector<uint8_t>& enc_session_key,
const std::vector<uint8_t>& mac_context, const std::vector<uint8_t>& mac_context,
const std::vector<uint8_t>& enc_context); const std::vector<uint8_t>& enc_context);
bool GenerateSignature(const uint8_t* message, size_t message_length, virtual bool GenerateSignature(const uint8_t* message, size_t message_length,
uint8_t* signature, size_t* signature_length); uint8_t* signature, size_t* signature_length);
size_t RSASignatureSize(); size_t RSASignatureSize();
OEMCryptoResult GenerateRSASignature(const uint8_t* message, virtual OEMCryptoResult GenerateRSASignature(
size_t message_length, const uint8_t* message, size_t message_length, uint8_t* signature,
uint8_t* signature, size_t* signature_length, RSA_Padding_Scheme padding_scheme);
size_t* signature_length, virtual bool ValidateMessage(const uint8_t* message, size_t message_length,
RSA_Padding_Scheme padding_scheme); const uint8_t* signature,
bool ValidateMessage(const uint8_t* message, size_t message_length, size_t signature_length);
const uint8_t* signature, size_t signature_length);
OEMCryptoResult DecryptCENC(const uint8_t* iv, size_t block_offset, OEMCryptoResult DecryptCENC(const uint8_t* iv, size_t block_offset,
const OEMCrypto_CENCEncryptPatternDesc* pattern, const OEMCrypto_CENCEncryptPatternDesc* pattern,
const uint8_t* cipher_data, const uint8_t* cipher_data,
@@ -118,7 +117,7 @@ class SessionContext {
size_t signature_length); size_t signature_length);
void StartTimer(); void StartTimer();
uint32_t CurrentTimer(); // (seconds). uint32_t CurrentTimer(); // (seconds).
OEMCryptoResult LoadKeys( virtual OEMCryptoResult LoadKeys(
const uint8_t* message, size_t message_length, const uint8_t* signature, const uint8_t* message, size_t message_length, const uint8_t* signature,
size_t signature_length, const uint8_t* enc_mac_key_iv, size_t signature_length, const uint8_t* enc_mac_key_iv,
const uint8_t* enc_mac_keys, size_t num_keys, 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, size_t pst_length, const uint8_t* srm_requirement,
OEMCrypto_LicenseType license_type); OEMCrypto_LicenseType license_type);
OEMCryptoResult LoadEntitledContentKeys( OEMCryptoResult LoadEntitledContentKeys(
size_t num_keys, size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array);
const OEMCrypto_EntitledContentKeyObject* key_array); virtual OEMCryptoResult InstallKey(const KeyId& key_id,
OEMCryptoResult InstallKey(const KeyId& key_id, const std::vector<uint8_t>& key_data,
const std::vector<uint8_t>& key_data, const std::vector<uint8_t>& key_data_iv,
const std::vector<uint8_t>& key_data_iv, const std::vector<uint8_t>& key_control,
const std::vector<uint8_t>& key_control, const std::vector<uint8_t>& key_control_iv,
const std::vector<uint8_t>& key_control_iv, bool second_license);
bool second_license);
bool InstallRSAEncryptedKey(const uint8_t* encrypted_message_key, bool InstallRSAEncryptedKey(const uint8_t* encrypted_message_key,
size_t encrypted_message_key_length); size_t encrypted_message_key_length);
bool DecryptRSAKey(const uint8_t* enc_rsa_key, size_t enc_rsa_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, 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); 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); bool LoadRSAKey(const uint8_t* pkcs8_rsa_key, size_t rsa_key_length);
OEMCryptoResult RefreshKey(const KeyId& key_id, virtual OEMCryptoResult RefreshKey(
const std::vector<uint8_t>& key_control, const KeyId& key_id, const std::vector<uint8_t>& key_control,
const std::vector<uint8_t>& key_control_iv); const std::vector<uint8_t>& key_control_iv);
bool UpdateMacKeys(const std::vector<uint8_t>& mac_keys, virtual bool UpdateMacKeys(const std::vector<uint8_t>& mac_keys,
const std::vector<uint8_t>& iv); const std::vector<uint8_t>& iv);
bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data); virtual bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data);
OEMCryptoResult SelectContentKey(const KeyId& key_id, virtual OEMCryptoResult SelectContentKey(const KeyId& key_id,
OEMCryptoCipherMode cipher_mode); OEMCryptoCipherMode cipher_mode);
const Key* current_content_key(void) { return current_content_key_; } const Key* current_content_key(void) { return current_content_key_; }
void set_mac_key_server(const std::vector<uint8_t>& mac_key_server) { void set_mac_key_server(const std::vector<uint8_t>& mac_key_server) {
mac_key_server_ = mac_key_server; mac_key_server_ = mac_key_server;
@@ -169,20 +167,20 @@ class SessionContext {
bool CheckNonce(uint32_t nonce); bool CheckNonce(uint32_t nonce);
void FlushNonces(); void FlushNonces();
OEMCryptoResult CreateNewUsageEntry(uint32_t* usage_entry_number); virtual OEMCryptoResult CreateNewUsageEntry(uint32_t* usage_entry_number);
OEMCryptoResult LoadUsageEntry(uint32_t index, virtual OEMCryptoResult LoadUsageEntry(uint32_t index,
const std::vector<uint8_t>& buffer); const std::vector<uint8_t>& buffer);
OEMCryptoResult UpdateUsageEntry(uint8_t* header_buffer, virtual OEMCryptoResult UpdateUsageEntry(uint8_t* header_buffer,
size_t* header_buffer_length, size_t* header_buffer_length,
uint8_t* entry_buffer, uint8_t* entry_buffer,
size_t* entry_buffer_length); size_t* entry_buffer_length);
OEMCryptoResult DeactivateUsageEntry(const std::vector<uint8_t>& pst); virtual OEMCryptoResult DeactivateUsageEntry(const std::vector<uint8_t>& pst);
OEMCryptoResult ReportUsage(const std::vector<uint8_t>& pst, uint8_t* buffer, virtual OEMCryptoResult ReportUsage(const std::vector<uint8_t>& pst,
size_t* buffer_length); uint8_t* buffer, size_t* buffer_length);
OEMCryptoResult MoveEntry(uint32_t new_index); OEMCryptoResult MoveEntry(uint32_t new_index);
OEMCryptoResult CopyOldUsageEntry(const std::vector<uint8_t>& pst); OEMCryptoResult CopyOldUsageEntry(const std::vector<uint8_t>& pst);
private: protected:
bool DeriveKey(const std::vector<uint8_t>& key, bool DeriveKey(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& context, int counter, const std::vector<uint8_t>& context, int counter,
std::vector<uint8_t>* out); std::vector<uint8_t>* out);

View File

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

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#ifndef REF_OEMCRYPTO_SESSION_KEY_TABLE_H_ #ifndef REF_OEMCRYPTO_SESSION_KEY_TABLE_H_
#define 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 // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#include "oemcrypto_usage_table_ref.h" #include "oemcrypto_usage_table_ref.h"
@@ -20,7 +20,6 @@
#include "file_store.h" #include "file_store.h"
#include "log.h" #include "log.h"
#include "oemcrypto_engine_ref.h" #include "oemcrypto_engine_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_old_usage_table_ref.h" #include "oemcrypto_old_usage_table_ref.h"
// TODO(fredgc): Setting the device files base bath is currently broken as // TODO(fredgc): Setting the device files base bath is currently broken as
// wvcdm::Properties is no longer used by the reference code. // 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); pst_report.set_pst_length(data_.pst_length);
memcpy(pst_report.pst(), data_.pst, data_.pst_length); memcpy(pst_report.pst(), data_.pst, data_.pst_length);
unsigned int md_len = SHA_DIGEST_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, if (!HMAC(EVP_sha1(), data_.mac_key_client, wvoec::MAC_KEY_SIZE,
buffer + SHA_DIGEST_LENGTH, length_needed - SHA_DIGEST_LENGTH, buffer + SHA_DIGEST_LENGTH, length_needed - SHA_DIGEST_LENGTH,
pst_report.signature(), &md_len)) { 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. // This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox 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();
const std::vector<uint8_t>& key = ce->DeviceRootKey(override_to_real);
// Encrypt the entry. // Encrypt the entry.
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE); 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. // This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox 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();
const std::vector<uint8_t>& key = ce->DeviceRootKey(override_to_real);
// Verify the signature of the usage entry. Sign encrypted into clear buffer. // Verify the signature of the usage entry. Sign encrypted into clear buffer.
unsigned int sig_length = SHA256_DIGEST_LENGTH; unsigned int sig_length = SHA256_DIGEST_LENGTH;
@@ -319,13 +307,6 @@ OEMCryptoResult UsageTableEntry::CopyOldUsageEntry(
} else { } else {
memcpy(data_.mac_key_client, &(old_entry->mac_key_client_[0]), memcpy(data_.mac_key_client, &(old_entry->mac_key_client_[0]),
wvoec::MAC_KEY_SIZE); 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) { if (pst.size() > kMaxPSTLength) {
LOGE("CopyOldEntry: PST Length was too large. Truncating."); LOGE("CopyOldEntry: PST Length was too large. Truncating.");
@@ -385,6 +366,10 @@ OEMCryptoResult UsageTable::UpdateUsageEntry(SessionContext* session,
return result; return result;
} }
UsageTableEntry* UsageTable::MakeEntry(uint32_t index) {
return new UsageTableEntry(this, index, master_generation_number_);
}
OEMCryptoResult UsageTable::CreateNewUsageEntry(SessionContext* session, OEMCryptoResult UsageTable::CreateNewUsageEntry(SessionContext* session,
UsageTableEntry** entry, UsageTableEntry** entry,
uint32_t* usage_entry_number) { uint32_t* usage_entry_number) {
@@ -395,8 +380,12 @@ OEMCryptoResult UsageTable::CreateNewUsageEntry(SessionContext* session,
if (!entry) return OEMCrypto_ERROR_UNKNOWN_FAILURE; if (!entry) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
if (!usage_entry_number) return OEMCrypto_ERROR_UNKNOWN_FAILURE; if (!usage_entry_number) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
uint32_t index = generation_numbers_.size(); uint32_t index = generation_numbers_.size();
UsageTableEntry* new_entry = size_t max = ce_->max_usage_table_size();
new UsageTableEntry(this, index, master_generation_number_); 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_); generation_numbers_.push_back(master_generation_number_);
sessions_.push_back(session); sessions_.push_back(session);
master_generation_number_++; master_generation_number_++;
@@ -420,8 +409,12 @@ OEMCryptoResult UsageTable::LoadUsageEntry(SessionContext* session,
LOGE("LoadUsageEntry: index %d used by other session.", index); LOGE("LoadUsageEntry: index %d used by other session.", index);
return OEMCrypto_ERROR_INVALID_SESSION; return OEMCrypto_ERROR_INVALID_SESSION;
} }
UsageTableEntry* new_entry = size_t max = ce_->max_usage_table_size();
new UsageTableEntry(this, index, master_generation_number_); 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); OEMCryptoResult status = new_entry->LoadData(ce_, index, buffer);
if (status != OEMCrypto_SUCCESS) { 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. // This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox 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();
const std::vector<uint8_t>& key = ce_->DeviceRootKey(override_to_real);
// Encrypt the entry. // Encrypt the entry.
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE); RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
@@ -530,6 +522,12 @@ OEMCryptoResult UsageTable::LoadUsageTableHeader(
if (!LoadGenerationNumber(false)) return OEMCrypto_ERROR_UNKNOWN_FAILURE; if (!LoadGenerationNumber(false)) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
if (buffer.size() < SignedHeaderSize(0)) return OEMCrypto_ERROR_SHORT_BUFFER; 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()); std::vector<uint8_t> clear_buffer(buffer.size());
SignedHeaderBlock* clear = SignedHeaderBlock* clear =
reinterpret_cast<SignedHeaderBlock*>(&clear_buffer[0]); reinterpret_cast<SignedHeaderBlock*>(&clear_buffer[0]);
@@ -538,8 +536,7 @@ OEMCryptoResult UsageTable::LoadUsageTableHeader(
// This should be encrypted and signed with a device specific key. // This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox 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();
const std::vector<uint8_t>& key = ce_->DeviceRootKey(override_to_real);
// Verify the signature of the usage entry. Sign encrypted into clear buffer. // Verify the signature of the usage entry. Sign encrypted into clear buffer.
unsigned int sig_length = SHA256_DIGEST_LENGTH; 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 // source code may only be used and distributed under the Widevine Master
// License Agreement. // License Agreement.
// //
// Ref implementation of OEMCrypto APIs // Reference implementation of OEMCrypto APIs
// //
#ifndef OEMCRYPTO_USAGE_TABLE_REF_H_ #ifndef OEMCRYPTO_USAGE_TABLE_REF_H_
#define OEMCRYPTO_USAGE_TABLE_REF_H_ #define OEMCRYPTO_USAGE_TABLE_REF_H_
@@ -42,8 +42,7 @@ struct StoredUsageEntry {
class UsageTableEntry { class UsageTableEntry {
public: public:
UsageTableEntry(UsageTable* table, uint32_t index, int64_t generation); UsageTableEntry(UsageTable* table, uint32_t index, int64_t generation);
// owner_(owner), session_(session), loaded_(false) {} virtual ~UsageTableEntry(); // Free memory, remove reference in header.
~UsageTableEntry(); // Free memory, remove reference in header.
bool Inactive() { return data_.status >= kInactive; } bool Inactive() { return data_.status >= kInactive; }
OEMCryptoResult SetPST(const uint8_t* pst, size_t pst_length); OEMCryptoResult SetPST(const uint8_t* pst, size_t pst_length);
bool VerifyPST(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. // for update.
bool CheckForUse(); bool CheckForUse();
void Deactivate(const std::vector<uint8_t>& pst); void Deactivate(const std::vector<uint8_t>& pst);
OEMCryptoResult ReportUsage(const std::vector<uint8_t>& pst, uint8_t* buffer, virtual OEMCryptoResult ReportUsage(const std::vector<uint8_t>& pst,
size_t* buffer_length); uint8_t* buffer, size_t* buffer_length);
void UpdateAndIncrement(); virtual void UpdateAndIncrement();
OEMCryptoResult SaveData(CryptoEngine* ce, SessionContext* session, OEMCryptoResult SaveData(CryptoEngine* ce, SessionContext* session,
uint8_t* signed_buffer, size_t buffer_size); uint8_t* signed_buffer, size_t buffer_size);
OEMCryptoResult LoadData(CryptoEngine* ce, uint32_t index, OEMCryptoResult LoadData(CryptoEngine* ce, uint32_t index,
const std::vector<uint8_t>& buffer); 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; } int64_t generation_number() { return data_.generation_number; }
void set_generation_number(int64_t value) { data_.generation_number = value; } void set_generation_number(int64_t value) { data_.generation_number = value; }
void set_index(int32_t index) { data_.index = index; } 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_server() { return data_.mac_key_server; }
const uint8_t* mac_key_client() { return data_.mac_key_client; } const uint8_t* mac_key_client() { return data_.mac_key_client; }
private: protected:
UsageTable* usage_table_; // Owner of this object. UsageTable* usage_table_; // Owner of this object.
bool recent_decrypt_; bool recent_decrypt_;
bool forbid_report_; bool forbid_report_;
@@ -82,8 +81,8 @@ class UsageTableEntry {
class UsageTable { class UsageTable {
public: public:
explicit UsageTable(CryptoEngine* ce) explicit UsageTable(CryptoEngine* ce)
: ce_(ce), header_loaded_(false), old_table_(NULL){}; : ce_(ce), header_loaded_(false), old_table_(NULL) {};
~UsageTable(); virtual ~UsageTable();
OEMCryptoResult CreateNewUsageEntry(SessionContext* session, OEMCryptoResult CreateNewUsageEntry(SessionContext* session,
UsageTableEntry** entry, UsageTableEntry** entry,
@@ -113,23 +112,23 @@ class UsageTable {
uint64_t time_since_first_decrypt, uint64_t time_since_first_decrypt,
uint64_t time_since_last_decrypt, uint64_t time_since_last_decrypt,
OEMCrypto_Usage_Entry_Status status, OEMCrypto_Usage_Entry_Status status,
uint8_t *server_mac_key, uint8_t* server_mac_key,
uint8_t *client_mac_key, uint8_t* client_mac_key,
const uint8_t* pst, const uint8_t* pst, size_t pst_length);
size_t pst_length);
private: protected:
OEMCryptoResult SaveUsageTableHeader(uint8_t* signed_buffer, virtual UsageTableEntry* MakeEntry(uint32_t index);
size_t buffer_size); virtual OEMCryptoResult SaveUsageTableHeader(uint8_t* signed_buffer,
bool SaveGenerationNumber(); size_t buffer_size);
bool LoadGenerationNumber(bool or_make_new_one); virtual bool SaveGenerationNumber();
virtual bool LoadGenerationNumber(bool or_make_new_one);
CryptoEngine* ce_; CryptoEngine* ce_;
bool header_loaded_; bool header_loaded_;
int64_t master_generation_number_; int64_t master_generation_number_;
std::vector<int64_t> generation_numbers_; std::vector<int64_t> generation_numbers_;
std::vector<SessionContext*> sessions_; std::vector<SessionContext*> sessions_;
OldUsageTable *old_table_; OldUsageTable* old_table_;
}; };
} // namespace wvoec_ref } // 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 < 12) FilterOut(&filter, "*API12*");
if (api_version < 13) FilterOut(&filter, "*API13*"); if (api_version < 13) FilterOut(&filter, "*API13*");
if (api_version < 14) FilterOut(&filter, "*API14*"); 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 // Some tests may require root access. If user is not root, filter these tests
// out. // out.
if (getuid()) { if (getuid()) {

View File

@@ -1094,9 +1094,14 @@ void Session::InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key) {
GenerateDerivedKeysFromSessionKey(); GenerateDerivedKeysFromSessionKey();
} }
void Session::CreateNewUsageEntry() { void Session::CreateNewUsageEntry(OEMCryptoResult* status) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCryptoResult result =
OEMCrypto_CreateNewUsageEntry(session_id(), &usage_entry_number_)); 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) { 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. // GenerateDerivedKeysFromSessionKey to install known encryption and mac keys.
void InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key); void InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key);
// Creates a new usage entry, and keeps track of the index. // 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. // Copy encrypted usage entry from other session, and then load it.
// This session must already be open. // This session must already be open.
void LoadUsageEntry(uint32_t index, const vector<uint8_t>& buffer); 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 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 // 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). // totient. That means e*d = 1 mod lambda, where lambda = lcm(p-1, q-1).
static const uint8_t kTestKeyRSACarmichael_2048[] = { static const uint8_t kTestKeyRSACarmichael_2048[] = {

View File

@@ -24,6 +24,7 @@
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <string> #include <string>
#include <sstream>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -36,25 +37,21 @@
#include "oemcrypto_types.h" #include "oemcrypto_types.h"
#include "string_conversions.h" #include "string_conversions.h"
#ifdef CDM_TESTS
#include "properties.h"
#endif
using ::testing::Bool; using ::testing::Bool;
using ::testing::Combine; using ::testing::Combine;
using ::testing::Range; using ::testing::Range;
using ::testing::Values; using ::testing::Values;
using ::testing::WithParamInterface; using ::testing::WithParamInterface;
using ::testing::tuple;
using namespace std; using namespace std;
using std::tr1::tuple;
namespace std { // GTest wants PrintTo to be in the std namespace. namespace std { // GTest wants PrintTo to be in the std namespace.
void PrintTo(const tuple<OEMCrypto_CENCEncryptPatternDesc, OEMCryptoCipherMode, void PrintTo(const tuple<OEMCrypto_CENCEncryptPatternDesc, OEMCryptoCipherMode,
bool>& param, bool>& param,
ostream* os) { ostream* os) {
OEMCrypto_CENCEncryptPatternDesc pattern = std::tr1::get<0>(param); OEMCrypto_CENCEncryptPatternDesc pattern = ::testing::get<0>(param);
OEMCryptoCipherMode mode = std::tr1::get<1>(param); OEMCryptoCipherMode mode = ::testing::get<1>(param);
bool decrypt_inplace = std::tr1::get<2>(param); bool decrypt_inplace = ::testing::get<2>(param);
*os << ((mode == OEMCrypto_CipherMode_CTR) ? "CTR mode" : "CBC mode") *os << ((mode == OEMCrypto_CipherMode_CTR) ? "CTR mode" : "CBC mode")
<< ", encrypt=" << pattern.encrypt << ", skip=" << pattern.skip << ", encrypt=" << pattern.encrypt << ", skip=" << pattern.skip
<< ", decrypt in place = " << (decrypt_inplace ? "true" : "false"); << ", decrypt in place = " << (decrypt_inplace ? "true" : "false");
@@ -76,9 +73,6 @@ class OEMCryptoClientTest : public ::testing::Test, public SessionUtil {
virtual void SetUp() { virtual void SetUp() {
::testing::Test::SetUp(); ::testing::Test::SetUp();
#ifdef CDM_TESTS
wvcdm::Properties::Init();
#endif
wvcdm::g_cutoff = wvcdm::LOG_INFO; wvcdm::g_cutoff = wvcdm::LOG_INFO;
const ::testing::TestInfo* const test_info = const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_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."; << "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) { TEST_F(OEMCryptoKeyboxTest, NormalGetDeviceId) {
OEMCryptoResult sts; OEMCryptoResult sts;
@@ -530,6 +538,11 @@ TEST_F(OEMCryptoProv30Test, DeviceClaimsOEMCertificate) {
ASSERT_EQ(OEMCrypto_OEMCertificate, OEMCrypto_GetProvisioningMethod()); 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) { TEST_F(OEMCryptoProv30Test, OEMCertValid) {
Session s; Session s;
ASSERT_NO_FATAL_FAILURE(s.open()); ASSERT_NO_FATAL_FAILURE(s.open());
@@ -1654,9 +1667,9 @@ class OEMCryptoSessionTestsDecryptTests
protected: protected:
virtual void SetUp() { virtual void SetUp() {
OEMCryptoSessionTests::SetUp(); OEMCryptoSessionTests::SetUp();
pattern_ = std::tr1::get<0>(GetParam()); pattern_ = ::testing::get<0>(GetParam());
cipher_mode_ = std::tr1::get<1>(GetParam()); cipher_mode_ = ::testing::get<1>(GetParam());
decrypt_inplace_ = std::tr1::get<2>(GetParam()); decrypt_inplace_ = ::testing::get<2>(GetParam());
} }
void FindTotalSize() { void FindTotalSize() {
@@ -1849,9 +1862,9 @@ class OEMCryptoSessionTestsPartialBlockTests
: public OEMCryptoSessionTestsDecryptTests {}; : public OEMCryptoSessionTestsDecryptTests {};
TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) { 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 // 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)); subsample_size_.push_back(SampleSize(0, 400));
FindTotalSize(); FindTotalSize();
vector<uint8_t> unencryptedData(total_size_); vector<uint8_t> unencryptedData(total_size_);
@@ -2030,6 +2043,21 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptLargeBuffer) {
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData); 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) { TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptUnencrypted) {
subsample_size_.push_back(SampleSize(256, 0)); subsample_size_.push_back(SampleSize(256, 0));
FindTotalSize(); FindTotalSize();
@@ -2515,6 +2543,41 @@ TEST_F(OEMCryptoLoadsCertificate, TestCarmichaelRSAKey) {
ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR()); 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. // Devices that load certificates, should at least support RSA 2048 keys.
TEST_F(OEMCryptoLoadsCertificate, SupportsCertificatesAPI13) { TEST_F(OEMCryptoLoadsCertificate, SupportsCertificatesAPI13) {
ASSERT_NE(0u, ASSERT_NE(0u,
@@ -4528,6 +4591,30 @@ TEST_P(UsageTableTestWithMAC, OnlineLicense) {
s.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE)); 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) { TEST_P(UsageTableTestWithMAC, ForbidReportWithNoUpdate) {
std::string pst = "my_pst"; std::string pst = "my_pst";
Session s; Session s;
@@ -4657,65 +4744,6 @@ TEST_F(UsageTableTest, OnlineMissingEntry) {
ASSERT_NO_FATAL_FAILURE(s.close()); 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) { TEST_P(UsageTableTestWithMAC, GenericCryptoEncrypt) {
std::string pst = "A PST"; std::string pst = "A PST";
uint32_t nonce = session_.get_nonce(); uint32_t nonce = session_.get_nonce();
@@ -5122,6 +5150,49 @@ TEST_P(UsageTableTestWithMAC, DeactivateOfflineLicense) {
EXPECT_EQ(kInactiveUsed, s3.pst_report().status()); 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) { TEST_P(UsageTableTestWithMAC, BadRange) {
std::string pst = "my_pst"; std::string pst = "my_pst";
Session s; Session s;
@@ -5347,6 +5418,95 @@ TEST_F(UsageTableDefragTest, ReloadUsageEntryBadData) {
&data[0], data.size())); &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) { TEST_F(UsageTableTest, CopyOldEntries) {
// First create three old entries. We open sessions first to force creation // First create three old entries. We open sessions first to force creation
// of the mac keys. // 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) { TEST_F(OEMCryptoAndroidLMPTest, MinVersionNumber9) {
uint32_t version = OEMCrypto_APIVersion(); uint32_t version = OEMCrypto_APIVersion();
ASSERT_LE(9u, version); ASSERT_LE(9u, version);
@@ -142,10 +148,10 @@ TEST_F(OEMCryptoAndroidOCTest, MinVersionNumber13) {
ASSERT_GE(version, 13u); ASSERT_GE(version, 13u);
} }
// These tests are required for Pi MR1 Android devices. // These tests are required for Q Android devices.
class OEMCryptoAndroidPiMR1Test : public OEMCryptoAndroidOCTest {}; class OEMCryptoAndroidQTest : public OEMCryptoAndroidOCTest {};
TEST_F(OEMCryptoAndroidPiMR1Test, MinVersionNumber14) { TEST_F(OEMCryptoAndroidQTest, MinVersionNumber14) {
uint32_t version = OEMCrypto_APIVersion(); uint32_t version = OEMCrypto_APIVersion();
ASSERT_GE(version, 14u); ASSERT_GE(version, 14u);
} }

View File

@@ -4,9 +4,6 @@
#include "OEMCryptoCENC.h" #include "OEMCryptoCENC.h"
#include "log.h" #include "log.h"
#include "oec_device_features.h" #include "oec_device_features.h"
#ifdef CDM_TESTS
#include "properties.h"
#endif
static void acknowledge_cast() { static void acknowledge_cast() {
std::cout std::cout
@@ -17,9 +14,6 @@ static void acknowledge_cast() {
int main(int argc, char** argv) { int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
#ifdef CDM_TESTS
wvcdm::Properties::Init();
#endif
wvcdm::g_cutoff = wvcdm::LOG_INFO; wvcdm::g_cutoff = wvcdm::LOG_INFO;
bool is_cast_receiver = false; bool is_cast_receiver = false;
bool force_load_test_keybox = 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 // 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_ #ifndef WVCDM_UTIL_DISALLOW_COPY_AND_ASSIGN_H_
#define 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 // 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 // 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 // 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_ #ifndef WVCDM_UTIL_STRING_CONVERSIONS_H_
#define 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" #include "string_conversions.h"