Source release 19.6.0
GitOrigin-RevId: 13a33e34413c19da1bfe76abcc66be519c9ac9d1
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
24
oemcrypto/odk/src/odk_versions.h
Normal file
24
oemcrypto/odk/src/odk_versions.h
Normal 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_
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user