OEMCrypto and OPK 19.6.0

GitOrigin-RevId: 13a33e34413c19da1bfe76abcc66be519c9ac9d1
This commit is contained in:
Googler
2025-05-30 14:47:25 -07:00
committed by mattfedd
parent 98dfef4389
commit b47d0c2db0
51 changed files with 677 additions and 1182 deletions

View File

@@ -2,6 +2,29 @@
[TOC]
## [Version 19.6][v19.6]
### API
- Added new L3 API functions `OEMCrypto_LoadLicenseData()` and
`OEMCrypto_SaveLicenseData()`.
### Tests
- Updated `OEMCryptoClientTest.CheckBuildInformation_OutputLengthAPI17` to
accept a returned SHORT_BUFFER size that is larger than the actual required
size.
- Updated `OEMCryptoClientTest.CheckJsonBuildInformationAPI18` to treat the
JSON fields in the `ree` block as optional.
### OPK
- OPK_SharedBuffer_Reset optimized to zero out used memory only.
- OPK_BumpAllocator_Reset optimized to zero out used memory only.
- OPKI_ObjectTable mutable struct members separated from immutable members.
- Update reference BCC implementation to set leaf node profile name to
"widevine.<version>"
## [Version 19.5][v19.5]
This release adds new OEMCrypto APIs to support CAS PVR. It also includes test

View File

@@ -33,8 +33,8 @@ void InitLogging() {
void Log(const char* file, const char* function, int line, LogPriority level,
const char* fmt, ...) {
const char* severities[] = {"ERROR", "WARN", "INFO", "DEBUG", "VERBOSE"};
if (level < 0 || level >= static_cast<LogPriority>(sizeof(severities) /
sizeof(severities[0]))) {
if (level < 0 || static_cast<size_t>(level) >=
sizeof(severities) / sizeof(severities[0])) {
fprintf(kOutputFile, "[FATAL:%s(%d):%s] Invalid log priority level: %d\n",
file, line, function, level);
return;

View File

@@ -1,159 +0,0 @@
#!/usr/bin/python3
# Copyright 2017 Google LLC. All Rights Reserved.
"""Common test utility functions for OEM certificate generation."""
import datetime
import io
from cryptography import x509
from cryptography.hazmat import backends
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509 import oid
import oem_certificate
_COUNTRY_NAME = 'US'
_STATE_OR_PROVINCE_NAME = 'WA'
_LOCALITY_NAME = 'Kirkland'
_ORGANIZATION_NAME = 'CompanyXYZ'
_ORGANIZATIONAL_UNIT_NAME = 'ContentProtection'
_NOT_VALID_BEFORE = datetime.datetime(2001, 8, 9)
_VALID_DURATION = 100
_LEAF_CERT_VALID_DURATION = 8000
_SYSTEM_ID = 2001
_ROOT_PRIVATE_KEY_PASSPHRASE = b'root_passphrase'
class ArgParseObject(object):
"""A convenient object to allow adding arbitrary attribute to it."""
def create_root_certificate_and_key():
"""Creates a root certificate and key."""
key = rsa.generate_private_key(
public_exponent=65537,
key_size=3072,
backend=backends.default_backend())
subject_name = x509.Name(
[x509.NameAttribute(oid.NameOID.COMMON_NAME, u'root_cert')])
certificate = oem_certificate.build_certificate(
subject_name, subject_name, None,
datetime.datetime(2001, 8, 9), 1000, key.public_key(), key, True)
return (key, certificate)
def setup_csr_args(country_name=_COUNTRY_NAME,
state_or_province_name=_STATE_OR_PROVINCE_NAME,
locality_name=_LOCALITY_NAME,
organization_name=_ORGANIZATION_NAME,
organizational_unit_name=_ORGANIZATIONAL_UNIT_NAME,
key_size=4096,
output_csr_file=None,
output_private_key_file=None,
passphrase=None,
common_name=None):
"""Sets up arguments to OEM Certificate generator for generating csr."""
args = ArgParseObject()
args.key_size = key_size
args.country_name = country_name
args.state_or_province_name = state_or_province_name
args.locality_name = locality_name
args.organization_name = organization_name
args.organizational_unit_name = organizational_unit_name
args.common_name = common_name
if output_csr_file:
args.output_csr_file = output_csr_file
else:
args.output_csr_file = io.BytesIO()
if output_private_key_file:
args.output_private_key_file = output_private_key_file
else:
args.output_private_key_file = io.BytesIO()
args.passphrase = passphrase
return args
def setup_intermediate_cert_args(
csr_bytes, root_key, root_certificate, not_valid_before=_NOT_VALID_BEFORE,
valid_duration=_VALID_DURATION, system_id=_SYSTEM_ID,
root_private_key_passphrase=_ROOT_PRIVATE_KEY_PASSPHRASE,
output_certificate_file=None):
"""Sets up args to OEM Cert generator for generating intermediate cert."""
args = ArgParseObject()
args.not_valid_before = not_valid_before
args.valid_duration = valid_duration
args.system_id = system_id
args.csr_file = io.BytesIO(csr_bytes)
args.root_private_key_passphrase = root_private_key_passphrase
if output_certificate_file:
args.output_certificate_file = output_certificate_file
else:
args.output_certificate_file = io.BytesIO()
serialized_private_key = root_key.private_bytes(
serialization.Encoding.DER,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.BestAvailableEncryption(
args.root_private_key_passphrase))
serialized_certificate = root_certificate.public_bytes(
serialization.Encoding.DER)
args.root_certificate_file = io.BytesIO(serialized_certificate)
args.root_private_key_file = io.BytesIO(serialized_private_key)
return args
def setup_leaf_cert_args(intermediate_key_bytes,
intermediate_certificate_bytes,
key_size=1024,
passphrase=None,
not_valid_before=_NOT_VALID_BEFORE,
valid_duration=_LEAF_CERT_VALID_DURATION,
output_certificate_file=None,
output_private_key_file=None):
"""Sets up args to OEM Certificate generator for generating leaf cert."""
args = ArgParseObject()
args.key_size = key_size
args.not_valid_before = not_valid_before
args.valid_duration = valid_duration
args.intermediate_private_key_passphrase = None
if output_certificate_file:
args.output_certificate_file = output_certificate_file
else:
args.output_certificate_file = io.BytesIO()
if output_private_key_file:
args.output_private_key_file = output_private_key_file
else:
args.output_private_key_file = io.BytesIO()
args.passphrase = passphrase
args.intermediate_private_key_file = io.BytesIO(
intermediate_key_bytes)
args.intermediate_certificate_file = io.BytesIO(
intermediate_certificate_bytes)
return args
def create_intermediate_certificate_and_key_bytes(key_size=4096,
passphrase=None,
pem_format=True):
"""Creates an intermediate certificate and key."""
csr_args = setup_csr_args(key_size=key_size, passphrase=passphrase)
oem_certificate.generate_csr(csr_args)
csr_bytes = csr_args.output_csr_file.getvalue()
root_key, root_certificate = create_root_certificate_and_key()
args = setup_intermediate_cert_args(csr_bytes, root_key, root_certificate)
oem_certificate.generate_intermediate_certificate(args)
cert_bytes = args.output_certificate_file.getvalue()
if pem_format:
cert = x509.load_der_x509_certificate(cert_bytes,
backends.default_backend())
cert_bytes = cert.public_bytes(serialization.Encoding.PEM)
return (csr_args.output_private_key_file.getvalue(), cert_bytes)

View File

@@ -3,7 +3,7 @@
// License Agreement.
/**
* @mainpage OEMCrypto API v19.5
* @mainpage OEMCrypto API v19.6
*
* OEMCrypto is the low level library implemented by the OEM to provide key and
* content protection, usually in a separate secure memory or process space. The
@@ -766,6 +766,8 @@ typedef enum OEMCrypto_SignatureHashAlgorithm {
#define OEMCrypto_GetBCCSignatureType _oecc156
#define OEMCrypto_GetPVRKey _oecc157
#define OEMCrypto_LoadPVRKey _oecc158
#define OEMCrypto_LoadLicenseData _oecc159
#define OEMCrypto_SaveLicenseData _oecc160
// clang-format on
/// @addtogroup initcontrol
@@ -1027,7 +1029,10 @@ OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session);
* state, an error of OEMCrypto_ERROR_INVALID_CONTEXT is returned.
*
* @param[in] session: handle for the session to be used.
* @param[out] nonce: pointer to memory to receive the computed nonce.
* @param[out] nonce pointer to memory to receive the computed nonce. The nonce
* will only be stored into this memory location if the function returns
* OEMCrypto_SUCCESS. If any other OEMCryptoResult is returned, the contents
* of the memory pointed to by nonce will remain unchanged.
*
* Results:
* nonce: the nonce is also stored in secure memory.
@@ -3639,7 +3644,9 @@ uint32_t OEMCrypto_MinorAPIVersion(void);
* defined
*
* While not required, another optional top level struct can be added to the
* build information string to provide information about liboemcrypto.so:
* build information string to provide information about liboemcrypto.so. The
* fields within this struct are not required, but if they are included they
* must match the listed data type:
* - "ree" {
* - "liboemcrypto_ver" [string]: liboemcrypto.so version in string format
* eg "2.15.0+tag". Note that this is separate from the "ta_ver" field
@@ -4314,8 +4321,8 @@ OEMCryptoResult OEMCrypto_LoadProvisioning(
* Receiver certificates may refuse to load these keys and return an error of
* OEMCrypto_ERROR_NOT_IMPLEMENTED. The main use case for these alternative
* signing algorithms is to support devices that use X509 certificates for
* authentication when acting as a ChromeCast receiver. This is not needed for
* devices that wish to send data to a ChromeCast. Keys loaded from this
* authentication when acting as a Google Cast receiver. This is not needed for
* devices that wish to send data to a Google Cast. Keys loaded from this
* function may not be used with OEMCrypto_PrepAndSignLicenseRequest().
*
* First, OEMCrypto should generate three secondary keys, mac_key[server],
@@ -4388,8 +4395,8 @@ OEMCryptoResult OEMCrypto_LoadProvisioning(
* algorithms may refuse to load these keys and return an error of
* OEMCrypto_ERROR_NOT_IMPLEMENTED. The main use case for these
* alternative signing algorithms is to support devices that use X.509
* certificates for authentication when acting as a ChromeCast receiver.
* This is not needed for devices that wish to send data to a ChromeCast.
* certificates for authentication when acting as a Google Cast receiver.
* This is not needed for devices that wish to send data to a Google Cast.
* 7. After possibly skipping past the first 8 bytes signifying the allowed
* signing algorithm, the rest of the buffer private_key contains an ECC
* private key or an RSA private key in PKCS#8 binary DER encoded
@@ -4562,7 +4569,7 @@ OEMCryptoResult OEMCrypto_LoadTestRSAKey(void);
*
* The second padding scheme is for devices that use X509 certificates for
* authentication. The main example is devices that work as a Cast receiver,
* like a ChromeCast, not for devices that wish to send to the Cast device,
* like a Google Cast, not for devices that wish to send to the Cast device,
* such as almost all Android devices. OEMs that do not support X509
* certificate authentication need not implement this function and can return
* OEMCrypto_ERROR_NOT_IMPLEMENTED.
@@ -6398,6 +6405,44 @@ OEMCryptoResult OEMCrypto_UseSecondaryKey(OEMCrypto_SESSION session_id,
*/
OEMCryptoResult OEMCrypto_MarkOfflineSession(OEMCrypto_SESSION session);
/**
* Loads the license data into the given session.
*
* @param[in] session: session id for operation.
* @param[in] data: the buffer to import.
* @param[in] data_length: the number of bytes in |data|.
*
* @ignore
* @retval OEMCrypto_SUCCESS on success
* @retval OEMCrypto_ERROR_INVALID_SESSION
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
* @retval OEMCrypto_ERROR_SESSION_STATE_LOST
* @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
* @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
*/
OEMCryptoResult OEMCrypto_LoadLicenseData(OEMCrypto_SESSION session,
const uint8_t* data,
size_t data_length);
/**
* Saves the license data for the given session.
*
* @param[in] session: session id for operation.
* @param[out] data: the buffer to export into.
* @param[in,out] data_length: (in) length of the data buffer, in bytes.
* (out) actual length of the data, in bytes.
*
* @ignore
* @retval OEMCrypto_SUCCESS on success
* @retval OEMCrypto_ERROR_INVALID_SESSION
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
* @retval OEMCrypto_ERROR_SESSION_STATE_LOST
* @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
* @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
*/
OEMCryptoResult OEMCrypto_SaveLicenseData(OEMCrypto_SESSION session,
uint8_t* data, size_t* data_length);
#ifdef __cplusplus
}
#endif

View File

@@ -1,675 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine
// License Agreement.
/*********************************************************************
* level3.h
*
* Reference APIs needed to support Widevine's crypto algorithms.
*********************************************************************/
#ifndef LEVEL3_OEMCRYPTO_H_
#define LEVEL3_OEMCRYPTO_H_
#include <stddef.h>
#include <stdint.h>
#include "OEMCryptoCENC.h"
#include "level3_file_system.h"
// clang-format off
#ifdef DYNAMIC_ADAPTER
#define Level3_IsInApp _lcc00
#define Level3_Initialize _lcc01
#define Level3_Terminate _lcc02
#define Level3_InstallKeyboxOrOEMCert _lcc03
#define Level3_GetKeyData _lcc04
#define Level3_IsKeyboxOrOEMCertValid _lcc05
#define Level3_GetDeviceID _lcc07
#define Level3_WrapKeyboxOrOEMCert _lcc08
#define Level3_OpenSession _lcc09
#define Level3_CloseSession _lcc10
#define Level3_GenerateSignature _lcc13
#define Level3_GenerateNonce _lcc14
#define Level3_RewrapDeviceRSAKey _lcc18
#define Level3_LoadDeviceRSAKey _lcc19
#define Level3_DeriveKeysFromSessionKey _lcc21
#define Level3_APIVersion _lcc22
#define Level3_Generic_Encrypt_V17 _lcc24
#define Level3_Generic_Decrypt_V17 _lcc25
#define Level3_Generic_Sign_V17 _lcc26
#define Level3_Generic_Verify_V17 _lcc27
#define Level3_SupportsUsageTable _lcc29
#define Level3_ReportUsage _lcc32
#define Level3_GetMaxNumberOfSessions _lcc37
#define Level3_GetNumberOfOpenSessions _lcc38
#define Level3_IsAntiRollbackHwPresent _lcc39
#define Level3_QueryKeyControl _lcc41
#define Level3_GetHDCPCapability _lcc44
#define Level3_LoadTestRSAKey _lcc45
#define Level3_SecurityPatchLevel _lcc46
#define Level3_GetProvisioningMethod _lcc49
#define Level3_RewrapDeviceRSAKey30 _lcc51
#define Level3_SupportedCertificates _lcc52
#define Level3_IsSRMUpdateSupported _lcc53
#define Level3_GetCurrentSRMVersion _lcc54
#define Level3_LoadSRM _lcc55
#define Level3_RemoveSRM _lcc57
#define Level3_CreateUsageTableHeader _lcc61
#define Level3_LoadUsageTableHeader _lcc62
#define Level3_CreateNewUsageEntry _lcc63
#define Level3_LoadUsageEntry _lcc64
#define Level3_UpdateUsageEntry _lcc65
#define Level3_ShrinkUsageTableHeader _lcc67
#define Level3_MoveEntry _lcc68
#define Level3_GetAnalogOutputFlags _lcc71
#define Level3_LoadTestKeybox _lcc78
#define Level3_SelectKey _lcc81
#define Level3_LoadKeys _lcc83
#define Level3_SetSandbox _lcc84
#define Level3_ResourceRatingTier _lcc85
#define Level3_SupportsDecryptHash _lcc86
#define Level3_SetDecryptHash_V18 _lcc88
#define Level3_GetHashErrorCode _lcc89
#define Level3_RefreshKeys _lcc91
#define Level3_LoadEntitledContentKeys_V16 _lcc92
#define Level3_CopyBuffer _lcc93
#define Level3_MaximumUsageTableHeaderSize _lcc94
#define Level3_GenerateDerivedKeys _lcc95
#define Level3_PrepAndSignLicenseRequest _lcc96
#define Level3_PrepAndSignRenewalRequest _lcc97
#define Level3_PrepAndSignProvisioningRequest _lcc98
#define Level3_LoadLicense_V18 _lcc99
#define Level3_LoadRenewal _lcc101
#define Level3_LoadProvisioning_V18 _lcc102
#define Level3_LoadOEMPrivateKey _lcc103
#define Level3_GetOEMPublicCertificate _lcc104
#define Level3_DecryptCENC_V17 _lcc105
#define Level3_LoadDRMPrivateKey _lcc107
#define Level3_MinorAPIVersion _lcc108
#define Level3_AllocateSecureBuffer _lcc109
#define Level3_FreeSecureBuffer _lcc110
#define Level3_CreateEntitledKeySession _lcc111
#define Level3_RemoveEntitledKeySession _lcc112
#define Level3_GetBootCertificateChain _lcc116
#define Level3_GenerateCertificateKeyPair _lcc117
#define Level3_InstallOemPrivateKey _lcc118
#define Level3_ReassociateEntitledKeySession _lcc119
#define Level3_LoadCasECMKeys _lcc120
#define Level3_LoadEntitledContentKeys _lcc121 // place holder for v17.
#define Level3_ProductionReady _lcc122
#define Level3_Idle _lcc123
#define Level3_Wake _lcc124
#define Level3_BuildInformation _lcc125
#define Level3_SecurityLevel _lcc126
#define Level3_ReuseUsageEntry _lcc127
#define Level3_GetDTCP2Capability _lcc128
#define Level3_GetWatermarkingSupport _lcc129
#define Level3_GetOEMKeyToken _lcc130
#define Level3_GetDeviceInformation _lcc131
#define Level3_SetMaxAPIVersion _lcc132
#define Level3_GetKeyHandle _lcc133
#define Level3_DecryptCENC _lcc134
#define Level3_Generic_Encrypt _lcc135
#define Level3_Generic_Decrypt _lcc136
#define Level3_Generic_Sign _lcc137
#define Level3_Generic_Verify _lcc138
#define Level3_GetSignatureHashAlgorithm _lcc139
#define Level3_EnterTestMode _lcc140
#define Level3_GetDeviceSignedCsrPayload _lcc141
#define Level3_SetDecryptHash _lcc143
#define Level3_LoadLicense _lcc144
#define Level3_LoadProvisioning _lcc145
#define Level3_LoadProvisioningCast _lcc146
#define Level3_PrepAndSignReleaseRequest _lcc147
#define Level3_GetUsageEntryInfo _lcc148
#define Level3_GetBCCType _lcc149
#define Level3_LoadRelease _lcc150
#define Level3_GetEmbeddedDrmCertificate _lcc151
#define Level3_UseSecondaryKey _lcc152
#define Level3_MarkOfflineSession _lcc153
#define Level3_SetSessionUsage _lcc155
#define Level3_GetBCCSignatureType _lcc156
#define Level3_GetPVRKey _lcc157
#define Level3_LoadPVRKey _lcc158
#else
#define Level3_Initialize _oecc01
#define Level3_Terminate _oecc02
#define Level3_InstallKeyboxOrOEMCert _oecc03
#define Level3_GetKeyData _oecc04
#define Level3_IsKeyboxOrOEMCertValid _oecc05
#define Level3_GetDeviceID _oecc07
#define Level3_WrapKeyboxOrOEMCert _oecc08
#define Level3_OpenSession _oecc09
#define Level3_CloseSession _oecc10
#define Level3_GenerateSignature _oecc13
#define Level3_GenerateNonce _oecc14
#define Level3_RewrapDeviceRSAKey _oecc18
#define Level3_LoadDeviceRSAKey _oecc19
#define Level3_DeriveKeysFromSessionKey _oecc21
#define Level3_APIVersion _oecc22
#define Level3_Generic_Encrypt_V17 _oecc24
#define Level3_Generic_Decrypt_V17 _oecc25
#define Level3_Generic_Sign_V17 _oecc26
#define Level3_Generic_Verify_V17 _oecc27
#define Level3_SupportsUsageTable _oecc29
#define Level3_ReportUsage _oecc32
#define Level3_GenerateRSASignature _oecc36
#define Level3_GetMaxNumberOfSessions _oecc37
#define Level3_GetNumberOfOpenSessions _oecc38
#define Level3_IsAntiRollbackHwPresent _oecc39
#define Level3_QueryKeyControl _oecc41
#define Level3_GetHDCPCapability _oecc44
#define Level3_LoadTestRSAKey _oecc45
#define Level3_SecurityPatchLevel _oecc46
#define Level3_GetProvisioningMethod _oecc49
#define Level3_RewrapDeviceRSAKey30 _oecc51
#define Level3_SupportedCertificates _oecc52
#define Level3_IsSRMUpdateSupported _oecc53
#define Level3_GetCurrentSRMVersion _oecc54
#define Level3_LoadSRM _oecc55
#define Level3_RemoveSRM _oecc57
#define Level3_CreateUsageTableHeader _oecc61
#define Level3_LoadUsageTableHeader _oecc62
#define Level3_CreateNewUsageEntry _oecc63
#define Level3_LoadUsageEntry _oecc64
#define Level3_UpdateUsageEntry _oecc65
#define Level3_DeactivateUsageEntry _oecc66
#define Level3_ShrinkUsageTableHeader _oecc67
#define Level3_MoveEntry _oecc68
#define Level3_GetAnalogOutputFlags _oecc71
#define Level3_LoadTestKeybox _oecc78
#define Level3_SelectKey _oecc81
#define Level3_LoadKeys _oecc83
#define Level3_SetSandbox _oecc84
#define Level3_ResourceRatingTier _oecc85
#define Level3_SupportsDecryptHash _oecc86
#define Level3_SetDecryptHash_V18 _oecc88
#define Level3_GetHashErrorCode _oecc89
#define Level3_RefreshKeys _oecc91
#define Level3_LoadEntitledContentKeys_V16 _oecc92
#define Level3_CopyBuffer _oecc93
#define Level3_MaximumUsageTableHeaderSize _oecc94
#define Level3_GenerateDerivedKeys _oecc95
#define Level3_PrepAndSignLicenseRequest _oecc96
#define Level3_PrepAndSignRenewalRequest _oecc97
#define Level3_PrepAndSignProvisioningRequest _oecc98
#define Level3_LoadLicense_V18 _oecc99
#define Level3_LoadRenewal _oecc101
#define Level3_LoadProvisioning_V18 _oecc102
#define Level3_LoadOEMPrivateKey _oecc103
#define Level3_GetOEMPublicCertificate _oecc104
#define Level3_DecryptCENC_V17 _oecc105
#define Level3_LoadDRMPrivateKey _oecc107
#define Level3_MinorAPIVersion _oecc108
#define Level3_AllocateSecureBuffer _oecc109
#define Level3_FreeSecureBuffer _oecc110
#define Level3_CreateEntitledKeySession _oecc111
#define Level3_RemoveEntitledKeySession _oecc112
#define Level3_GetBootCertificateChain _oecc116
#define Level3_GenerateCertificateKeyPair _oecc117
#define Level3_InstallOemPrivateKey _oecc118
#define Level3_ReassociateEntitledKeySession _oecc119
#define Level3_LoadCasECMKeys _oecc120
#define Level3_LoadEntitledContentKeys _oecc121 // place holder for v17.
#define Level3_ProductionReady _oecc122
#define Level3_Idle _oecc123
#define Level3_Wake _oecc124
#define Level3_BuildInformation _oecc125
#define Level3_SecurityLevel _oecc126
#define Level3_ReuseUsageEntry _oecc127
#define Level3_GetDTCP2Capability _oecc128
#define Level3_GetWatermarkingSupport _oecc129
#define Level3_GetOEMKeyToken _oecc130
#define Level3_GetDeviceInformation _oecc131
#define Level3_SetMaxAPIVersion _oecc132
#define Level3_GetKeyHandle _oecc133
#define Level3_DecryptCENC _oecc134
#define Level3_Generic_Encrypt _oecc135
#define Level3_Generic_Decrypt _oecc136
#define Level3_Generic_Sign _oecc137
#define Level3_Generic_Verify _oecc138
#define Level3_GetSignatureHashAlgorithm _oecc139
#define Level3_EnterTestMode _oecc140
#define Level3_GetDeviceSignedCsrPayload _oecc141
#define Level3_SetDecryptHash _oecc143
#define Level3_LoadLicense _oecc144
#define Level3_LoadProvisioning _oecc145
#define Level3_LoadProvisioningCast _oecc146
#define Level3_PrepAndSignReleaseRequest _oecc147
#define Level3_GetUsageEntryInfo _oecc148
#define Level3_GetBCCType _oecc149
#define Level3_LoadRelease _oecc150
// Internal-only.
#define Level3_GetEmbeddedDrmCertificate _oecc151
#define Level3_UseSecondaryKey _oecc152
#define Level3_MarkOfflineSession _oecc153
#define Level3_SetSessionUsage _oecc155
#define Level3_GetBCCSignatureType _oecc156
#define Level3_GetPVRKey _oecc157
#define Level3_LoadPVRKey _oecc158
#endif
#define Level3_GetInitializationState _oecl3o01
// clang-format on
extern "C" {
bool Level3_IsInApp();
OEMCryptoResult Level3_Initialize(void);
OEMCryptoResult Level3_Terminate(void);
OEMCryptoResult Level3_OpenSession(OEMCrypto_SESSION* session);
OEMCryptoResult Level3_CloseSession(OEMCrypto_SESSION session);
OEMCryptoResult Level3_GenerateDerivedKeys(OEMCrypto_SESSION session,
const uint8_t* mac_key_context,
size_t mac_key_context_length,
const uint8_t* enc_key_context,
size_t enc_key_context_length);
OEMCryptoResult Level3_GenerateNonce(OEMCrypto_SESSION session,
uint32_t* nonce);
OEMCryptoResult Level3_QueryKeyControl(OEMCrypto_SESSION session,
const uint8_t* key_id,
size_t key_id_length,
uint8_t* key_control_block,
size_t* key_control_block_length);
OEMCryptoResult Level3_DecryptCENC_V17(
OEMCrypto_SESSION session, const OEMCrypto_SampleDescription* samples,
size_t samples_length, const OEMCrypto_CENCEncryptPatternDesc* pattern);
OEMCryptoResult Level3_InstallKeyboxOrOEMCert(const uint8_t* rot,
size_t rotLength);
OEMCryptoResult Level3_IsKeyboxOrOEMCertValid(void);
OEMCryptoResult Level3_WrapKeyboxOrOEMCert(const uint8_t* rot, size_t rotLength,
uint8_t* wrappedRot,
size_t* wrappedRotLength,
const uint8_t* transportKey,
size_t transportKeyLength);
OEMCrypto_ProvisioningMethod Level3_GetProvisioningMethod();
OEMCryptoResult Level3_GetOEMPublicCertificate(uint8_t* public_cert,
size_t* public_cert_length);
OEMCryptoResult Level3_GetDeviceID(uint8_t* deviceID, size_t* idLength);
OEMCryptoResult Level3_GetKeyData(uint8_t* keyData, size_t* keyDataLength);
OEMCryptoResult Level3_LoadOEMPrivateKey(OEMCrypto_SESSION session);
OEMCryptoResult Level3_LoadDRMPrivateKey(OEMCrypto_SESSION session,
OEMCrypto_PrivateKeyType key_type,
const uint8_t* wrapped_rsa_key,
size_t wrapped_rsa_key_length);
OEMCryptoResult Level3_LoadProvisioning_V18(
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
size_t core_message_length, const uint8_t* signature,
size_t signature_length, uint8_t* wrapped_private_key,
size_t* wrapped_private_key_length);
OEMCryptoResult Level3_RewrapDeviceRSAKey(
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
const uint8_t* signature, size_t signature_length, const uint32_t* nonce,
const uint8_t* enc_rsa_key, size_t enc_rsa_key_length,
const uint8_t* enc_rsa_key_iv, uint8_t* wrapped_rsa_key,
size_t* wrapped_rsa_key_length);
OEMCryptoResult Level3_LoadTestRSAKey();
OEMCryptoResult Level3_GenerateRSASignature(OEMCrypto_SESSION session,
const uint8_t* message,
size_t message_length,
uint8_t* signature,
size_t* signature_length,
RSA_Padding_Scheme padding_scheme);
OEMCryptoResult Level3_DeriveKeysFromSessionKey(OEMCrypto_SESSION session,
const uint8_t* enc_session_key,
size_t enc_session_key_length,
const uint8_t* mac_key_context,
size_t mac_key_context_length,
const uint8_t* enc_key_context,
size_t enc_key_context_length);
uint32_t Level3_APIVersion();
uint32_t Level3_MinorAPIVersion();
uint8_t Level3_SecurityPatchLevel();
OEMCrypto_Security_Level Level3_SecurityLevel();
OEMCryptoResult Level3_GetHDCPCapability(OEMCrypto_HDCP_Capability* current,
OEMCrypto_HDCP_Capability* maximum);
bool Level3_SupportsUsageTable();
bool Level3_IsAntiRollbackHwPresent();
OEMCryptoResult Level3_GetNumberOfOpenSessions(size_t* count);
OEMCryptoResult Level3_GetMaxNumberOfSessions(size_t* maximum);
uint32_t Level3_SupportedCertificates();
OEMCryptoResult Level3_Generic_Encrypt_V17(
OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer);
OEMCryptoResult Level3_Generic_Decrypt_V17(
OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer);
OEMCryptoResult Level3_Generic_Sign_V17(OEMCrypto_SESSION session,
const uint8_t* in_buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
uint8_t* signature,
size_t* signature_length);
OEMCryptoResult Level3_Generic_Verify_V17(OEMCrypto_SESSION session,
const uint8_t* in_buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
const uint8_t* signature,
size_t signature_length);
OEMCryptoResult Level3_DeactivateUsageEntry(OEMCrypto_SESSION session,
const uint8_t* pst,
size_t pst_length);
OEMCryptoResult Level3_ReportUsage(OEMCrypto_SESSION session,
const uint8_t* pst, size_t pst_length,
uint8_t* buffer, size_t* buffer_length);
bool Level3_IsSRMUpdateSupported();
OEMCryptoResult Level3_GetCurrentSRMVersion(uint16_t* version);
OEMCryptoResult Level3_LoadSRM(const uint8_t* buffer, size_t buffer_length);
OEMCryptoResult Level3_RemoveSRM();
OEMCryptoResult Level3_CreateUsageTableHeader(uint8_t* header_buffer,
size_t* header_buffer_length);
OEMCryptoResult Level3_LoadUsageTableHeader(const uint8_t* buffer,
size_t buffer_length);
OEMCryptoResult Level3_CreateNewUsageEntry(OEMCrypto_SESSION session,
uint32_t* usage_entry_number);
OEMCryptoResult Level3_LoadUsageEntry(OEMCrypto_SESSION session, uint32_t index,
const uint8_t* buffer,
size_t buffer_size);
OEMCryptoResult Level3_UpdateUsageEntry(OEMCrypto_SESSION session,
uint8_t* header_buffer,
size_t* header_buffer_length,
uint8_t* entry_buffer,
size_t* entry_buffer_length);
OEMCryptoResult Level3_ShrinkUsageTableHeader(uint32_t new_table_size,
uint8_t* header_buffer,
size_t* header_buffer_length);
OEMCryptoResult Level3_MoveEntry(OEMCrypto_SESSION session, uint32_t new_index);
uint32_t Level3_GetAnalogOutputFlags();
OEMCryptoResult Level3_LoadTestKeybox(const uint8_t* buffer, size_t length);
OEMCryptoResult Level3_SelectKey(const OEMCrypto_SESSION session,
const uint8_t* key_id, size_t key_id_length,
OEMCryptoCipherMode cipher_mode);
OEMCryptoResult Level3_LoadLicense_V18(OEMCrypto_SESSION session,
const uint8_t* message,
size_t message_length,
size_t core_message_length,
const uint8_t* signature,
size_t signature_length);
OEMCryptoResult Level3_LoadKeys(
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
const uint8_t* signature, size_t signature_length,
OEMCrypto_Substring enc_mac_keys_iv, OEMCrypto_Substring enc_mac_keys,
size_t num_keys, const OEMCrypto_KeyObject* key_array,
OEMCrypto_Substring pst, OEMCrypto_Substring srm_restriction_data,
OEMCrypto_LicenseType license_type);
OEMCryptoResult Level3_SetSandbox(const uint8_t* sandbox_id,
size_t sandbox_id_length);
uint32_t Level3_ResourceRatingTier();
uint32_t Level3_SupportsDecryptHash();
OEMCryptoResult Level3_SetDecryptHash(OEMCrypto_SESSION session,
uint32_t frame_number, uint32_t crc32);
OEMCryptoResult Level3_SetDecryptHash_V18(OEMCrypto_SESSION session,
uint32_t frame_number,
const uint8_t* hash,
size_t hash_length);
OEMCryptoResult Level3_GetHashErrorCode(OEMCrypto_SESSION session,
uint32_t* failed_frame_number);
OEMCryptoResult Level3_BuildInformation(char* buffer, size_t* buffer_length);
OEMCryptoResult Level3_LoadRenewal(OEMCrypto_SESSION session,
const uint8_t* message,
size_t message_length,
size_t core_message_length,
const uint8_t* signature,
size_t signature_length);
OEMCryptoResult Level3_RefreshKeys(OEMCrypto_SESSION session,
const uint8_t* message,
size_t message_length,
const uint8_t* signature,
size_t signature_length, size_t num_keys,
const OEMCrypto_KeyRefreshObject* key_array);
OEMCryptoResult Level3_LoadEntitledContentKeys(
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array);
OEMCryptoResult Level3_CopyBuffer(
OEMCrypto_SESSION session, const uint8_t* data_addr, size_t data_length,
const OEMCrypto_DestBufferDesc* out_buffer_descriptor,
uint8_t subsample_flags);
OEMCryptoResult Level3_PrepAndSignProvisioningRequest(
OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
size_t* core_message_length, uint8_t* signature, size_t* signature_length);
OEMCryptoResult Level3_PrepAndSignLicenseRequest(
OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
size_t* core_message_length, uint8_t* signature, size_t* signature_length);
OEMCryptoResult Level3_PrepAndSignRenewalRequest(
OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
size_t* core_message_length, uint8_t* signature, size_t* signature_length);
size_t Level3_MaximumUsageTableHeaderSize();
OEMCryptoResult Level3_AllocateSecureBuffer(
OEMCrypto_SESSION session, size_t buffer_size,
OEMCrypto_DestBufferDesc* output_descriptor, int* secure_fd);
OEMCryptoResult Level3_FreeSecureBuffer(
OEMCrypto_SESSION session, OEMCrypto_DestBufferDesc* output_descriptor,
int secure_fd);
OEMCryptoResult Level3_CreateEntitledKeySession(OEMCrypto_SESSION oec_session,
OEMCrypto_SESSION* key_session);
OEMCryptoResult Level3_RemoveEntitledKeySession(OEMCrypto_SESSION key_session);
OEMCryptoResult Level3_GetBootCertificateChain(
uint8_t* bcc, size_t* bcc_size, uint8_t* additional_signature,
size_t* additional_signature_size);
OEMCryptoResult Level3_GenerateCertificateKeyPair(
OEMCrypto_SESSION session, uint8_t* public_key, size_t* public_key_size,
uint8_t* public_key_signature, size_t* public_key_signature_size,
uint8_t* wrapped_private_key, size_t* wrapped_private_key_size,
OEMCrypto_PrivateKeyType* key_type);
OEMCryptoResult Level3_InstallOemPrivateKey(OEMCrypto_SESSION session,
OEMCrypto_PrivateKeyType key_type,
const uint8_t* wrapped_private_key,
size_t wrapped_private_key_length);
OEMCryptoResult Level3_ReassociateEntitledKeySession(
OEMCrypto_SESSION key_session, OEMCrypto_SESSION oec_session);
OEMCryptoResult Level3_LoadCasECMKeys(
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
const OEMCrypto_EntitledContentKeyObject* even_key,
const OEMCrypto_EntitledContentKeyObject* odd_key);
OEMCryptoResult Level3_ProductionReady();
OEMCryptoResult Level3_Idle(OEMCrypto_IdleState state,
uint32_t os_specific_code);
OEMCryptoResult Level3_Wake();
OEMCryptoResult Level3_ReuseUsageEntry(OEMCrypto_SESSION session,
uint32_t usage_entry_number);
OEMCryptoResult Level3_GetDTCP2Capability(
OEMCrypto_DTCP2_Capability* capability);
OEMCrypto_WatermarkingSupport Level3_GetWatermarkingSupport();
OEMCryptoResult Level3_GetOEMKeyToken(OEMCrypto_SESSION key_session,
uint8_t* key_token,
size_t* key_token_length);
OEMCryptoResult Level3_SetSessionUsage(OEMCrypto_SESSION session,
uint32_t intent, uint32_t mode);
OEMCryptoResult Level3_GetPVRKey(OEMCrypto_SESSION session,
uint8_t* wrapped_pvr_key,
size_t* wrapped_pvr_key_length);
OEMCryptoResult Level3_LoadPVRKey(OEMCrypto_SESSION session,
const uint8_t* wrapped_pvr_key,
size_t wrapped_pvr_key_length);
OEMCryptoResult Level3_GetDeviceInformation(uint8_t* device_info,
size_t* device_info_length);
OEMCryptoResult Level3_GetDeviceSignedCsrPayload(
const uint8_t* challenge, size_t challenge_length,
const uint8_t* encoded_device_info, size_t encoded_device_info_length,
uint8_t* signed_csr_payload, size_t* signed_csr_payload_length);
OEMCryptoResult Level3_SetMaxAPIVersion(uint32_t max_version);
OEMCryptoResult Level3_GetKeyHandle(OEMCrypto_SESSION session,
const uint8_t* content_key_id,
size_t content_key_id_length,
OEMCryptoCipherMode cipher_mode,
uint8_t* key_handle,
size_t* key_handle_length);
OEMCryptoResult Level3_DecryptCENC(
const uint8_t* key_handle, size_t key_handle_length,
const OEMCrypto_SampleDescription* samples, size_t samples_length,
const OEMCrypto_CENCEncryptPatternDesc* pattern);
OEMCryptoResult Level3_Generic_Encrypt(const uint8_t* key_handle,
size_t key_handle_length,
const OEMCrypto_SharedMemory* in_buffer,
size_t in_buffer_length,
const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
OEMCrypto_SharedMemory* out_buffer);
OEMCryptoResult Level3_Generic_Decrypt(const uint8_t* key_handle,
size_t key_handle_length,
const OEMCrypto_SharedMemory* in_buffer,
size_t in_buffer_length,
const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
OEMCrypto_SharedMemory* out_buffer);
OEMCryptoResult Level3_Generic_Sign(const uint8_t* key_handle,
size_t key_handle_length,
const OEMCrypto_SharedMemory* buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
OEMCrypto_SharedMemory* signature,
size_t* signature_length);
OEMCryptoResult Level3_Generic_Verify(const uint8_t* key_handle,
size_t key_handle_length,
const OEMCrypto_SharedMemory* buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
const OEMCrypto_SharedMemory* signature,
size_t signature_length);
OEMCryptoResult Level3_GetSignatureHashAlgorithm(
OEMCrypto_SESSION session, OEMCrypto_SignatureHashAlgorithm* algorithm);
OEMCryptoResult Level3_EnterTestMode(void);
OEMCryptoResult Level3_LoadLicense(
OEMCrypto_SESSION session, const uint8_t* context, size_t context_length,
const uint8_t* derivation_key, size_t derivation_key_length,
const uint8_t* message, size_t message_length, size_t core_message_length,
const uint8_t* signature, size_t signature_length);
OEMCryptoResult Level3_LoadProvisioning(
OEMCrypto_SESSION session, const uint8_t* provision_request,
size_t provision_request_length, const uint8_t* message,
size_t message_length, size_t core_message_length, const uint8_t* signature,
size_t signature_length, uint8_t* wrapped_private_key,
size_t* wrapped_private_key_length);
OEMCryptoResult Level3_LoadProvisioningCast(
OEMCrypto_SESSION session, const uint8_t* derivation_key,
size_t derivation_key_length, const uint8_t* provision_request,
size_t provision_request_length, const uint8_t* message,
size_t message_length, size_t core_message_length, const uint8_t* signature,
size_t signature_length, uint8_t* wrapped_private_key,
size_t* wrapped_private_key_length);
OEMCryptoResult Level3_GetBCCType(OEMCrypto_BCCType* bcc_type);
OEMCryptoResult Level3_GetEmbeddedDrmCertificate(uint8_t* public_cert,
size_t* public_cert_length);
OEMCryptoResult Level3_UseSecondaryKey(OEMCrypto_SESSION session_id,
bool dual_key);
OEMCryptoResult Level3_MarkOfflineSession(OEMCrypto_SESSION session_id);
OEMCryptoResult Level3_GetBCCSignatureType(
OEMCrypto_BCCSignatureType* bcc_signature_type);
// The following are specific to Google's Level 3 implementation and are not
// required.
enum Level3InitializationState {
LEVEL3_INITIALIZATION_SUCCESS = 0,
LEVEL3_INITIALIZATION_UNKNOWN_FAILURE = 1,
LEVEL3_SEED_FAILURE = 2,
LEVEL3_SAVE_DEVICE_KEYS_FAILURE = 3,
LEVEL3_READ_DEVICE_KEYS_FAILURE = 4,
LEVEL3_VERIFY_DEVICE_KEYS_FAILURE = 5,
};
enum Level3RunningMode {
LEVEL3_MODE_HAYSTACK_ONLY = 0,
LEVEL3_MODE_RIKERS_DEFAULT = 1,
LEVEL3_MODE_RIKERS_ONLY = 2,
};
/*
* Level3_GetRunningMode
*
* Description:
* Returns the current mode the Level3 is running in. This shouldn't change
* while the processes is running.
*
* Parameters:
* N/A
*
* Threading:
* No other function calls will be made while this function is running.
*
* Version:
* This method is new in API version 19.
*/
Level3RunningMode Level3_GetRunningMode(void);
/*
* Level3_GetInitializationState
*
* Description:
* Return any warning or error condition which occurred during
* initialization. On some platforms, this value will be logged and metrics
* will be gathered on production devices. This is an optional feature, and
* OEMCrypto may always return 0, even if Level3_Initialize failed. This
* function may be called whether Level3_Initialize succeeded or not.
*
* Parameters:
* N/A
*
* Threading:
* No other function calls will be made while this function is running.
*
* Returns:
* LEVEL3_INITIALIZATION_SUCCESS - no warnings or errors during initialization
* LEVEL3_SEED_FAILURE - error in seeding the software RNG
* LEVEL3_SAVE_DEVICE_KEYS_FAILURE - failed to save device keys to file system
* LEVEL3_READ_DEVICE_KEYS_FAILURE - failed to read device keys from file
* system
* LEVEL3_VERIFY_DEVICE_KEYS_FAILURE - failed to verify decrypted device keys
*
* Version:
* This method is new in API version 14.
*/
Level3InitializationState Level3_GetInitializationState(void);
/*
* Level3_OutputErrorLogs
*
* Description:
* Call to output any errors in the Level 3 execution if the Level 3 has
* failed. This method should only be called if the Level 3 has failed in
* an unrecoverable state, and needs to be reinitialized.
*
* Parameters:
* N/A
*
* Threading:
* No other function calls will be made while this function is running.
*
* Returns:
* N/A
*
* Version:
* This method is new in API version 15.
*/
void Level3_OutputErrorLogs();
} // extern "C"
namespace wvoec3 {
// The following are interfaces needed for Google's Level 3 OEMCrypto
// specifically, which partners are expected to implement.
// Returns a stable, unique identifier for the device. This could be a
// serial number or any other character sequence representing that device.
// The parameter |len| needs to be changed to reflect the length of the
// unique identifier.
const char* getUniqueID(size_t* len);
// Returns a 64-bit unsigned integer to be used as a random seed for RNG.
// If the operation is unsuccessful, this function returns 0.
// We provide a sample implementation under the name generate_entropy_linux.cpp
// which partners should use if they can.
uint64_t generate_entropy();
// Creates and returns an OEMCrypto_Level3FileSystem implementation.
OEMCrypto_Level3FileSystem* createLevel3FileSystem();
// Deletes the pointer retrieved by the function above.
void deleteLevel3FileSystem(OEMCrypto_Level3FileSystem* file_system);
} // namespace wvoec3
#endif // LEVEL3_OEMCRYPTO_H_

View File

@@ -1,32 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine
// License Agreement.
/*********************************************************************
* level3_file_system.h
*
* File system for OEMCrypto Level3 file operations.
*********************************************************************/
#ifndef LEVEL3_FILE_SYSTEM_H_
#define LEVEL3_FILE_SYSTEM_H_
#include <stdlib.h>
#include "platform.h"
namespace wvoec3 {
class OEMCrypto_Level3FileSystem {
public:
virtual ~OEMCrypto_Level3FileSystem() {}
virtual ssize_t Read(const char *filename, void *buffer, size_t size) = 0;
virtual ssize_t Write(const char *filename, const void *buffer,
size_t size) = 0;
virtual bool Exists(const char *filename) = 0;
virtual ssize_t FileSize(const char *filename) = 0;
virtual bool Remove(const char *filename) = 0;
};
} // namespace wvoec3
#endif

View File

@@ -26,9 +26,9 @@ struct CoreMessageFeatures {
// This is the published version of the ODK Core Message library. The default
// behavior is for the server to restrict messages to at most this version
// number. The default is 19.5.
// number. The default is 19.6.
uint32_t maximum_major_version = 19;
uint32_t maximum_minor_version = 5;
uint32_t maximum_minor_version = 6;
bool operator==(const CoreMessageFeatures &other) const;
bool operator!=(const CoreMessageFeatures &other) const {

View File

@@ -98,6 +98,36 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
uint32_t api_major_version,
uint32_t session_id);
/*
* This function initializes the session's data structures. It shall be
* called from OEMCrypto_OpenSession.
*
* This function is an extended "Ex" version of
* ODK_InitializeSessionValues(). It is not intended for production systems;
* ODK_InitializeSessionValues() should be used instead.
*
* This function is intentionally excluded from Doxygen.
*
* @param[out] timer_limits: the session's timer limits.
* @param[out] clock_values: the session's clock values.
* @param[out] nonce_values: the session's ODK nonce values.
* @param[in] api_major_version: the API major version of OEMCrypto.
* @param[in] api_minor_version: the API minor version of OEMCrypto.
* @param[in] session_id: the session id of the newly created session.
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 19.6 of the API.
*/
OEMCryptoResult ODK_InitializeSessionValuesEx(ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
ODK_NonceValues* nonce_values,
uint32_t api_major_version,
uint32_t api_minor_version,
uint32_t session_id);
/**
* This function sets the nonce value in the session's nonce structure. It
* shall be called from OEMCrypto_GenerateNonce.

View File

@@ -16,10 +16,10 @@ extern "C" {
/* The version of this library. */
#define ODK_MAJOR_VERSION 19
#define ODK_MINOR_VERSION 5
#define ODK_MINOR_VERSION 6
/* ODK Version string. Date changed automatically on each release. */
#define ODK_RELEASE_DATE "ODK v19.5 2025-03-11"
#define ODK_RELEASE_DATE "ODK v19.6 2025-06-03"
/* The lowest version number for an ODK message. */
#define ODK_FIRST_VERSION 16

View File

@@ -89,10 +89,8 @@ bool ParseRequest(uint32_t message_type,
return true;
}
} // namespace
static bool GetNonceFromMessage(const std::string& oemcrypto_core_message,
ODK_NonceValues* nonce_values) {
bool GetNonceFromMessage(const std::string& oemcrypto_core_message,
ODK_NonceValues* nonce_values) {
if (nonce_values == nullptr) return false;
if (oemcrypto_core_message.size() < sizeof(ODK_CoreMessage)) return false;
@@ -125,6 +123,8 @@ bool CopyCounterInfo(ODK_MessageCounter* dest, ODK_MessageCounterInfo* src) {
return true;
}
} // namespace
bool CoreLicenseRequestFromMessage(const std::string& oemcrypto_core_message,
ODK_LicenseRequest* core_license_request) {
ODK_NonceValues nonce;

View File

@@ -33,7 +33,7 @@ CoreMessageFeatures CoreMessageFeatures::DefaultFeatures(
features.maximum_minor_version = 4; // 18.4
break;
case 19:
features.maximum_minor_version = 5; // 19.5
features.maximum_minor_version = 6; // 19.6
break;
default:
features.maximum_minor_version = 0;

View File

@@ -3,12 +3,16 @@
// License Agreement.
#include <stdint.h>
#include <string.h>
#include "odk.h"
#include "odk_attributes.h"
#include "odk_overflow.h"
#include "odk_structs_priv.h"
#include "odk_versions.h"
/* This is a special value used to signal that the latest API
* minor version should be used for a particular API major version. */
#define ODK_LATEST_API_MINOR_VERSION UINT32_MAX
/* Private function. Checks to see if the license is active. Returns
* ODK_TIMER_EXPIRED if the license is valid but inactive. Returns
@@ -241,6 +245,62 @@ OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
return ODK_SET_TIMER;
}
/* Private function. Initialize the timer limits to default values. */
static void InitializeTimerLimits(ODK_TimerLimits* timer_limits) {
if (timer_limits == NULL) {
return;
}
timer_limits->soft_enforce_rental_duration = false;
timer_limits->soft_enforce_playback_duration = false;
timer_limits->earliest_playback_start_seconds = 0;
timer_limits->rental_duration_seconds = 0;
timer_limits->total_playback_duration_seconds = 0;
timer_limits->initial_renewal_duration_seconds = 0;
}
/* Private function. Obtains the maximum minor version for a given major
* version. */
static uint32_t GetApiMinorVersion(uint32_t api_major_version) {
/* This needs to be updated with new major version releases. */
switch (api_major_version) {
case 16:
return ODK_V16_MINOR_VERSION;
case 17:
return ODK_V17_MINOR_VERSION;
case 18:
return ODK_V18_MINOR_VERSION;
case 19:
return ODK_V19_MINOR_VERSION;
default:
return 0;
}
}
/* Private function. Initialize the nonce values.
* Note: |api_minor_version| may be set to ODK_LATEST_API_MINOR_VERSION.*/
static void InitializeNonceValues(ODK_NonceValues* nonce_values,
uint32_t api_major_version,
uint32_t api_minor_version,
uint32_t session_id) {
if (nonce_values == NULL) {
return;
}
if (api_major_version > ODK_MAJOR_VERSION) {
api_major_version = ODK_MAJOR_VERSION;
}
/* Floor the API minor version to the maximum minor version for the API major
* version. */
const uint32_t max_api_minor_version = GetApiMinorVersion(api_major_version);
if (api_minor_version > max_api_minor_version) {
api_minor_version = max_api_minor_version;
}
nonce_values->api_major_version = api_major_version;
nonce_values->api_minor_version = api_minor_version;
nonce_values->nonce = 0;
nonce_values->session_id = session_id;
}
/************************************************************************/
/************************************************************************/
/* Public functions, declared in odk.h. */
@@ -254,38 +314,27 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
timer_limits->soft_enforce_rental_duration = false;
timer_limits->soft_enforce_playback_duration = false;
timer_limits->earliest_playback_start_seconds = 0;
timer_limits->rental_duration_seconds = 0;
timer_limits->total_playback_duration_seconds = 0;
timer_limits->initial_renewal_duration_seconds = 0;
InitializeTimerLimits(timer_limits);
ODK_InitializeClockValues(clock_values, 0);
InitializeNonceValues(nonce_values, api_major_version,
ODK_LATEST_API_MINOR_VERSION, session_id);
return OEMCrypto_SUCCESS;
}
nonce_values->api_major_version = api_major_version;
// This needs to be updated with new version releases in the default features
// of core message features.
switch (nonce_values->api_major_version) {
case 16:
nonce_values->api_minor_version = 5;
break;
case 17:
nonce_values->api_minor_version = 2;
break;
case 18:
nonce_values->api_minor_version = 4;
break;
case 19:
nonce_values->api_minor_version = 5;
break;
default:
nonce_values->api_minor_version = 0;
break;
/* This is called when certain OEMCrypto implementations opens a new session. */
OEMCryptoResult ODK_InitializeSessionValuesEx(ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
ODK_NonceValues* nonce_values,
uint32_t api_major_version,
uint32_t api_minor_version,
uint32_t session_id) {
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
nonce_values->nonce = 0;
nonce_values->session_id = session_id;
InitializeTimerLimits(timer_limits);
ODK_InitializeClockValues(clock_values, 0);
InitializeNonceValues(nonce_values, api_major_version, api_minor_version,
session_id);
return OEMCrypto_SUCCESS;
}

View File

@@ -0,0 +1,24 @@
// Copyright 2025 Google LLC. This file and proprietary
// source code may only be used and distributed under the Widevine
// License Agreement.
#ifndef WIDEVINE_ODK_SRC_ODK_VERSIONS_H_
#define WIDEVINE_ODK_SRC_ODK_VERSIONS_H_
#include <stdint.h>
#include "odk_structs.h"
/* Highest ODK minor version number by major version. */
#define ODK_V16_MINOR_VERSION 5
#define ODK_V17_MINOR_VERSION 8
#define ODK_V18_MINOR_VERSION 10
/* Whenever the next major version is released, this should be updated to the
* new major version. */
#if ODK_MAJOR_VERSION != 19
# error "ODK_MAJOR_VERSION has changed. Please update this file."
#endif
#define ODK_V19_MINOR_VERSION ODK_MINOR_VERSION
#endif // WIDEVINE_ODK_SRC_ODK_VERSIONS_H_

View File

@@ -1275,7 +1275,7 @@ std::vector<VersionParameters> TestCases() {
{16, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 16, 5},
{17, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 17, 2},
{18, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 18, 4},
{19, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 19, 5},
{19, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 19, 6},
// Here are some known good versions. Make extra sure they work.
{ODK_MAJOR_VERSION, 16, 3, 16, 3},
{ODK_MAJOR_VERSION, 16, 4, 16, 4},
@@ -1291,6 +1291,7 @@ std::vector<VersionParameters> TestCases() {
{ODK_MAJOR_VERSION, 19, 3, 19, 3},
{ODK_MAJOR_VERSION, 19, 4, 19, 4},
{ODK_MAJOR_VERSION, 19, 5, 19, 5},
{ODK_MAJOR_VERSION, 19, 6, 19, 6},
{0, 16, 3, 16, 3},
{0, 16, 4, 16, 4},
{0, 16, 5, 16, 5},
@@ -1304,6 +1305,7 @@ std::vector<VersionParameters> TestCases() {
{0, 19, 3, 19, 3},
{0, 19, 4, 19, 4},
{0, 19, 5, 19, 5},
{0, 19, 6, 19, 6},
};
return test_cases;
}

View File

@@ -34,8 +34,8 @@
// version bumps to v17.1, the first released OPK implementation would be
// v17.1.0
#define API_MAJOR_VERSION 19
#define API_MINOR_VERSION 5
#define API_MINOR_VERSION 6
#define OPK_PATCH_VERSION 0
#define OPK_BUILD_ID "19.5.0"
#define OPK_BUILD_ID "2025-06-10"
#endif /* OEMCRYPTO_TA_OEMCRYPTO_API_MACROS_H_ */

View File

@@ -7,11 +7,12 @@
#include "oemcrypto_check_macros.h"
#include "wtpi_logging_interface.h"
static void* UnsafeGetElem(OPKI_ObjectTable* table, uint32_t index) {
static void* UnsafeGetElem(const OPKI_ObjectTable* table, uint32_t index) {
return (char*)table->elems + index * table->elem_size;
}
void* OPKI_AllocFromObjectTable(OPKI_ObjectTable* table, uint32_t* index) {
void* OPKI_AllocFromObjectTable(const OPKI_ObjectTable* table,
uint32_t* index) {
if (!table) return NULL;
if (table->next_free[0] == 0) {
// This should be impossible, so this means we aren't initialized yet (since
@@ -21,16 +22,17 @@ void* OPKI_AllocFromObjectTable(OPKI_ObjectTable* table, uint32_t* index) {
}
}
const uint32_t new_index = table->first_free;
const uint32_t new_index = table->mutable_members->first_free;
if (new_index == table->capacity) return NULL;
if (index) *index = new_index;
table->first_free = table->next_free[new_index];
table->mutable_members->first_free = table->next_free[new_index];
ABORT_IF(table->is_used[new_index], "Inconsistent free list");
table->is_used[new_index] = true;
return UnsafeGetElem(table, new_index);
}
OEMCryptoResult OPKI_FreeFromObjectTable(OPKI_ObjectTable* table, void* elem) {
OEMCryptoResult OPKI_FreeFromObjectTable(const OPKI_ObjectTable* table,
void* elem) {
if (!table) return OEMCrypto_ERROR_INVALID_CONTEXT;
if (!elem) return OEMCrypto_SUCCESS;
@@ -43,7 +45,7 @@ OEMCryptoResult OPKI_FreeFromObjectTable(OPKI_ObjectTable* table, void* elem) {
return OPKI_FreeFromObjectTableByIndex(table, index);
}
OEMCryptoResult OPKI_FreeFromObjectTableByIndex(OPKI_ObjectTable* table,
OEMCryptoResult OPKI_FreeFromObjectTableByIndex(const OPKI_ObjectTable* table,
uint32_t index) {
if (!table) return OEMCrypto_ERROR_INVALID_CONTEXT;
if (index >= table->capacity) {
@@ -60,30 +62,30 @@ OEMCryptoResult OPKI_FreeFromObjectTableByIndex(OPKI_ObjectTable* table,
if (result != OEMCrypto_SUCCESS) return result;
}
table->next_free[index] = table->first_free;
table->first_free = index;
table->next_free[index] = table->mutable_members->first_free;
table->mutable_members->first_free = index;
table->is_used[index] = false;
return OEMCrypto_SUCCESS;
}
void* OPKI_GetFromObjectTable(OPKI_ObjectTable* table, uint32_t index) {
void* OPKI_GetFromObjectTable(const OPKI_ObjectTable* table, uint32_t index) {
if (!table || index >= table->capacity || !table->is_used[index]) {
return NULL;
}
return UnsafeGetElem(table, index);
}
void OPKI_UnsafeClearObjectTable(OPKI_ObjectTable* table) {
void OPKI_UnsafeClearObjectTable(const OPKI_ObjectTable* table) {
if (!table) return;
for (uint32_t i = 0; i < table->capacity; i++) {
table->next_free[i] = i + 1;
table->is_used[i] = false;
}
table->first_free = 0;
table->mutable_members->first_free = 0;
}
uint32_t OPKI_GetObjectTableUseCount(OPKI_ObjectTable* table) {
uint32_t OPKI_GetObjectTableUseCount(const OPKI_ObjectTable* table) {
if (!table) return 0;
uint32_t ret = 0;
for (uint32_t index = 0; index < table->capacity; index++) {

View File

@@ -15,15 +15,19 @@
extern "C" {
#endif
typedef struct OPKI_ObjectTableMutableMembers {
uint32_t first_free;
} OPKI_ObjectTableMutableMembers;
typedef struct OPKI_ObjectTable {
uint32_t capacity;
size_t elem_size;
uint32_t first_free;
// Note, the argument pointer can be a pointer to any type.
OEMCryptoResult (*dtor)(void*);
void* elems;
uint32_t* next_free;
bool* is_used;
OPKI_ObjectTableMutableMembers* mutable_members;
} OPKI_ObjectTable;
/**
@@ -36,14 +40,15 @@ typedef struct OPKI_ObjectTable {
/* Note these arrays are initialized to 0. */ \
static uint32_t var_name##_next_free[(max_count)]; \
static bool var_name##_is_used[(max_count)]; \
static OPKI_ObjectTable var_name = { \
static OPKI_ObjectTableMutableMembers var_name##_mutable_members; \
static const OPKI_ObjectTable var_name = { \
.capacity = (max_count), \
.elem_size = sizeof(type_name), \
.dtor = dtor_arg, \
.first_free = 0, \
.elems = var_name##_elems, \
.next_free = var_name##_next_free, \
.is_used = var_name##_is_used, \
.mutable_members = &var_name##_mutable_members, \
}
/**
@@ -51,30 +56,31 @@ typedef struct OPKI_ObjectTable {
* no more free elements. If |index| is not null, it will be filled with the
* index of the new object.
*/
void* OPKI_AllocFromObjectTable(OPKI_ObjectTable* table, uint32_t* index);
void* OPKI_AllocFromObjectTable(const OPKI_ObjectTable* table, uint32_t* index);
/**
* Frees an object and makes it available for allocation. If the table was
* given a destructor, this calls it. If the destructor fails, the object is
* still allocated in the table.
*/
OEMCryptoResult OPKI_FreeFromObjectTable(OPKI_ObjectTable* table, void* elem);
OEMCryptoResult OPKI_FreeFromObjectTable(const OPKI_ObjectTable* table,
void* elem);
/** The same as FreeFromObjectTable, but gives an index instead. */
OEMCryptoResult OPKI_FreeFromObjectTableByIndex(OPKI_ObjectTable* table,
OEMCryptoResult OPKI_FreeFromObjectTableByIndex(const OPKI_ObjectTable* table,
uint32_t index);
/** Gets the object at the given index, or NULL if not valid. */
void* OPKI_GetFromObjectTable(OPKI_ObjectTable* table, uint32_t index);
void* OPKI_GetFromObjectTable(const OPKI_ObjectTable* table, uint32_t index);
/**
* Deletes all objects from the table, allowing any to be used again. This
* does NOT invoke destructors
*/
void OPKI_UnsafeClearObjectTable(OPKI_ObjectTable* table);
void OPKI_UnsafeClearObjectTable(const OPKI_ObjectTable* table);
/** Gets the number of objects used from the given table. */
uint32_t OPKI_GetObjectTableUseCount(OPKI_ObjectTable* table);
uint32_t OPKI_GetObjectTableUseCount(const OPKI_ObjectTable* table);
#ifdef __cplusplus
} // extern "C"

View File

@@ -1426,7 +1426,7 @@ OEMCryptoResult OPKI_ShrinkUsageTableHeader(uint32_t new_entry_count,
LOGE("Usage table not initialized");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (new_entry_count >= g_usage_table.table_size) {
if (new_entry_count > g_usage_table.table_size) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
for (size_t i = new_entry_count; i < g_usage_table.table_size; i++) {

View File

@@ -3,36 +3,33 @@
Some of the headers in wtpi/ directory are tested by the code in wtpi_test/.
wtpi_test uses serialization/generator/scrape_interface.py to parse the WTPI
interface declarations and generate serialization APIs such as:
* OPK_Pack_SaveGenerationNumber_Request(),
* OPK_Unpack_K1_DeriveKeyFromKeyHandle_Response(),
* `OPK_Pack_SaveGenerationNumber_Request()`
* `OPK_Unpack_K1_DeriveKeyFromKeyHandle_Response()`
* ...
In order for the types of the parameters of these WTPI interfaces to be
correctly determined and inserted into the auto-generated
OPK_Pack_* / OPK_Unpack_* functions, certain naming conventions have to be
followed:
* To pack a variable length buffer X with type uint8_t*, the size of the
array must be named as "X_length" or XLength".
* If an output variable length buffer doesn't have an output size specified in
the parameter list, and is supposed to have the same size as the input buffer,
then the output buffer must be named as "out_buffer".
Below is an example following the naming convention above:
```
OEMCryptoResult WTPI_C1_SHA256(const uint8_t* input, size_t input_length,
uint8_t* out_buffer);
```
You can find more details in scrape_interface.py for what is looked for by the
parser.
OPK_Pack_* / OPK_Unpack_* functions,
[certain naming conventions][naming-conventions] have to be followed.
WTPI interfaces that are currently covered by wtpi_test:
* wtpi_generation_number_interface.h,
* wtpi_crypto_and_key_management_interface_layer1.h,
* wtpi_crypto_asymmetric_interface.h,
* wtpi_crc32_interface.h,
* wtpi_provisioning_4_interface.h,
* wtpi_generation_number_interface.h
* wtpi_crypto_and_key_management_interface_layer1.h
* wtpi_crypto_asymmetric_interface.h
* wtpi_provisioning_4_interface.h
* wtpi_crc32_interface.h
* wtpi_clock_interface_layer1.h
* wtpi_config_interface.h
* wtpi_device_key_interface.h
However, all WTPI interface may potentially be covered someday, so it's best
practice to always follow [the naming conventions][naming-conventions].
Please be cautious when updating parameter names in these interfaces. It can
potentially break the auto-generated serialization functions used by the WTPI
tests if the naming convention is not enforced.
tests if the naming conventions are not enforced. It can also cause the
generator to generate invalid or insecure code.
[naming-conventions]: https://g3doc.corp.google.com/video/widevine/g3doc/devices/oec_function_conventions.md

View File

@@ -13,6 +13,7 @@
#include "dice/cbor_writer.h"
#include "dice/config.h"
#include "dice/dice.h"
#include "oemcrypto_api_macros.h"
#include "oemcrypto_check_macros.h"
#include "wtpi_crypto_and_key_management_interface_layer1.h"
#include "wtpi_crypto_asymmetric_interface.h"
@@ -217,20 +218,23 @@ static DiceResult EncodeConfigurationDescriptor(size_t buffer_size,
CborOutInit(buffer, buffer_size, &out);
CborWriteMap(/*num_pairs=*/2, &out);
char str_buf[32] = {0};
// Add component name.
CborWriteInt(kComponentNameLabel, &out);
if (is_leaf) {
// The leaf certificate's component name must contain "Widevine".
CborWriteTstr("Widevine", &out);
} else {
char buf[32] = {0};
snprintf(buf, sizeof(buf), "Component %u", entry_index);
CborWriteTstr(buf, &out);
snprintf(str_buf, sizeof(str_buf), "Component %u", entry_index);
CborWriteTstr(str_buf, &out);
memset(str_buf, 0, sizeof(str_buf));
}
// Add component version.
CborWriteInt(kComponentVersionLabel, &out);
CborWriteTstr("19", &out);
snprintf(str_buf, sizeof(str_buf), "%d", API_MAJOR_VERSION);
CborWriteTstr(str_buf, &out);
memset(str_buf, 0, sizeof(str_buf));
if (CborOutOverflowed(&out)) {
return kDiceResultBufferTooSmall;
@@ -423,7 +427,13 @@ static OEMCryptoResult GenerateEncodedBccPayload(
// Add the profile name.
CborWriteInt(kProfileNameLabel, &cbor_out);
CborWriteTstr("android.15", &cbor_out);
if (is_leaf) {
snprintf(str_buf, sizeof(str_buf), "widevine.%d", API_MAJOR_VERSION);
CborWriteTstr(str_buf, &cbor_out);
memset(str_buf, 0, sizeof(str_buf));
} else {
CborWriteTstr("android.15", &cbor_out);
}
// Add the subject public key.
CborWriteInt(kSubjectPublicKeyLabel, &cbor_out);

View File

@@ -87,6 +87,7 @@ void print_cbor(cn_cbor* cn, uint32_t type) {
}
namespace wtpi_test {
namespace {
// Copied and modified from open-dice test_utils.cc
ScopedCbor ExtractCwtFromCborCertificate(const uint8_t* certificate,
size_t certificate_size) {
@@ -157,6 +158,7 @@ ScopedCbor ExtractPublicKeyFromCwt(const cn_cbor* cwt) {
}
return key;
}
} // namespace
ScopedCbor ExtractPublicKeyFromBcc(const uint8_t* bytes, size_t bytes_len) {
// Get bcc payload, which is a CBOR Web Token.

View File

@@ -16,6 +16,8 @@
#include "wtpi_device_key_interface.h"
#define UUID_LENGTH 16
namespace {
// This struct represents a wrapped blob that we do not yet know how to
// interpret. It contains only the fields that we expect every versioned blob to
// have.
@@ -27,11 +29,11 @@ typedef struct WrappedData {
} WrappedData;
// The randomly-generated UUID that identifies a blob as a WrappedData struct,
// in network byte order.
static const uint8_t kMagicUuid[UUID_LENGTH] = {
0xb5, 0x76, 0x3b, 0xad, 0x84, 0x05, 0x40, 0xfd,
0xa0, 0x88, 0x3b, 0x6c, 0x69, 0x97, 0xfc, 0x74};
const uint8_t kMagicUuid[UUID_LENGTH] = {0xb5, 0x76, 0x3b, 0xad, 0x84, 0x05,
0x40, 0xfd, 0xa0, 0x88, 0x3b, 0x6c,
0x69, 0x97, 0xfc, 0x74};
// 1 in network byte order
static const uint8_t kVersionOne[sizeof(uint32_t)] = {0x00, 0x00, 0x00, 0x01};
const uint8_t kVersionOne[sizeof(uint32_t)] = {0x00, 0x00, 0x00, 0x01};
// This is the layout of the |data| field of a WrappedData structure when its
// |version| field is 1.
typedef struct WrappedData_V1 {
@@ -39,15 +41,15 @@ typedef struct WrappedData_V1 {
uint8_t enc_data[];
} WrappedData_V1;
static OEMCryptoResult GetEncryptAndSignSize(uint32_t context, size_t in_size,
size_t* wrapped_size) {
OEMCryptoResult GetEncryptAndSignSize(uint32_t context, size_t in_size,
size_t* wrapped_size) {
*wrapped_size = in_size + sizeof(WrappedData) + sizeof(WrappedData_V1);
return OEMCrypto_SUCCESS;
}
OEMCryptoResult EncryptAndSign_V1(uint32_t context, const uint8_t* data,
size_t data_size, uint8_t* out,
size_t* out_size) {
size_t data_size, uint8_t* out,
size_t* out_size) {
if (!out_size) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
@@ -91,6 +93,7 @@ OEMCryptoResult EncryptAndSign_V1(uint32_t context, const uint8_t* data,
WTPI_K1_FreeKeyHandle(signing_key);
return result;
}
} // namespace
class LegacyKeywrapTest : public ::testing::Test {
protected:

View File

@@ -7,6 +7,7 @@
#include "log.h"
namespace {
void dump_ssl_error(void) {
int count = 0;
unsigned long err;
@@ -17,6 +18,7 @@ void dump_ssl_error(void) {
LOGE("SSL Error %d -- %lu -- %s", count, err, buffer);
}
}
} // namespace
bool DeserializePKCS8PrivateKey(const uint8_t* serialized_bytes, size_t size,
RSA** rsa) {

View File

@@ -12,7 +12,10 @@
* This is a PKCS8 RSA key encoded in DER format.
*/
#include "stdint.h"
#include "test_common.h"
#include <stdint.h>
uint8_t test_rsa_key_der[] = {
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,

View File

@@ -55,7 +55,16 @@ cflags += \
-DWTPI_BUILD_INFO=\"$(WTPI_BUILD_INFO)\" \
-DSUPPORT_CAS \
-DWV_POSIX_RESOURCE_ID=\"$(project)\" \
-D_DEFAULT_SOURCE
-DOPK_CONFIG_SOC_VENDOR_NAME=$(SOC_VENDOR) \
-DOPK_CONFIG_SOC_MODEL_NAME=$(SOC_MODEL) \
-DOPK_CONFIG_TEE_OS_NAME=$(TEE_OS) \
-DOPK_CONFIG_TEE_OS_VERSION=$(TEE_VERSION) \
-DOPK_CONFIG_DEVICE_FORM_FACTOR=$(DEVICE_FORM_FACTOR) \
-DOPK_CONFIG_IMPLEMENTER_NAME=$(IMPLEMENTER) \
-DOPK_CONFIG_PROVISIONING_METHOD=$(PROVISIONING_METHOD) \
-D_DEFAULT_SOURCE \
-fstack-protector-strong \
-D_DEBUG
ldflags = \
-lrt -lpthread \

View File

@@ -9,7 +9,7 @@
#include <stddef.h>
#include <stdint.h>
#include "OEMCryptoCENC.h"
#include "wtpi_config_macros.h"
#include "opk_config.h"
#include "wtpi_crypto_and_key_management_interface_layer1.h"
#ifdef __cplusplus

View File

@@ -9,6 +9,8 @@
// posix_services.h implementation of semaphores and shared memory
// which is based on the POSIX shared memory and semaphore libraries.
#include "tos_transport.h"
#include "odk_message.h"
#include "posix_resources.h"
#include "tos_transport_interface.h"
@@ -20,19 +22,20 @@
using namespace posix;
namespace {
// message request/response payload data
static RequestResponseBlock* shared_memory_ = nullptr;
RequestResponseBlock* shared_memory_ = nullptr;
// mailbox containing the size of the payload
static MailboxBlock* mailbox_memory_ = nullptr;
MailboxBlock* mailbox_memory_ = nullptr;
// post when a request message is ready
static RequestSemaphore* request_semaphore_ = nullptr;
RequestSemaphore* request_semaphore_ = nullptr;
// post when a response message is ready
static ResponseSemaphore* response_semaphore_ = nullptr;
ResponseSemaphore* response_semaphore_ = nullptr;
static void ReleaseResources() {
void ReleaseResources() {
if (shared_memory_) {
delete shared_memory_;
shared_memory_ = nullptr;
@@ -51,6 +54,25 @@ static void ReleaseResources() {
}
}
// Get the size of the message from the mailbox and return it
uint32_t PeekSize(void) {
uint8_t* mailbox = mailbox_memory_->GetAddress();
uint32_t message_size = (uint32_t)mailbox[0] | (uint32_t)mailbox[1] << 8 |
(uint32_t)mailbox[2] << 16 |
(uint32_t)mailbox[3] << 24;
return message_size;
}
// Put the size of the message into the mailbox
void PokeSize(uint32_t size) {
uint8_t* mailbox = mailbox_memory_->GetAddress();
mailbox[0] = (uint8_t)(size);
mailbox[1] = (uint8_t)(size >> 8);
mailbox[2] = (uint8_t)(size >> 16);
mailbox[3] = (uint8_t)(size >> 24);
}
} // namespace
bool TOS_Transport_Initialize(void) {
if (!(shared_memory_ = new RequestResponseBlock()) ||
!(shared_memory_->Allocate(OPK_TRANSPORT_MESSAGE_SIZE))) {
@@ -94,24 +116,6 @@ void TOS_Transport_ReleaseMessage(ODK_Message* message) {
(void)message;
}
// Get the size of the message from the mailbox and return it
static uint32_t PeekSize(void) {
uint8_t* mailbox = mailbox_memory_->GetAddress();
uint32_t message_size = (uint32_t)mailbox[0] | (uint32_t)mailbox[1] << 8 |
(uint32_t)mailbox[2] << 16 |
(uint32_t)mailbox[3] << 24;
return message_size;
}
// Put the size of the message into the mailbox
static void PokeSize(uint32_t size) {
uint8_t* mailbox = mailbox_memory_->GetAddress();
mailbox[0] = (uint8_t)(size);
mailbox[1] = (uint8_t)(size >> 8);
mailbox[2] = (uint8_t)(size >> 16);
mailbox[3] = (uint8_t)(size >> 24);
}
// The request has been packed into the shared memory, all we need to
// do is poke the message size in the mailbox and post on the request
// semaphore, then wait for the response semaphore. The response will

View File

@@ -52,6 +52,7 @@ cflags_c += \
cppflags += \
$(cflags) \
-std=c++17 \
$(CPPFLAGS)
# Filter out files and directories in third_party.
@@ -105,7 +106,9 @@ define clang-tidy-rule
.PHONY: clang-tidy-$(1)
clang-tidy-$(1):
@$(cmd-echo-silent) ' CLANG-TIDY $(1)'
${q}clang-tidy $(clang-tidy-flags) $(1) -- $(cflags)
${q}clang-tidy $(clang-tidy-flags) $(1) -- $(cflags) \
$(if $(filter .c,$(suffix $(1))),-std=c11 -D_POSIX_C_SOURCE=200809L) \
$(if $(filter .cpp,$(suffix $(1))),-std=c++17)
endef
define clang-tidy-rule-cpp

View File

@@ -8,7 +8,7 @@
#define OPK_CONFIG_H_
#ifndef OPK_CONFIG_SECURITY_LEVEL
# define OPK_CONFIG_SECURITY_LEVEL OEMCrypto_Level3
# define OPK_CONFIG_SECURITY_LEVEL OEMCrypto_Level1
#endif
#ifndef OPK_CONFIG_RESOURCE_RATING_TIER

View File

@@ -19,6 +19,7 @@
static pthread_t main_thread_tid;
static bool thread_running = false;
namespace {
void signalHandler(int signum) {
(void)signum;
// TODO(fredgc): this doesn't actually kill anything because the main loop is
@@ -27,6 +28,7 @@ void signalHandler(int signum) {
// This exits, but then we skip the OPK_Terminate call.
exit(0);
}
} // namespace
// The request message data must be copied into a local buffer
// so the contents can't be modified while being parsed.

View File

@@ -9,7 +9,9 @@
#include "oemcrypto_corpus_generator_helper.h"
#include "test_sleep.h"
static void acknowledge_cast() {
namespace {
void acknowledge_cast() {
std::cout
<< "==================================================================\n"
<< "= This device is expected to load x509 certs as a cast receiver. =\n"
@@ -38,6 +40,8 @@ int CheckAndInstallProv30ROT() {
return 0;
}
} // namespace
// This special main procedure is used instead of the standard GTest main,
// because we need to initialize the list of features supported by the device.
// Also, the test filter is updated based on the feature list.

View File

@@ -106,7 +106,9 @@ define clang-tidy-rule
.PHONY: clang-tidy-$(1)
clang-tidy-$(1):
@$(cmd-echo-silent) ' CLANG-TIDY $(1)'
${q}clang-tidy $(clang-tidy-flags) $(1) -- $(cflags)
${q}clang-tidy $(clang-tidy-flags) $(1) -- $(cflags) \
$(if $(filter .c,$(suffix $(1))),-std=c11 -D_POSIX_C_SOURCE=200809L) \
$(if $(filter .cpp,$(suffix $(1))),-std=c++17)
endef
define clang-tidy-rule-cpp

View File

@@ -28,6 +28,8 @@ clang-tidy-flags = \
clang-tidy-cflags = \
-m$(ARCH) \
$(if $(filter .c,$(suffix $(1))),-std=c11 -D_POSIX_C_SOURCE=200809L) \
$(if $(filter .cpp,$(suffix $(1))),-std=c++17) \
$(comp-cppflags-$(call oname,$(1)))
# Define a rule template to run clang-tidy with a single source file.

View File

@@ -26,6 +26,8 @@ clang-tidy-flags := \
clang-tidy-cflags := \
$(MODULE_CFLAGS) \
$(if $(filter .c,$(suffix $(1))),-std=c11 -D_POSIX_C_SOURCE=200809L) \
$(if $(filter .cpp,$(suffix $(1))),-std=c++17) \
$(addprefix -D,$(MODULE_DEFINES) TRUSTY_USERSPACE) \
$(addprefix -I,\
$(MODULE_INCLUDES) \
@@ -37,7 +39,7 @@ clang-tidy-cflags := \
define clang-tidy-rule
.PHONY: clang-tidy-$(1)
clang-tidy-$(1): clang-tidy-flags := $(clang-tidy-flags)
clang-tidy-$(1): clang-tidy-cflags := $(clang-tidy-cflags)
clang-tidy-$(1): clang-tidy-cflags := $(call clang-tidy-cflags,$(1))
clang-tidy-$(1):
@echo running clang-tidy: $(1)
$(NOECHO)clang-tidy $(clang-tidy-flags) $(1) -- $(clang-tidy-cflags)

View File

@@ -0,0 +1,75 @@
# Copyright (C) 2024 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
MODULE := $(LOCAL_DIR)
WV_TA_TOP_LEVEL := $(LOCAL_DIR)/../../../../
SHARED_DIR := $(WV_TA_TOP_LEVEL)/shared
IMPL_DIR := $(WV_TA_TOP_LEVEL)/interface_impls
CDM_DIR := trusty/vendor/widevine/cdm
APP_DIR := $(CDM_DIR)/oemcrypto/opk/oemcrypto_ta
SERIALIZATION_DIR := $(CDM_DIR)/oemcrypto/opk/serialization
ODK_DIR := $(CDM_DIR)/oemcrypto/odk
ifndef WIDEVINE_PROVISION_METHOD
$(error WIDEVINE_PROVISION_METHOD is not set. \
Please set it in the [target_name]-inc.mk file of your project)
endif
MODULE_DEFINES += \
WIDEVINE_PROVISION_METHOD=$(WIDEVINE_PROVISION_METHOD) \
# Default value if WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE is not set by *-inc.mk.
WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE ?= 0
MODULE_DEFINES += \
WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE=$(WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE)
MODULE_DEFINES += \
OPK_CONFIG_SOC_VENDOR_NAME=Google \
OPK_CONFIG_SOC_MODEL_NAME=$(PLATFORM) \
OPK_CONFIG_TEE_OS_NAME=Trusty \
OPK_CONFIG_TEE_OS_VERSION=0.0 \
OPK_CONFIG_DEVICE_FORM_FACTOR=phone+tablet \
OPK_CONFIG_IMPLEMENTER_NAME=Widevine \
WTPI_BUILD_INFO=TRUSTY \
# Widevine vendor code assumes trusty defines __linux__. We need to get this
# fixed upstream. TODO(b/232255239)
MODULE_CFLAGS += -D__linux__
MODULE_SRCS += \
$(APP_DIR)/wtpi_reference/wtpi_decrypt_sample.c \
MODULE_INCLUDES += \
$(LOCAL_DIR)/include \
$(SHARED_DIR)/include \
MODULE_INCLUDES += \
$(CDM_DIR)/oemcrypto/include \
$(ODK_DIR)/include \
$(CDM_DIR)/oemcrypto/odk/src \
$(IMPL_DIR) \
$(APP_DIR) \
$(WV_TA_TOP_LEVEL)/include \
$(APP_DIR)/wtpi \
$(APP_DIR)/wtpi_reference \
MODULE_LIBRARY_DEPS += \
trusty/user/base/lib/libc-trusty \
include make/library.mk

View File

@@ -0,0 +1,71 @@
# Copyright (C) 2024 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
MODULE := $(LOCAL_DIR)
TOP_LEVEL := $(LOCAL_DIR)/../../../../
SHARED_DIR := $(TOP_LEVEL)/shared
IMPL_DIR := $(TOP_LEVEL)/interface_impls
CDM_DIR := trusty/vendor/widevine/cdm
APP_DIR := $(CDM_DIR)/oemcrypto/opk/oemcrypto_ta
SERIALIZATION_DIR := $(CDM_DIR)/oemcrypto/opk/serialization
ODK_DIR := $(CDM_DIR)/oemcrypto/odk
ifndef WIDEVINE_PROVISION_METHOD
$(error WIDEVINE_PROVISION_METHOD is not set. \
Please set it in the [target_name]-inc.mk file of your project)
endif
MODULE_DEFINES += \
WIDEVINE_PROVISION_METHOD=$(WIDEVINE_PROVISION_METHOD) \
# Default value if WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE is not set by *-inc.mk.
WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE ?= 0
MODULE_DEFINES += \
WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE=$(WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE)
MODULE_DEFINES += \
OPK_CONFIG_SOC_VENDOR_NAME=Google \
OPK_CONFIG_SOC_MODEL_NAME=$(PLATFORM) \
OPK_CONFIG_TEE_OS_NAME=Trusty \
OPK_CONFIG_TEE_OS_VERSION=0.0 \
OPK_CONFIG_DEVICE_FORM_FACTOR=phone+tablet \
OPK_CONFIG_IMPLEMENTER_NAME=Widevine \
WTPI_BUILD_INFO=TRUSTY \
MODULE_SRCS += \
$(IMPL_DIR)/derive_key.c \
MODULE_INCLUDES += \
$(LOCAL_DIR)/include \
$(SHARED_DIR)/include \
MODULE_INCLUDES += \
$(CDM_DIR)/oemcrypto/include \
$(ODK_DIR)/include \
$(CDM_DIR)/oemcrypto/odk/src \
$(IMPL_DIR) \
$(APP_DIR) \
$(TOP_LEVEL)/include \
$(APP_DIR)/wtpi \
$(APP_DIR)/wtpi_reference \
MODULE_LIBRARY_DEPS += \
trusty/user/base/lib/hwkey \
include make/library.mk

View File

@@ -0,0 +1,95 @@
# Copyright (C) 2024 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
MODULE := $(LOCAL_DIR)
WV_TA_TOP_LEVEL := $(LOCAL_DIR)/../../../../
SHARED_DIR := $(WV_TA_TOP_LEVEL)/shared
IMPL_DIR := $(WV_TA_TOP_LEVEL)/interface_impls
CDM_DIR := trusty/vendor/widevine/cdm
APP_DIR := $(CDM_DIR)/oemcrypto/opk/oemcrypto_ta
SERIALIZATION_DIR := $(CDM_DIR)/oemcrypto/opk/serialization
ODK_DIR := $(CDM_DIR)/oemcrypto/odk
ifndef WIDEVINE_PROVISION_METHOD
$(error WIDEVINE_PROVISION_METHOD is not set. \
Please set it in the [target_name]-inc.mk file of your project)
endif
# oemcrypto.h will declare constants as C++-style statics.
# C sources do not like this, so change the behavior.
MODULE_CFLAGS += -DNO_OEMCRYPTO_VARIABLE_DEFINITIONS
# Ensure API entry points are renamed in a predictable manner.
# TODO: can we remove this?
MODULE_CFLAGS += -DOEMCRYPTO_TA_TEST_ONLY
# TODO: remove when the prototypes in oemcrypto.h are strict.
MODULE_CFLAGS += -Wno-strict-prototypes
# TODO: remove when unused variable in dump_ssl_error() is fixed
MODULE_CFLAGS += -Wno-error=unused-but-set-variable
MODULE_DEFINES += \
WIDEVINE_PROVISION_METHOD=$(WIDEVINE_PROVISION_METHOD) \
# Default value if WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE is not set by *-inc.mk.
WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE ?= 0
MODULE_DEFINES += \
WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE=$(WIDEVINE_PROVISION_BCC_SIGNATURE_TYPE)
MODULE_DEFINES += \
OPK_CONFIG_SOC_VENDOR_NAME=Google \
OPK_CONFIG_SOC_MODEL_NAME=$(PLATFORM) \
OPK_CONFIG_TEE_OS_NAME=Trusty \
OPK_CONFIG_TEE_OS_VERSION=0.0 \
OPK_CONFIG_DEVICE_FORM_FACTOR=phone+tablet \
OPK_CONFIG_IMPLEMENTER_NAME=Widevine \
WTPI_BUILD_INFO=TRUSTY \
# Widevine vendor code assumes trusty defines __linux__. We need to get this
# fixed upstream. TODO(b/232255239)
MODULE_CFLAGS += -D__linux__
# The base Trusty app.
MODULE_SRCS += \
$(IMPL_DIR)/wtpi_persistent_storage_layer1.c \
$(IMPL_DIR)/wtpi_initialize_terminate.c \
$(IMPL_DIR)/wtpi_root_of_trust_layer2.c \
$(WV_TA_TOP_LEVEL)/tee_context.c \
MODULE_INCLUDES += \
$(WV_TA_TOP_LEVEL)/include \
$(CDM_DIR)/oemcrypto/include \
$(ODK_DIR)/include \
$(SERIALIZATION_DIR)/common \
$(SERIALIZATION_DIR)/common/include \
$(CDM_DIR)/oemcrypto/odk/src \
$(SERIALIZATION_DIR)/os_interfaces \
$(IMPL_DIR) \
MODULE_INCLUDES += \
$(APP_DIR) \
$(APP_DIR)/wtpi \
$(APP_DIR)/wtpi_reference \
MODULE_LIBRARY_DEPS += \
trusty/user/base/lib/libc-trusty \
trusty/user/base/lib/storage \
include make/library.mk

View File

@@ -52,6 +52,6 @@ UBSAN_IGNORE_UNSIGNED_OVERFLOW void* OPK_BumpAllocate(size_t nbytes) {
void OPK_BumpAllocator_Reset(void) {
LOGV("bump allocator capacity = %d", BUFFER_SIZE);
memset(buffer, 0, BUFFER_SIZE);
memset(buffer, 0, buffer_offset);
buffer_offset = 0;
}

View File

@@ -122,7 +122,7 @@ void OPK_SharedBuffer_Terminate(void) {
* allocated.
*/
void OPK_SharedBuffer_Reset(void) {
memset(&allocations_[0], 0, sizeof(allocations_));
memset(&allocations_[0], 0, buffer_count_ * sizeof(allocations_[0]));
next_buffer_offset_ = 0;
next_buffer_index_ = 0;
buffer_count_ = 0;

View File

@@ -1,27 +0,0 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/util/include \
LOCAL_MODULE:=oemcrypto_test
LOCAL_LICENSE_KINDS:=legacy_by_exception_only legacy_proprietary
LOCAL_LICENSE_CONDITIONS:=by_exception_only proprietary by_exception_only
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE_OWNER := widevine
LOCAL_PROPRIETARY_MODULE := true
LOCAL_C_INCLUDES += external/googletest/googlemock/include \
# When built, explicitly put it in the DATA/nativetest directory.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
LOCAL_MODULE_TARGET_ARCH := arm x86 mips
endif
include $(LOCAL_PATH)/common.mk
include $(BUILD_EXECUTABLE)

View File

@@ -450,3 +450,11 @@ OEMCryptoResult _oecc157(OEMCrypto_SESSION session, uint8_t* wrapped_pvr_key,
OEMCryptoResult _oecc158(OEMCrypto_SESSION session,
const uint8_t* wrapped_pvr_key,
size_t wrapped_pvr_key_length);
// OEMCrypto_LoadLicenseData defined in v19.6
OEMCryptoResult _oecc159(OEMCrypto_SESSION session, const uint8_t* data,
size_t data_length);
// OEMCrypto_SaveLicenseData defined in v19.6
OEMCryptoResult _oecc160(OEMCrypto_SESSION session, uint8_t* data,
size_t* data_length);

View File

@@ -1,76 +0,0 @@
LOCAL_PATH:= $(call my-dir)
ifeq ($(filter mips mips64, $(TARGET_ARCH)),)
# Tests need to be compatible with devices that do not support gnu hash-style
LOCAL_LDFLAGS+=-Wl,--hash-style=both
endif
# The unit tests can access v15 functions through the dynamic adapter:
LOCAL_CFLAGS += -DTEST_OEMCRYPTO_V15
LOCAL_SRC_FILES:= \
GEN_api_lock_file.c \
oec_device_features.cpp \
oec_decrypt_fallback_chain.cpp \
oec_key_deriver.cpp \
oec_session_util.cpp \
oemcrypto_corpus_generator_helper.cpp \
oemcrypto_session_tests_helper.cpp \
oemcrypto_basic_test.cpp \
oemcrypto_cast_test.cpp \
oemcrypto_decrypt_test.cpp \
oemcrypto_generic_crypto_test.cpp \
oemcrypto_license_test.cpp \
oemcrypto_provisioning_test.cpp \
oemcrypto_security_test.cpp \
oemcrypto_usage_table_test.cpp \
oemcrypto_test.cpp \
oemcrypto_test_android.cpp \
oemcrypto_test_main.cpp \
ota_keybox_test.cpp \
../../cdm/util/test/test_sleep.cpp \
../util/src/bcc_validator.cpp \
../util/src/cbor_validator.cpp \
../util/src/device_info_validator.cpp \
../util/src/oemcrypto_ecc_key.cpp \
../util/src/oemcrypto_rsa_key.cpp \
../util/src/prov4_validation_helper.cpp \
../util/src/signed_csr_payload_validator.cpp \
../util/src/wvcrc.cpp \
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/fuzz_tests \
$(LOCAL_PATH)/../include \
$(LOCAL_PATH)/../odk/include \
$(LOCAL_PATH)/../odk/kdo/include \
$(LOCAL_PATH)/../ref/src \
$(LOCAL_PATH)/../util/include \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/cdm/util/test \
LOCAL_STATIC_LIBRARIES := \
libcdm \
libcppbor \
libjsmn \
libgmock \
libgtest \
libgtest_main \
libwvlevel3 \
libcdm_protos \
libcdm_utils \
libwv_kdo \
libwv_odk \
libPlatformProperties \
LOCAL_SHARED_LIBRARIES := \
libbase \
libcrypto \
libdl \
libbinder_ndk \
liblog \
libmedia_omx \
libprotobuf-cpp-lite \
libstagefright_foundation \
libutils \
libz \

View File

@@ -7,13 +7,13 @@ namespace {
void OpenOEMCryptoTASession() {
uint8_t request_body[] = {
0x06, // TAG_UINT32
0x07, // TAG_UINT32
0x09, 0x00, 0x00, 0x00, // API value (0x09)
0x07, // TAG_UINT64
0x08, // TAG_UINT64
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp
0x01, // TAG_BOOL
0x00, // value (false)
0x0a // TAG_EOM
0x0b // TAG_EOM
};
ODK_Message request = ODK_Message_Create(request_body, sizeof(request_body));
ODK_Message_SetSize(&request, sizeof(request_body));
@@ -23,11 +23,11 @@ void OpenOEMCryptoTASession() {
void InitializeOEMCryptoTA() {
uint8_t request_body[] = {
0x06, // TAG_UINT32
0x07, // TAG_UINT32
0x01, 0x00, 0x00, 0x00, // API value (0x01)
0x07, // TAG_UINT64
0x08, // TAG_UINT64
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp
0x0a // TAG_EOM
0x0b // TAG_EOM
};
ODK_Message request = ODK_Message_Create(request_body, sizeof(request_body));
ODK_Message_SetSize(&request, sizeof(request_body));

View File

@@ -42,12 +42,8 @@
{
'target_name': 'oemcrypto_opk_dispatcher_fuzz',
'include_dirs': [
'<(oemcrypto_dir)/opk/serialization/common',
'<(oemcrypto_dir)/opk/serialization/common/include',
'<(oemcrypto_dir)/opk/serialization/os_interfaces',
'<(oemcrypto_dir)/opk/serialization/tee',
'<(oemcrypto_dir)/opk/serialization/tee/include',
'<(oemcrypto_dir)/opk/ports/trusty/include/',
],
'dependencies': [
'<(oemcrypto_dir)/opk/serialization/tee/tee.gyp:opk_tee',
@@ -55,9 +51,9 @@
'sources': [
'oemcrypto_opk_dispatcher_fuzz.cc',
'<(oemcrypto_dir)/opk/serialization/test/tos_secure_buffers.c',
'<(oemcrypto_dir)/opk/serialization/test/tos_transport_interface.c',
'<(oemcrypto_dir)/opk/serialization/test/tos_logging.c',
'<(oemcrypto_dir)/opk/ports/trusty/serialization_adapter/shared_memory.c',
'<(oemcrypto_dir)/opk/serialization/test/tos_shared_memory.c',
'<(oemcrypto_dir)/opk/serialization/test/tos_transport_interface.c',
],
},
{

View File

@@ -1796,7 +1796,11 @@ void Session::close() {
void Session::GenerateNonce(int* error_counter) {
// We make one attempt. If it fails, we assume there was a nonce flood.
if (OEMCrypto_SUCCESS == OEMCrypto_GenerateNonce(session_id(), &nonce_)) {
// Using |temp_nonce| to avoid member |nonce_| being modified
// during failure.
uint32_t temp_nonce = 0;
if (OEMCrypto_SUCCESS == OEMCrypto_GenerateNonce(session_id(), &temp_nonce)) {
nonce_ = temp_nonce;
return;
}
if (error_counter) {
@@ -1806,7 +1810,8 @@ void Session::GenerateNonce(int* error_counter) {
// The following is after a 1 second pause, so it cannot be from a nonce
// flood.
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_GenerateNonce(session_id(), &nonce_));
OEMCrypto_GenerateNonce(session_id(), &temp_nonce));
nonce_ = temp_nonce;
}
}

View File

@@ -317,14 +317,14 @@ TEST_F(OEMCryptoClientTest, FreeUnallocatedSecureBufferNoFailure) {
*/
TEST_F(OEMCryptoClientTest, VersionNumber) {
const std::string log_message =
"OEMCrypto unit tests for API 19.5. Tests last updated 2025-03-11";
"OEMCrypto unit tests for API 19.6. Tests last updated 2025-06-03";
cout << " " << log_message << "\n";
cout << " " << "These tests are part of Android V." << "\n";
LOGI("%s", log_message.c_str());
// If any of the following fail, then it is time to update the log message
// above.
EXPECT_EQ(ODK_MAJOR_VERSION, 19);
EXPECT_EQ(ODK_MINOR_VERSION, 5);
EXPECT_EQ(ODK_MINOR_VERSION, 6);
EXPECT_EQ(kCurrentAPI, static_cast<unsigned>(ODK_MAJOR_VERSION));
RecordWvProperty("test_major_version", std::to_string(ODK_MAJOR_VERSION));
RecordWvProperty("test_minor_version", std::to_string(ODK_MINOR_VERSION));
@@ -498,45 +498,58 @@ TEST_F(OEMCryptoClientTest, CheckBuildInformation_OutputLengthAPI17) {
ASSERT_GT(build_info_length, kZero)
<< "Signaling ERROR_SHORT_BUFFER should have assigned a length";
// Try again using the size they provided, ensuring that it
// is successful.
const size_t initial_estimate_length = build_info_length;
build_info.assign(build_info_length, kNullChar);
result = OEMCrypto_BuildInformation(&build_info[0], &build_info_length);
ASSERT_EQ(result, OEMCrypto_SUCCESS)
<< "initial_estimate_length = " << initial_estimate_length
<< ", build_info_length (output) = " << build_info_length;
ASSERT_GT(build_info_length, kZero) << "Build info cannot be empty";
// Ensure the real length is within the size originally specified.
// OK if final length is smaller than estimated length.
ASSERT_LE(build_info_length, initial_estimate_length);
const size_t expected_length = build_info_length;
// Force a ERROR_SHORT_BUFFER using a non-zero value.
// Note: It is assumed that vendors will provide more than a single
// character of info.
const size_t second_attempt_length =
(build_info_length >= 2) ? build_info_length / 2 : 1;
build_info.assign(second_attempt_length, kNullChar);
const size_t short_length = (expected_length >= 2) ? expected_length / 2 : 1;
build_info.assign(short_length, kNullChar);
build_info_length = build_info.size();
result = OEMCrypto_BuildInformation(&build_info[0], &build_info_length);
ASSERT_EQ(result, OEMCrypto_ERROR_SHORT_BUFFER)
<< "second_attempt_length = " << second_attempt_length
<< ", build_info_length" << build_info_length;
<< "short_length = " << short_length
<< ", expected_length = " << expected_length << ", build_info_length"
<< build_info_length;
// OEM specified build info length should be larger than the
// original length if returning ERROR_SHORT_BUFFER.
ASSERT_GT(build_info_length, second_attempt_length);
ASSERT_GT(build_info_length, short_length);
// Final attempt with a buffer large enough buffer, padding to
// ensure the caller truncates.
constexpr size_t kBufferPadSize = 42;
const size_t expected_length = build_info_length;
const size_t final_attempt_length = expected_length + kBufferPadSize;
build_info.assign(final_attempt_length, kNullChar);
const size_t oversize_length = expected_length + kBufferPadSize;
build_info.assign(oversize_length, kNullChar);
build_info_length = build_info.size();
result = OEMCrypto_BuildInformation(&build_info[0], &build_info_length);
ASSERT_EQ(result, OEMCrypto_SUCCESS)
<< "final_attempt_length = " << final_attempt_length
<< "oversize_length = " << oversize_length
<< ", expected_length = " << expected_length
<< ", build_info_length = " << build_info_length;
<< ", build_info_length (output) = " << build_info_length;
// Ensure not empty.
ASSERT_GT(build_info_length, kZero) << "Build info cannot be empty";
// Ensure it was truncated down from the padded length.
ASSERT_LT(build_info_length, final_attempt_length)
ASSERT_LT(build_info_length, oversize_length)
<< "Should have truncated from oversized buffer: expected_length = "
<< expected_length;
// Ensure the real length is within the size originally specified.
// OK if final length is smaller than estimated length.
ASSERT_LE(build_info_length, expected_length);
// Ensure that length is equal to the length of the previous
// successful call.
ASSERT_EQ(build_info_length, expected_length);
}
// Verifies that OEMCrypto_BuildInformation() is behaving as expected
@@ -680,7 +693,7 @@ TEST_F(OEMCryptoClientTest, CheckJsonBuildInformationAPI18) {
// Whether this was built with FACTORY_MODE_ONLY defined
{"is_factory_mode", JSMN_PRIMITIVE},
// ... provide information about liboemcrypto.so
// Special case, see kOptionalReeFields for details.
// Special case, see kReeOptionalFields for details.
{kSpecialCaseReeKey, JSMN_OBJECT},
// Technically required, but several implementations
// do not implement this fields.
@@ -778,7 +791,7 @@ TEST_F(OEMCryptoClientTest, CheckJsonBuildInformationAPI18) {
// The optional field "ree", if present, must follow the required
// format.
const std::map<std::string, jsmntype_t> kReeRequiredFields = {
const std::map<std::string, jsmntype_t> kReeOptionalFields = {
// liboemcrypto.so version in string format eg "2.15.0+tag"
{"liboemcrypto_ver", JSMN_STRING},
// git hash of code that compiled liboemcrypto.so
@@ -786,7 +799,6 @@ TEST_F(OEMCryptoClientTest, CheckJsonBuildInformationAPI18) {
// ISO 8601 timestamp for when liboemcrypto.so was built
{"build_timestamp", JSMN_STRING}};
found_required_fields.clear();
for (int32_t i = 0; (i + 1) < static_cast<int32_t>(ree_tokens.size());
i += 2) {
const jsmntok_t& key_token = ree_tokens[i];
@@ -796,11 +808,10 @@ TEST_F(OEMCryptoClientTest, CheckJsonBuildInformationAPI18) {
const std::string key =
build_info.substr(key_token.start, key_token.end - key_token.start);
if (kReeRequiredFields.find(key) != kReeRequiredFields.end()) {
ASSERT_EQ(value_token.type, kReeRequiredFields.at(key))
if (kReeOptionalFields.find(key) != kReeOptionalFields.end()) {
ASSERT_EQ(value_token.type, kReeOptionalFields.at(key))
<< "Unexpected optional REE field type: ree_field = " << key
<< ", build_info = " << build_info;
found_required_fields.insert(key);
RecordWvProperty(kReeBuildInfoRecordPrefix + key,
build_info.substr(value_token.start,
value_token.end - value_token.start));
@@ -810,25 +821,6 @@ TEST_F(OEMCryptoClientTest, CheckJsonBuildInformationAPI18) {
i += JsmnAncestorCount(ree_tokens, i + 1);
}
// Step 4b: Ensure all required fields of the "ree" object were found.
if (found_required_fields.size() == kReeRequiredFields.size()) return;
// Generate a list of all the missing REE fields.
std::string missing_ree_fields;
for (const auto& required_field : kReeRequiredFields) {
if (found_required_fields.find(required_field.first) !=
found_required_fields.end())
continue;
if (!missing_ree_fields.empty()) {
missing_ree_fields.append(", ");
}
missing_ree_fields.push_back('"');
missing_ree_fields.append(required_field.first);
missing_ree_fields.push_back('"');
}
FAIL() << "REE info JSON object does not contain all required keys; "
<< "missing_ree_fields = [" << missing_ree_fields
<< "], build_info = " << build_info;
}
TEST_F(OEMCryptoClientTest, CheckMaxNumberOfSessionsAPI10) {

View File

@@ -9,7 +9,9 @@
namespace wvoec {
namespace {
bool g_generate_corpus;
}
void AppendToFile(const std::string& file_name, const char* message,
const size_t message_size) {

View File

@@ -604,11 +604,13 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, ContinueDecryptionAfterIdleAndWake) {
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
}
namespace {
// Used to construct a specific pattern.
constexpr OEMCrypto_CENCEncryptPatternDesc MakePattern(size_t encrypt,
size_t skip) {
return {encrypt, skip};
}
} // namespace
INSTANTIATE_TEST_SUITE_P(
CTRTests, OEMCryptoSessionTestsDecryptTests,

View File

@@ -8,18 +8,6 @@ using namespace wvoec;
namespace wvoec {
// Make this function available when in Fuzz mode because we are not inheriting
// from OEMCryptoClientTest.
const uint8_t* find(const vector<uint8_t>& message,
const vector<uint8_t>& substring) {
vector<uint8_t>::const_iterator pos = search(
message.begin(), message.end(), substring.begin(), substring.end());
if (pos == message.end()) {
return nullptr;
}
return &(*pos);
}
void SessionUtil::CreateWrappedDRMKey() {
if (global_features.provisioning_method == OEMCrypto_BootCertificateChain) {
// Have the device create a wrapped key.

View File

@@ -11,6 +11,7 @@ namespace wvoec {
namespace util {
#define INIT_CRC32 0xffffffff
namespace {
uint32_t wvrunningcrc32(const uint8_t* p_begin, size_t i_count,
uint32_t i_crc) {
constexpr uint32_t CRC32[256] = {
@@ -67,6 +68,7 @@ uint32_t wvrunningcrc32(const uint8_t* p_begin, size_t i_count,
return(i_crc);
}
} // namespace
uint32_t wvcrc32(const uint8_t* p_begin, size_t i_count) {
return(wvrunningcrc32(p_begin, i_count, INIT_CRC32));

View File

@@ -13,7 +13,8 @@
namespace wvoec {
namespace util {
namespace {
// Putting type in non-anonymous namespace to prevent linkage warnings.
struct HmacTestVector {
std::vector<uint8_t> key;
std::vector<uint8_t> message;
@@ -43,6 +44,7 @@ void PrintTo(const HmacTestVector& v, std::ostream* os) {
*os << "signature_sha1 = " << wvutil::b2a_hex(v.signature_sha1) << "}";
}
namespace {
std::vector<uint8_t> FromString(const std::string& s) {
return std::vector<uint8_t>(s.begin(), s.end());
}