Update Partner Repo

This update brings the partner repo up-to-date with commit
ae93405f980295f9a783bd04e2132a2370720107 in the internal repo.
This commit is contained in:
Aaron Vaage
2021-01-12 12:03:12 -08:00
parent bee7997487
commit 565237f8e6
41 changed files with 1466 additions and 1137 deletions

View File

@@ -1,8 +1,6 @@
This ODK Library is used to generate and parse core OEMCrypto messages for This ODK Library is used to generate and parse core OEMCrypto messages for
OEMCrypto v16 and above. OEMCrypto v16 and above. This library is used by both OEMCrypto on a device
and by Widevine license and provisioning servers.
This library is used by both OEMCrypto on a device, and by Widevine license and
provisioning servers.
The source of truth for these files is in the server code base on piper. Do not The source of truth for these files is in the server code base on piper. Do not
edit these files in the Android directory tree or in the Widevine Git edit these files in the Android directory tree or in the Widevine Git

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
/********************************************************************* /*********************************************************************
* OEMCryptoCENCCommon.h * OEMCryptoCENCCommon.h
@@ -20,7 +20,11 @@
extern "C" { extern "C" {
#endif #endif
/// @addtogroup common_types
/// @{
/* clang-format off */ /* clang-format off */
/** Error and result codes returned by OEMCrypto functions. */
typedef enum OEMCryptoResult { typedef enum OEMCryptoResult {
OEMCrypto_SUCCESS = 0, OEMCrypto_SUCCESS = 0,
OEMCrypto_ERROR_INIT_FAILED = 1, OEMCrypto_ERROR_INIT_FAILED = 1,
@@ -83,6 +87,7 @@ typedef enum OEMCryptoResult {
OEMCrypto_ERROR_LICENSE_RELOAD = 57, OEMCrypto_ERROR_LICENSE_RELOAD = 57,
OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES = 58, OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES = 58,
OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION = 59, OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION = 59,
OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION = 60,
/* ODK return values */ /* ODK return values */
ODK_ERROR_BASE = 1000, ODK_ERROR_BASE = 1000,
ODK_ERROR_CORE_MESSAGE = ODK_ERROR_BASE, ODK_ERROR_CORE_MESSAGE = ODK_ERROR_BASE,
@@ -94,8 +99,7 @@ typedef enum OEMCryptoResult {
} OEMCryptoResult; } OEMCryptoResult;
/* clang-format on */ /* clang-format on */
/* /**
* OEMCrypto_Usage_Entry_Status.
* Valid values for status in the usage table. * Valid values for status in the usage table.
*/ */
typedef enum OEMCrypto_Usage_Entry_Status { typedef enum OEMCrypto_Usage_Entry_Status {
@@ -106,7 +110,7 @@ typedef enum OEMCrypto_Usage_Entry_Status {
kInactiveUnused = 4, kInactiveUnused = 4,
} OEMCrypto_Usage_Entry_Status; } OEMCrypto_Usage_Entry_Status;
/* /**
* OEMCrypto_LicenseType is used in the license message to indicate if the key * OEMCrypto_LicenseType is used in the license message to indicate if the key
* objects are for content keys, or for entitlement keys. * objects are for content keys, or for entitlement keys.
*/ */
@@ -122,9 +126,7 @@ typedef enum OEMCrypto_PrivateKeyType {
OEMCrypto_ECC_Private_Key = 1, OEMCrypto_ECC_Private_Key = 1,
} OEMCrypto_PrivateKeyType; } OEMCrypto_PrivateKeyType;
/* /**
* OEMCrypto_Substring
*
* Used to indicate a substring of a signed message in OEMCrypto_LoadKeys and * Used to indicate a substring of a signed message in OEMCrypto_LoadKeys and
* other functions which must verify that a parameter is contained within a * other functions which must verify that a parameter is contained within a
* signed message. * signed message.
@@ -134,23 +136,22 @@ typedef struct {
size_t length; size_t length;
} OEMCrypto_Substring; } OEMCrypto_Substring;
/* /**
* OEMCrypto_KeyObject
* Points to the relevant fields for a content key. The fields are extracted * Points to the relevant fields for a content key. The fields are extracted
* from the License Response message offered to OEMCrypto_LoadKeys(). Each * from the License Response message offered to OEMCrypto_LoadKeys(). Each
* field points to one of the components of the key. Key data, key control, * field points to one of the components of the key. Key data, key control,
* and both IV fields are 128 bits (16 bytes): * and both IV fields are 128 bits (16 bytes):
* key_id - the unique id of this key. * @param key_id: the unique id of this key.
* key_id_length - the size of key_id. OEMCrypto may assume this is at * @param key_id_length: the size of key_id. OEMCrypto may assume this is at
* most 16. However, OEMCrypto shall correctly handle key id lengths * most 16. However, OEMCrypto shall correctly handle key id lengths
* from 1 to 16 bytes. * from 1 to 16 bytes.
* key_data_iv - the IV for performing AES-128-CBC decryption of the * @param key_data_iv: the IV for performing AES-128-CBC decryption of the
* key_data field. * key_data field.
* key_data - the key data. It is encrypted (AES-128-CBC) with the * @param key_data - the key data. It is encrypted (AES-128-CBC) with the
* session's derived encrypt key and the key_data_iv. * session's derived encrypt key and the key_data_iv.
* key_control_iv - the IV for performing AES-128-CBC decryption of the * @param key_control_iv: the IV for performing AES-128-CBC decryption of the
* key_control field. * key_control field.
* key_control - the key control block. It is encrypted (AES-128-CBC) with * @param key_control: the key control block. It is encrypted (AES-128-CBC) with
* the content key from the key_data field. * the content key from the key_data field.
* *
* The memory for the OEMCrypto_KeyObject fields is allocated and freed * The memory for the OEMCrypto_KeyObject fields is allocated and freed
@@ -164,8 +165,10 @@ typedef struct {
OEMCrypto_Substring key_control; OEMCrypto_Substring key_control;
} OEMCrypto_KeyObject; } OEMCrypto_KeyObject;
/// @}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* WIDEVINE_ODK_INCLUDE_OEMCRYPTOCENCCOMMON_H_ */ #endif // WIDEVINE_ODK_INCLUDE_OEMCRYPTOCENCCOMMON_H_

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
/********************************************************************* /*********************************************************************
* core_message_deserialize.h * core_message_deserialize.h
@@ -53,7 +53,17 @@ bool CoreProvisioningRequestFromMessage(
const std::string& oemcrypto_core_message, const std::string& oemcrypto_core_message,
ODK_ProvisioningRequest* core_provisioning_request); ODK_ProvisioningRequest* core_provisioning_request);
} /* namespace deserialize */ /**
} /* namespace oemcrypto_core_message */ * Serializer counterpart is not used and is therefore not implemented.
*
* Parameters:
* [in] oemcrypto_core_message
* [out] core_common_request
*/
bool CoreCommonRequestFromMessage(const std::string& oemcrypto_core_message,
ODK_CommonRequest* core_common_request);
#endif /* WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_DESERIALIZE_H_ */ } // namespace deserialize
} // namespace oemcrypto_core_message
#endif // WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_DESERIALIZE_H_

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
/********************************************************************* /*********************************************************************
* core_message_serialize.h * core_message_serialize.h
@@ -62,7 +62,7 @@ bool CreateCoreRenewalResponse(const ODK_RenewalRequest& core_request,
bool CreateCoreProvisioningResponse(const ODK_ParsedProvisioning& parsed_prov, bool CreateCoreProvisioningResponse(const ODK_ParsedProvisioning& parsed_prov,
const ODK_ProvisioningRequest& core_request, const ODK_ProvisioningRequest& core_request,
std::string* oemcrypto_core_message); std::string* oemcrypto_core_message);
} /* namespace serialize */ } // namespace serialize
} /* namespace oemcrypto_core_message */ } // namespace oemcrypto_core_message
#endif /* WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_H_ */ #endif // WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_H_

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
/********************************************************************* /*********************************************************************
* core_message_serialize_proto.h * core_message_serialize_proto.h
@@ -23,7 +23,7 @@
namespace oemcrypto_core_message { namespace oemcrypto_core_message {
namespace serialize { namespace serialize {
/* @ public create response (serializer) functions accepting proto input */ // @ public create response (serializer) functions accepting proto input
/** /**
* Counterpart (serializer) of ODK_ParseLicense (deserializer) * Counterpart (serializer) of ODK_ParseLicense (deserializer)
@@ -34,12 +34,14 @@ namespace serialize {
* [in] core_request oemcrypto core message from request. * [in] core_request oemcrypto core message from request.
* [in] core_request_sha256 - hash of serialized core request. * [in] core_request_sha256 - hash of serialized core request.
* [in] nonce_required - if the device should require a nonce match. * [in] nonce_required - if the device should require a nonce match.
* [in] uses_padding - if the keys use padding.
* [out] oemcrypto_core_message - the serialized oemcrypto core response. * [out] oemcrypto_core_message - the serialized oemcrypto core response.
*/ */
bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license, bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
const ODK_LicenseRequest& core_request, const ODK_LicenseRequest& core_request,
const std::string& core_request_sha256, const std::string& core_request_sha256,
const bool nonce_required, const bool nonce_required,
const bool uses_padding,
std::string* oemcrypto_core_message); std::string* oemcrypto_core_message);
/** /**
@@ -56,7 +58,7 @@ bool CreateCoreProvisioningResponseFromProto(
const ODK_ProvisioningRequest& core_request, const ODK_ProvisioningRequest& core_request,
std::string* oemcrypto_core_message); std::string* oemcrypto_core_message);
} /* namespace serialize */ } // namespace serialize
} /* namespace oemcrypto_core_message */ } // namespace oemcrypto_core_message
#endif /* WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_PROTO_H_ */ #endif // WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_PROTO_H_

View File

@@ -1,8 +1,8 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
/* clang-format off */ // clang-format off
/********************************************************************* /*********************************************************************
* core_message_types.h * core_message_types.h
* *
@@ -38,6 +38,8 @@
* | | ODK_PrepareCoreRenewalRequest | | CoreRenewalRequestFromMessage | * | | ODK_PrepareCoreRenewalRequest | | CoreRenewalRequestFromMessage |
* | +------------------------------------+ +-----------------------------------+ * | +------------------------------------+ +-----------------------------------+
* | | ODK_PrepareCoreProvisioningRequest | | CoreProvisioningRequestFromMessage| * | | ODK_PrepareCoreProvisioningRequest | | CoreProvisioningRequestFromMessage|
* | +------------------------------------+ +-----------------------------------+
* | | ODK_PrepareCommonRequest | | CoreCommonRequestFromMessage |
* +---+------------------------------------+---+-----------------------------------+ * +---+------------------------------------+---+-----------------------------------+
* | d | ODK_ParseLicense | s | CreateCoreLicenseResponse | * | d | ODK_ParseLicense | s | CreateCoreLicenseResponse |
* | +------------------------------------+ +-----------------------------------+ * | +------------------------------------+ +-----------------------------------+
@@ -47,7 +49,7 @@
* +---+------------------------------------+---+-----------------------------------+ * +---+------------------------------------+---+-----------------------------------+
* *
*********************************************************************/ *********************************************************************/
/* clang-format on */ // clang-format on
#ifndef WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_TYPES_H_ #ifndef WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_TYPES_H_
#define WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_TYPES_H_ #define WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_TYPES_H_
@@ -57,7 +59,18 @@
namespace oemcrypto_core_message { namespace oemcrypto_core_message {
/* @ input/output structs */ // @ input/output structs
/**
* Output structure for CommonRequestFromMessage
* Input structure for CreateCommonResponse
*/
struct ODK_CommonRequest {
uint16_t api_minor_version;
uint16_t api_major_version;
uint32_t nonce;
uint32_t session_id;
};
/** /**
* Output structure for CoreLicenseRequestFromMessage * Output structure for CoreLicenseRequestFromMessage
@@ -94,6 +107,6 @@ struct ODK_ProvisioningRequest {
std::string device_id; std::string device_id;
}; };
} /* namespace oemcrypto_core_message */ } // namespace oemcrypto_core_message
#endif /* WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_TYPES_H_ */ #endif // WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_TYPES_H_

View File

@@ -1,11 +1,9 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
/********************************************************************* /**
* odk.h * @mainpage OEMCrypto v16 Core Message Serialization library
*
* OEMCrypto v16 Core Message Serialization library
* *
* For Widevine Modular DRM, there are six message types between a server and * For Widevine Modular DRM, there are six message types between a server and
* a client device: license request and response, provisioning request and * a client device: license request and response, provisioning request and
@@ -34,12 +32,30 @@
* ODK library shall be sanitized by the OEMCrypto implementer to prevent * ODK library shall be sanitized by the OEMCrypto implementer to prevent
* modification by any process running the REE. * modification by any process running the REE.
* *
* See the documents "Widevine Core Message Serialization" and "License * See the documents
* Duration and Renewal" for a detailed description of the ODK API. You can * <a href="../odk">Widevine Core Message Serialization</a>
* and
* <a href="../../lic_duration_and_renewal">License Duration and Renewal</a>
* for a detailed description of the ODK API. You can
* find these documents in the widevine repository as * find these documents in the widevine repository as
* docs/Widevine_Core_Message_Serialization.pdf and * docs/Widevine_Core_Message_Serialization.pdf and
* docs/License_Duration_and_Renewal.pdf * docs/License_Duration_and_Renewal.pdf
* *
* @defgroup odk_parser Core Message Parsing and Verification
* Functions that parse core messages and verify they are valid.
* TODO(fredgc): add documentation for parsing functions.
*
* @defgroup odk_packer Core Message Creation
* Functions that create core messages.
* TODO(fredgc): add documentation for packing functions.
*
* @defgroup odk_timer Timer and Clock Functions
* Functions related to enforcing timer and duration restrictions.
* TODO(fredgc): add documentation for timers and clocks.
*
* @defgroup common_types Common Types
* Enumerations and structures that are used by several OEMCrypto and ODK
* functions.
*********************************************************************/ *********************************************************************/
#ifndef WIDEVINE_ODK_INCLUDE_ODK_H_ #ifndef WIDEVINE_ODK_INCLUDE_ODK_H_
@@ -54,25 +70,23 @@
extern "C" { extern "C" {
#endif #endif
/* /// @addtogroup odk_timer
* ODK_InitializeSessionValues /// @{
*
* Description: /**
* This function initializes the session's data structures. It shall be * This function initializes the session's data structures. It shall be
* called from OEMCrypto_OpenSession. * called from OEMCrypto_OpenSession.
* *
* Parameters: * @param[out] timer_limits: the session's timer limits.
* [out] timer_limits: the session's timer limits. * @param[out] clock_values: the session's clock values.
* [out] clock_values: the session's clock values. * @param[out] nonce_values: the session's ODK nonce values.
* [out] nonce_values: the session's ODK nonce values. * @param[in] api_major_version: the API version of OEMCrypto.
* [in] api_major_version: the API version of OEMCrypto. * @param[in] session_id: the session id of the newly created session.
* [in] session_id: the session id of the newly created session.
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval OEMCrypto_ERROR_INVALID_CONTEXT
* OEMCrypto_ERROR_INVALID_CONTEXT
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits, OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
@@ -81,72 +95,60 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
uint32_t api_major_version, uint32_t api_major_version,
uint32_t session_id); uint32_t session_id);
/* /**
* ODK_SetNonceValues
*
* Description:
* This function sets the nonce value in the session's nonce structure. It * This function sets the nonce value in the session's nonce structure. It
* shall be called from OEMCrypto_GenerateNonce. * shall be called from OEMCrypto_GenerateNonce.
* *
* Parameters: * @param[in,out] nonce_values: the session's nonce data.
* [in/out] nonce_values: the session's nonce data. * @param[in] nonce: the new nonce that was just generated.
* [in] nonce: the new nonce that was just generated.
* *
* Returns: * @retval true on success
* true on success
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_SetNonceValues(ODK_NonceValues* nonce_values, OEMCryptoResult ODK_SetNonceValues(ODK_NonceValues* nonce_values,
uint32_t nonce); uint32_t nonce);
/* /**
* ODK_InitializeClockValues
*
* Description:
* This function initializes the clock values in the session clock_values * This function initializes the clock values in the session clock_values
* structure. It shall be called from OEMCrypto_PrepAndSignLicenseRequest. * structure. It shall be called from OEMCrypto_PrepAndSignLicenseRequest.
* *
* Parameters: * Parameters:
* [in/out] clock_values: the session's clock data. * @param[in,out] clock_values: the session's clock data.
* [in] system_time_seconds: the current time on OEMCrypto's monotonic clock. * @param[in] system_time_seconds: the current time on OEMCrypto's monotonic
* clock.
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval OEMCrypto_ERROR_INVALID_CONTEXT
* OEMCrypto_ERROR_INVALID_CONTEXT
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values, OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
uint64_t system_time_seconds); uint64_t system_time_seconds);
/* /**
* ODK_ReloadClockValues
*
* Description:
* This function sets the values in the clock_values structure. It shall be * This function sets the values in the clock_values structure. It shall be
* called from OEMCrypto_LoadUsageEntry. When a usage entry from a v15 or * called from OEMCrypto_LoadUsageEntry. When a usage entry from a v15 or
* earlier license is loaded, the value time_of_license_loaded shall be used * earlier license is loaded, the value time_of_license_loaded shall be used
* in place of time_of_license_signed. * in place of time_of_license_signed.
* *
* Parameters: * @param[in,out] clock_values: the session's clock data.
* [in/out] clock_values: the session's clock data. * @param[in] time_of_license_signed: the value time_license_received from the
* [in] time_of_license_signed: the value time_license_received from the
* loaded usage entry. * loaded usage entry.
* [in] time_of_first_decrypt: the value time_of_first_decrypt from the * @param[in] time_of_first_decrypt: the value time_of_first_decrypt from the
* loaded usage entry. * loaded usage entry.
* [in] time_of_last_decrypt: the value time_of_last_decrypt from the loaded * @param[in] time_of_last_decrypt: the value time_of_last_decrypt from the
* usage entry. * loaded usage entry.
* [in] status: the value status from the loaded usage entry. * @param[in] status: the value status from the loaded usage entry.
* [in] system_time_seconds: the current time on OEMCrypto's monotonic clock. * @param[in] system_time_seconds: the current time on OEMCrypto's monotonic
* clock.
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval OEMCrypto_ERROR_INVALID_CONTEXT
* OEMCrypto_ERROR_INVALID_CONTEXT
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values, OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
@@ -156,10 +158,7 @@ OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
enum OEMCrypto_Usage_Entry_Status status, enum OEMCrypto_Usage_Entry_Status status,
uint64_t system_time_seconds); uint64_t system_time_seconds);
/* /**
* ODK_AttemptFirstPlayback
*
* Description:
* This updates the clock values, and determines if playback may start based * This updates the clock values, and determines if playback may start based
* on the given system time. It uses the values in clock_values to determine * on the given system time. It uses the values in clock_values to determine
* if this is the first playback for the license or the first playback for * if this is the first playback for the license or the first playback for
@@ -172,23 +171,21 @@ OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
* ODK_SET_TIMER, then the timer should be set to the value pointed to by * ODK_SET_TIMER, then the timer should be set to the value pointed to by
* timer_value. * timer_value.
* *
* Parameters: * @param[in] system_time_seconds: the current time on OEMCrypto's monotonic
* [in] system_time_seconds: the current time on OEMCrypto's monotonic clock, * clock, in seconds.
* in seconds. * @param[in] timer_limits: timer limits specified in the license.
* [in] timer_limits: timer limits specified in the license. * @param[in,out] clock_values: the sessions clock values.
* [in/out] clock_values: the sessions clock values. * @param[out] timer_value: set to the new timer value. Only used if the return
* [out] timer_value: set to the new timer value. Only used if the return
* value is ODK_SET_TIMER. This must be non-null if OEMCrypto uses a * value is ODK_SET_TIMER. This must be non-null if OEMCrypto uses a
* hardware timer. * hardware timer.
* *
* Returns: * @retval ODK_SET_TIMER: Success. The timer should be reset to the specified
* ODK_SET_TIMER: Success. The timer should be reset to the specified value * value and playback is allowed.
* and playback is allowed. * @retval ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
* ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
* allowed. * allowed.
* ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed. * @retval ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds, OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
@@ -196,10 +193,7 @@ OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
ODK_ClockValues* clock_values, ODK_ClockValues* clock_values,
uint64_t* timer_value); uint64_t* timer_value);
/* /**
* ODK_UpdateLastPlaybackTime
*
* Description:
* Vendors that do not implement their own timer should call * Vendors that do not implement their own timer should call
* ODK_UpdateLastPlaybackTime regularly during playback. This updates the * ODK_UpdateLastPlaybackTime regularly during playback. This updates the
* clock values, and determines if playback may continue based on the given * clock values, and determines if playback may continue based on the given
@@ -211,47 +205,43 @@ OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
* OEMCrypto_UpdateUsageEntry before updating the usage entry so that the * OEMCrypto_UpdateUsageEntry before updating the usage entry so that the
* clock values are accurate. * clock values are accurate.
* *
* Parameters: * @param[in] system_time_seconds: the current time on OEMCrypto's monotonic
* [in] system_time_seconds: the current time on OEMCrypto's monotonic clock, * clock, in seconds.
* in seconds. * @param[in] timer_limits: timer limits specified in the license.
* [in] timer_limits: timer limits specified in the license. * @param[in,out] clock_values: the sessions clock values.
* [in/out] clock_values: the sessions clock values.
* *
* Returns: * @retval OEMCrypto_SUCCESS: Success. Playback is allowed.
* OEMCrypto_SUCCESS: Success. Playback is allowed. * @retval ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
* ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_UpdateLastPlaybackTime(uint64_t system_time_seconds, OEMCryptoResult ODK_UpdateLastPlaybackTime(uint64_t system_time_seconds,
const ODK_TimerLimits* timer_limits, const ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values); ODK_ClockValues* clock_values);
/* /**
* ODK_DeactivateUsageEntry
*
* Description:
* This function modifies the session's clock values to indicate that the * This function modifies the session's clock values to indicate that the
* license has been deactivated. It shall be called from * license has been deactivated. It shall be called from
* OEMCrypto_DeactivateUsageEntry * OEMCrypto_DeactivateUsageEntry
* *
* Parameters: * Parameters:
* [in/out] clock_values: the sessions clock values. * @param[in,out] clock_values: the sessions clock values.
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval OEMCrypto_ERROR_INVALID_CONTEXT
* OEMCrypto_ERROR_INVALID_CONTEXT
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values); OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values);
/* /// @}
* ODK_PrepareCoreLicenseRequest
* /// @addtogroup odk_packer
* Description: /// @{
/**
* Modifies the message to include a core license request at the beginning of * Modifies the message to include a core license request at the beginning of
* the message buffer. The values in nonce_values are used to populate the * the message buffer. The values in nonce_values are used to populate the
* message. * message.
@@ -262,31 +252,26 @@ OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values);
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output * zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
* core_message_size to the size needed. * core_message_size to the size needed.
* *
* Parameters: * @param[in,out] message: Pointer to memory for the entire message. Modified by
* [in/out] message: Pointer to memory for the entire message. Modified by
* the ODK library. * the ODK library.
* [in] message_length: length of the entire message buffer. * @param[in] message_length: length of the entire message buffer.
* [in/out] core_message_size: length of the core message at the beginning of * @param[in,out] core_message_size: length of the core message at the beginning
* the message. (in) size of buffer reserved for the core message, in * of the message. (in) size of buffer reserved for the core message, in
* bytes. (out) actual length of the core message, in bytes. * bytes. (out) actual length of the core message, in bytes.
* [in] nonce_values: pointer to the session's nonce data. * @param[in] nonce_values: pointer to the session's nonce data.
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
* OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small * @retval OEMCrypto_ERROR_INVALID_CONTEXT
* OEMCrypto_ERROR_INVALID_CONTEXT
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_PrepareCoreLicenseRequest( OEMCryptoResult ODK_PrepareCoreLicenseRequest(
uint8_t* message, size_t message_length, size_t* core_message_size, uint8_t* message, size_t message_length, size_t* core_message_size,
const ODK_NonceValues* nonce_values); const ODK_NonceValues* nonce_values);
/* /**
* ODK_PrepareCoreRenewalRequest
*
* Description:
* Modifies the message to include a core renewal request at the beginning of * Modifies the message to include a core renewal request at the beginning of
* the message buffer. The values in nonce_values, clock_values and * the message buffer. The values in nonce_values, clock_values and
* system_time_seconds are used to populate the message. The nonce_values * system_time_seconds are used to populate the message. The nonce_values
@@ -304,24 +289,22 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output * zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
* core_message_size to the size needed. * core_message_size to the size needed.
* *
* Parameters: * @param[in,out] message: Pointer to memory for the entire message. Modified by
* [in/out] message: Pointer to memory for the entire message. Modified by
* the ODK library. * the ODK library.
* [in] message_length: length of the entire message buffer. * @param[in] message_length: length of the entire message buffer.
* [in/out] core_message_size: length of the core message at the beginning of * @param[in,out] core_message_size: length of the core message at the beginning
* the message. (in) size of buffer reserved for the core message, in * of the message. (in) size of buffer reserved for the core message, in
* bytes. (out) actual length of the core message, in bytes. * bytes. (out) actual length of the core message, in bytes.
* [in/out] nonce_values: pointer to the session's nonce data. * @param[in,out] nonce_values: pointer to the session's nonce data.
* [in/out] clock_values: the session's clock values. * @param[in,out] clock_values: the session's clock values.
* [in] system_time_seconds: the current time on OEMCrypto's clock, in * @param[in] system_time_seconds: the current time on OEMCrypto's clock, in
* seconds. * seconds.
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
* OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small * @retval OEMCrypto_ERROR_INVALID_CONTEXT
* OEMCrypto_ERROR_INVALID_CONTEXT
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message, OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
@@ -331,10 +314,7 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
ODK_ClockValues* clock_values, ODK_ClockValues* clock_values,
uint64_t system_time_seconds); uint64_t system_time_seconds);
/* /**
* ODK_PrepareCoreProvisioningRequest
*
* Description:
* Modifies the message to include a core provisioning request at the * Modifies the message to include a core provisioning request at the
* beginning of the message buffer. The values in nonce_values are used to * beginning of the message buffer. The values in nonce_values are used to
* populate the message. * populate the message.
@@ -350,26 +330,24 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output * zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
* core_message_size to the size needed. * core_message_size to the size needed.
* *
* Parameters: * @param[in,out] message: Pointer to memory for the entire message. Modified by
* [in/out] message: Pointer to memory for the entire message. Modified by
* the ODK library. * the ODK library.
* [in] message_length: length of the entire message buffer. * @param[in] message_length: length of the entire message buffer.
* [in/out] core_message_size: length of the core message at the beginning of * @param[in,out] core_message_size: length of the core message at the beginning
* the message. (in) size of buffer reserved for the core message, in * of the message. (in) size of buffer reserved for the core message, in
* bytes. (out) actual length of the core message, in bytes. * bytes. (out) actual length of the core message, in bytes.
* [in] nonce_values: pointer to the session's nonce data. * @param[in] nonce_values: pointer to the session's nonce data.
* [in] device_id: For devices with a keybox, this is the device ID from the * @param[in] device_id: For devices with a keybox, this is the device ID from
* keybox. For devices with an OEM Certificate, this is a device unique * the keybox. For devices with an OEM Certificate, this is a device
* id string. * unique id string.
* [in] device_id_length: length of device_id. The device ID can be at most * @param[in] device_id_length: length of device_id. The device ID can be at
* 64 bytes. * most 64 bytes.
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
* OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small * @retval OEMCrypto_ERROR_INVALID_CONTEXT
* OEMCrypto_ERROR_INVALID_CONTEXT
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_PrepareCoreProvisioningRequest( OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
@@ -377,30 +355,30 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
const ODK_NonceValues* nonce_values, const uint8_t* device_id, const ODK_NonceValues* nonce_values, const uint8_t* device_id,
size_t device_id_length); size_t device_id_length);
/* /// @}
* ODK_InitializeV15Values
* /// @addtogroup odk_timer
* Description: /// @{
/**
* This function sets all limits in the timer_limits struct to the * This function sets all limits in the timer_limits struct to the
* key_duration and initializes the other values. The field * key_duration and initializes the other values. The field
* nonce_values.api_major_version will be set to 15. It shall be called from * nonce_values.api_major_version will be set to 15. It shall be called from
* OEMCrypto_LoadKeys when loading a legacy license. * OEMCrypto_LoadKeys when loading a legacy license.
* *
* Parameters: * @param[out] timer_limits: The session's timer limits.
* [out] timer_limits: The session's timer limits. * @param[in,out] clock_values: The session's clock values.
* [in/out] clock_values: The session's clock values. * @param[in,out] nonce_values: The session's ODK nonce values.
* [in/out] nonce_values: The session's ODK nonce values. * @param[in] key_duration: The duration from the first key's key control
* [in] key_duration: The duration from the first key's key control block. In * block. In practice, the key duration is the same for all keys and is
* practice, the key duration is the same for all keys and is the same * the same as the license duration.
* as the license duration. * @param[in] system_time_seconds: The current time on the system clock, as
* [in] system_time_seconds: The current time on the system clock, as
* described in the document "License Duration and Renewal". * described in the document "License Duration and Renewal".
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval OEMCrypto_ERROR_INVALID_CONTEXT
* OEMCrypto_ERROR_INVALID_CONTEXT
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits, OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
@@ -409,10 +387,7 @@ OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
uint32_t key_duration, uint32_t key_duration,
uint64_t system_time_seconds); uint64_t system_time_seconds);
/* /**
* ODK_RefreshV15Values
*
* Description:
* This function updates the clock_values as needed if a v15 renewal is * This function updates the clock_values as needed if a v15 renewal is
* accepted. The field nonce_values.api_major_version is verified to be 15. * accepted. The field nonce_values.api_major_version is verified to be 15.
* *
@@ -420,28 +395,26 @@ OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
* OEMCrypto shall pass in the current system time, and the key duration from * OEMCrypto shall pass in the current system time, and the key duration from
* the first object in the OEMCrypto_KeyRefreshObject. * the first object in the OEMCrypto_KeyRefreshObject.
* *
* Parameters: * @param[in] timer_limits: The session's timer limits.
* [in] timer_limits: The session's timer limits. * @param[in,out] clock_values: The session's clock values.
* [in/out] clock_values: The session's clock values. * @param[in] nonce_values: The session's ODK nonce values.
* [in] nonce_values: The session's ODK nonce values. * @param[in] system_time_seconds: The current time on the system clock, as
* [in] system_time_seconds: The current time on the system clock, as
* described in the document "License Duration and Renewal". * described in the document "License Duration and Renewal".
* [in] new_key_duration: The duration from the first * @param[in] new_key_duration: The duration from the first
* OEMCrypto_KeyRefreshObject in key_array. * OEMCrypto_KeyRefreshObject in key_array.
* [out] timer_value: set to the new timer value. Only used if the return * @param[out] timer_value: set to the new timer value. Only used if the return
* value is ODK_SET_TIMER. This must be non-null if OEMCrypto uses a * value is ODK_SET_TIMER. This must be non-null if OEMCrypto uses a
* hardware timer. * hardware timer.
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
* OEMCrypto_ERROR_UNKNOWN_FAILURE * @retval ODK_SET_TIMER: Success. The timer should be reset to the specified
* ODK_SET_TIMER: Success. The timer should be reset to the specified value * value and playback is allowed.
* and playback is allowed. * @retval ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
* ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
* allowed. * allowed.
* ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed. * @retval ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits, OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
@@ -451,10 +424,12 @@ OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
uint32_t new_key_duration, uint32_t new_key_duration,
uint64_t* timer_value); uint64_t* timer_value);
/* /// @}
* ODK_ParseLicense
* /// @addtogroup odk_parser
* Description: /// @{
/**
* The function ODK_ParseLicense will parse the message and verify fields in * The function ODK_ParseLicense will parse the message and verify fields in
* the message. * the message.
* *
@@ -486,31 +461,32 @@ OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
* If usage_entry_present is true, then ODK_ParseLicense shall verify that * If usage_entry_present is true, then ODK_ParseLicense shall verify that
* the pst in the license has a nonzero length. * the pst in the license has a nonzero length.
* *
* Parameters: * @param[in] message: pointer to the message buffer.
* [in] message: pointer to the message buffer. * @param[in] message_length: length of the entire message buffer.
* [in] message_length: length of the entire message buffer. * @param[in] core_message_size: length of the core message, at the beginning of
* [in] core_message_size: length of the core message, at the beginning of
* the message buffer. * the message buffer.
* [in] initial_license_load: true when called for OEMCrypto_LoadLicense and * @param[in] initial_license_load: true when called for OEMCrypto_LoadLicense
* false when called for OEMCrypto_ReloadLicense. * and false when called for OEMCrypto_ReloadLicense.
* [in] usage_entry_present: true if the session has a new usage entry * @param[in] usage_entry_present: true if the session has a new usage entry
* associated with it created via OEMCrypto_CreateNewUsageEntry. * associated with it created via OEMCrypto_CreateNewUsageEntry.
* [in] request_hash: the hash of the license request core message. This was * @param[in] request_hash: the hash of the license request core message. This
* computed by OEMCrypto when the license request was signed. * was computed by OEMCrypto when the license request was signed.
* [in/out] timer_limits: The session's timer limits. These will be updated. * @param[in,out] timer_limits: The session's timer limits. These will be
* [in/out] clock_values: The session's clock values. These will be updated. * updated.
* [in/out] nonce_values: The session's nonce values. These will be updated. * @param[in,out] clock_values: The session's clock values. These will be
* [out] parsed_license: the destination for the data. * updated.
* @param[in,out] nonce_values: The session's nonce values. These will be
* updated.
* @param[out] parsed_license: the destination for the data.
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval ODK_ERROR_CORE_MESSAGE: if the message did not parse correctly, or
* ODK_ERROR_CORE_MESSAGE: if the message did not parse correctly, or there * there were other incorrect values. An error should be returned to the
* were other incorrect values. An error should be returned to the CDM * CDM layer.
* layer. * @retval ODK_UNSUPPORTED_API
* ODK_UNSUPPORTED_API * @retval OEMCrypto_ERROR_INVALID_NONCE
* OEMCrypto_ERROR_INVALID_NONCE
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_ParseLicense( OEMCryptoResult ODK_ParseLicense(
@@ -520,10 +496,7 @@ OEMCryptoResult ODK_ParseLicense(
ODK_TimerLimits* timer_limits, ODK_ClockValues* clock_values, ODK_TimerLimits* timer_limits, ODK_ClockValues* clock_values,
ODK_NonceValues* nonce_values, ODK_ParsedLicense* parsed_license); ODK_NonceValues* nonce_values, ODK_ParsedLicense* parsed_license);
/* /**
* ODK_ParseRenewal
*
* Description:
* The function ODK_ParseRenewal will parse the message and verify its * The function ODK_ParseRenewal will parse the message and verify its
* contents. If the message does not parse correctly, an error of * contents. If the message does not parse correctly, an error of
* ODK_ERROR_CORE_MESSAGE is returned. * ODK_ERROR_CORE_MESSAGE is returned.
@@ -544,34 +517,33 @@ OEMCryptoResult ODK_ParseLicense(
* ODK_SET_TIMER, then OEMCrypto shall set the timer to the value pointed to * ODK_SET_TIMER, then OEMCrypto shall set the timer to the value pointed to
* by timer_value. * by timer_value.
* *
* Parameters: * @param[in] message: pointer to the message buffer.
* [in] message: pointer to the message buffer. * @param[in] message_length: length of the entire message buffer.
* [in] message_length: length of the entire message buffer. * @param[in] core_message_size: length of the core message, at the beginning of
* [in] core_message_size: length of the core message, at the beginning of
* the message buffer. * the message buffer.
* [in] nonce_values: pointer to the session's nonce data. * @param[in] nonce_values: pointer to the session's nonce data.
* [in] system_time_seconds: the current time on OEMCrypto's clock, in * @param[in] system_time_seconds: the current time on OEMCrypto's clock, in
* seconds. * seconds.
* [in] timer_limits: timer limits specified in the license. * @param[in] timer_limits: timer limits specified in the license.
* [in/out] clock_values: the sessions clock values. * @param[in,out] clock_values: the sessions clock values.
* [out] timer_value: set to the new timer value. Only used if the return * @param[out] timer_value: set to the new timer value. Only used if the return
* value is ODK_SET_TIMER. This must be non-null if OEMCrypto uses a * value is ODK_SET_TIMER. This must be non-null if OEMCrypto uses a
* hardware timer. * hardware timer.
* *
* Returns: * @retval ODK_ERROR_CORE_MESSAGE: the message did not parse correctly, or there
* ODK_ERROR_CORE_MESSAGE: the message did not parse correctly, or there were * were other incorrect values. An error should be returned to the CDM
* other incorrect values. An error should be returned to the CDM layer. * layer.
* ODK_SET_TIMER: Success. The timer should be reset to the specified timer * @retval ODK_SET_TIMER: Success. The timer should be reset to the specified
* value. * timer value.
* ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is * @retval ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
* allowed. * allowed.
* ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed. * @retval ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
* ODK_UNSUPPORTED_API * @retval ODK_UNSUPPORTED_API
* ODK_STALE_RENEWAL: This renewal is not the most recently signed. It is * @retval ODK_STALE_RENEWAL: This renewal is not the most recently signed. It
* rejected. * is rejected.
* OEMCrypto_ERROR_INVALID_NONCE * @retval OEMCrypto_ERROR_INVALID_NONCE
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length, OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
@@ -582,10 +554,7 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
ODK_ClockValues* clock_values, ODK_ClockValues* clock_values,
uint64_t* timer_value); uint64_t* timer_value);
/* /**
* ODK_ParseProvisioning
*
* Description:
* The function ODK_ParseProvisioning will parse the message and verify the * The function ODK_ParseProvisioning will parse the message and verify the
* nonce values match those in the license. * nonce values match those in the license.
* *
@@ -604,25 +573,24 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
* at message + core_message_length with size message_length - * at message + core_message_length with size message_length -
* core_message_length. * core_message_length.
* *
* Parameters: * @param[in] message: pointer to the message buffer.
* [in] message: pointer to the message buffer. * @param[in] message_length: length of the entire message buffer.
* [in] message_length: length of the entire message buffer. * @param[in] core_message_size: length of the core message, at the beginning of
* [in] core_message_size: length of the core message, at the beginning of
* the message buffer. * the message buffer.
* [in] nonce_values: pointer to the session's nonce data. * @param[in] nonce_values: pointer to the session's nonce data.
* [in] device_id: a pointer to a buffer containing the device ID of the * @param[in] device_id: a pointer to a buffer containing the device ID of the
* device. The ODK function will verify it matches that in the message. * device. The ODK function will verify it matches that in the message.
* [in] device_id_length: the length of the device ID. * @param[in] device_id_length: the length of the device ID.
* [out] parsed_response: destination for the parse data. * @param[out] parsed_response: destination for the parse data.
* *
* Returns: * @retval OEMCrypto_SUCCESS
* OEMCrypto_SUCCESS * @retval ODK_ERROR_CORE_MESSAGE: the message did not parse correctly, or there
* ODK_ERROR_CORE_MESSAGE: the message did not parse correctly, or there were * were other incorrect values. An error should be returned to the CDM
* other incorrect values. An error should be returned to the CDM layer. * layer.
* ODK_UNSUPPORTED_API * @retval ODK_UNSUPPORTED_API
* OEMCrypto_ERROR_INVALID_NONCE * @retval OEMCrypto_ERROR_INVALID_NONCE
* *
* Version: * @version
* This method is new in version 16 of the API. * This method is new in version 16 of the API.
*/ */
OEMCryptoResult ODK_ParseProvisioning( OEMCryptoResult ODK_ParseProvisioning(
@@ -630,8 +598,10 @@ OEMCryptoResult ODK_ParseProvisioning(
const ODK_NonceValues* nonce_values, const uint8_t* device_id, const ODK_NonceValues* nonce_values, const uint8_t* device_id,
size_t device_id_length, ODK_ParsedProvisioning* parsed_response); size_t device_id_length, ODK_ParsedProvisioning* parsed_response);
/// @}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* WIDEVINE_ODK_INCLUDE_ODK_H_ */ #endif // WIDEVINE_ODK_INCLUDE_ODK_H_

View File

@@ -0,0 +1,14 @@
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#ifndef WIDEVINE_ODK_INCLUDE_ODK_ATTRIBUTES_H_
#define WIDEVINE_ODK_INCLUDE_ODK_ATTRIBUTES_H_
#if defined(__GNUC__) || defined(__clang__)
#define UNUSED __attribute__((__unused__))
#else
#define UNUSED
#endif
#endif // WIDEVINE_ODK_INCLUDE_ODK_ATTRIBUTES_H_

View File

@@ -0,0 +1,138 @@
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#ifndef WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_H_
#define WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/*
* ODK_Message is the structure that defines the serialized messages passed
* between the REE and TEE. ODK_Message is an abstract data type that represents
* the concept of a message without disclosing the implementation details. By
* hiding the internal structure, arbitrary modification to the message fields
* by code that is not privy to the message definition can be prevented. By
* restricting message modification it is possible to enforce message validity
* and integrity with a small set of primitives that can be careful reviewed.
* This is important because it allows the assertion to be made that a message's
* fields are internally consistent after every operation. As an example, it
* can be guaranteed that the message status be checked prior to accessing any
* field, and that the status be set to the proper state when any parse error is
* detected. If the message definition was exposed, there could be fundamental
* yet subtle errors in message manipulation anywhere in the code base. It also
* makes development easier since any access to the message structure can be
* tracked through a single point so, for example, it becomes possible to add
* trace statements globally to all message operations by only changing the
* field accessors. Finally it simplies maintentance by localizing changes to
* the message to a few files.
*/
#if defined(__GNUC__) || defined(__clang__)
#define ALIGNED __attribute__((aligned))
#else
#define ALIGNED
#error ODK_Message must be aligned to the maximum useful alignment of the \
machine you are compiling for. Define the ALIGNED macro accordingly.
#endif
typedef struct {
#define SIZE_OF_ODK_MESSAGE_IMPL 64
uint8_t opaque_data[SIZE_OF_ODK_MESSAGE_IMPL];
} ALIGNED ODK_Message;
typedef enum {
MESSAGE_STATUS_OK = 0xe937fcf7,
MESSAGE_STATUS_UNKNOWN_ERROR = 0xe06c1190,
MESSAGE_STATUS_OVERFLOW_ERROR = 0xc43ae4bc,
MESSAGE_STATUS_UNDERFLOW_ERROR = 0x7123cd0b,
MESSAGE_STATUS_PARSE_ERROR = 0x0b9f6189,
MESSAGE_STATUS_NULL_POINTER_ERROR = 0x2d66837a,
MESSAGE_STATUS_API_VALUE_ERROR = 0x6ba34f47,
MESSAGE_STATUS_END_OF_MESSAGE_ERROR = 0x998db72a,
MESSAGE_STATUS_INVALID_ENUM_VALUE = 0xedb88197,
MESSAGE_STATUS_INVALID_TAG_ERROR = 0x14dce06a,
MESSAGE_STATUS_NOT_INITIALIZED = 0x2990b6c6
} ODK_MessageStatus;
/*
* Create a message structure that references a separate data buffer. An
* initialized message is returned. The caller is responsible for ensuring that
* the buffer remains allocated for the lifetime of the message. If |buffer|
* is NULL or |capacity| is zero, the message is invalid and the status
* will be set to MESSAGE_STATUS_NOT_INITIALIZED.
*/
ODK_Message ODK_Message_Create(uint8_t* buffer, size_t capacity);
/*
* Erase the contents of the message, set it to an empty state by setting the
* message size and read offset to 0, effectively erasing the contents of the
* message. The message data buffer pointer remains unchanged, i.e. the message
* retains ownership of the buffer. The message status is reset to
* MESSAGE_STATUS_OK.
*/
void ODK_Message_Clear(ODK_Message* message);
/*
* Reset read pointer to the beginning of the message and clear status
* so that parsing of the message will restart at the beginning of the
* message. The message status is reset to MESSAGE_STATUS_OK.
*/
void ODK_Message_Reset(ODK_Message* message);
/*
* Return a pointer to the message data buffer, i.e. the message payload.
* This is the buffer address that was passed into ODK_Message_Create.
*/
uint8_t* ODK_Message_GetBase(ODK_Message* message);
/*
* Get the maximum number of bytes the message can hold.
*/
size_t ODK_Message_GetCapacity(ODK_Message* message);
/*
* Get the number of bytes currently in the message
*/
size_t ODK_Message_GetSize(ODK_Message* message);
/*
* Get the offset of where the next bytes will be read from the message data
* buffer.
*/
size_t ODK_Message_GetOffset(ODK_Message* message);
/*
* Return the status of the message
*/
ODK_MessageStatus ODK_Message_GetStatus(ODK_Message* message);
/*
* Set the message status to a specific value
*/
void ODK_Message_SetStatus(ODK_Message* message, ODK_MessageStatus status);
/*
* Set the size of the message to a value. This may be needed after writing data
* into the message data buffer.
*/
void ODK_Message_SetSize(ODK_Message* message, size_t size);
/*
* Test if the integrity of a message. This means that the status must be
* MESSAGE_STATUS_OK and that the internal fields of the message are
* within the range of valid values.
*/
bool ODK_Message_IsValid(ODK_Message* message);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_H_

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_ #ifndef WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
#define WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_ #define WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
@@ -12,10 +12,13 @@
/* The version of this library. */ /* The version of this library. */
#define ODK_MAJOR_VERSION 16 #define ODK_MAJOR_VERSION 16
#define ODK_MINOR_VERSION 3 #define ODK_MINOR_VERSION 5
/* ODK Version string. Date changed automatically on each release. */ /* ODK Version string. Date changed automatically on each release. */
#define ODK_RELEASE_DATE "ODK v16.3 2020-07-19" // TODO(b/163416999): Remove the following line when we upgrade to v17.
// The version 16.5 should not be used by any CE CDM release.
#define ODK_RELEASE_DATE "ODK v16.5 (ALCATRAZ ONLY) 2021-01-12"
// #define ODK_RELEASE_DATE "ODK v17.0 2021-01-12"
/* The lowest version number for an ODK message. */ /* The lowest version number for an ODK message. */
#define ODK_FIRST_VERSION 16 #define ODK_FIRST_VERSION 16
@@ -24,10 +27,10 @@
#define ODK_DEVICE_ID_LEN_MAX 64 #define ODK_DEVICE_ID_LEN_MAX 64
#define ODK_SHA256_HASH_SIZE 32 #define ODK_SHA256_HASH_SIZE 32
/* /// @addtogroup odk_timer
* ODK_TimerLimits Structure /// @{
*
* Description: /**
* Timer limits are specified in a license and are used to determine when * Timer limits are specified in a license and are used to determine when
* playback is allowed. See the document "License Duration and Renewal" for a * playback is allowed. See the document "License Duration and Renewal" for a
* discussion on the time restrictions that may be placed on a license. The * discussion on the time restrictions that may be placed on a license. The
@@ -35,30 +38,30 @@
* license message. The fields are set when OEMCrypto calls the function * license message. The fields are set when OEMCrypto calls the function
* ODK_ParseLicense or ODK_InitializeV15Values. * ODK_ParseLicense or ODK_InitializeV15Values.
* *
* Fields: * @param soft_enforce_rental_duration: A boolean controlling the soft or hard
* soft_enforce_rental_duration: A boolean controlling the soft or hard
* enforcement of rental duration. * enforcement of rental duration.
* soft_enforce_playback_duration: A boolean controlling the soft or hard * @param soft_enforce_playback_duration: A boolean controlling the soft or hard
* enforcement of playback duration. * enforcement of playback duration.
* earliest_playback_start_seconds: The earliest time that the first playback * @param earliest_playback_start_seconds: The earliest time that the first
* is allowed. Measured in seconds since the license request was signed. For * playback is allowed. Measured in seconds since the license request was
* most use cases, this is zero. * signed. For most use cases, this is zero.
* rental_duration_seconds: Window of time for the allowed first playback. * @param rental_duration_seconds: Window of time for the allowed first
* Measured in seconds since the earliest playback start. If * playback. Measured in seconds since the earliest playback start. If
* soft_enforce_rental_duration is true, this applies only to the first * soft_enforce_rental_duration is true, this applies only to the first
* playback. If soft_enforce_rental_duration is false, then this restricts * playback. If soft_enforce_rental_duration is false, then this
* any playback. A value of zero means no limit. * restricts any playback. A value of zero means no limit.
* total_playback_duration_seconds: Window of time for allowed playback. * @param total_playback_duration_seconds: Window of time for allowed playback.
* Measured in seconds since the first playback start. If * Measured in seconds since the first playback start. If
* soft_enforce_playback_duration is true, this applies only to the start of * soft_enforce_playback_duration is true, this applies only to the start
* playback for any session. If soft_enforce_playback_duration is false, then * of playback for any session. If soft_enforce_playback_duration is
* this restricts any playback. A value of zero means no limit. * false, then this restricts any playback. A value of zero means no
* initial_renewal_duration_seconds: Window of time for allowed playback. * limit.
* @param initial_renewal_duration_seconds: Window of time for allowed playback.
* Measured in seconds since the first playback start. This value is only * Measured in seconds since the first playback start. This value is only
* used to start the renewal timer. After a renewal message is loaded, the * used to start the renewal timer. After a renewal message is loaded,
* timer will be reset. A value of zero means no limit. * the timer will be reset. A value of zero means no limit.
* *
* Version: * @version
* This struct changed in API version 16.2. * This struct changed in API version 16.2.
*/ */
typedef struct { typedef struct {
@@ -70,10 +73,7 @@ typedef struct {
uint64_t initial_renewal_duration_seconds; uint64_t initial_renewal_duration_seconds;
} ODK_TimerLimits; } ODK_TimerLimits;
/* /**
* ODK_ClockValues Structure
*
* Description:
* Clock values are modified when decryption occurs or when a renewal is * Clock values are modified when decryption occurs or when a renewal is
* processed. They are used to track the current status of the license -- * processed. They are used to track the current status of the license --
* i.e. has playback started? When does the timer expire? See the section * i.e. has playback started? When does the timer expire? See the section
@@ -88,28 +88,28 @@ typedef struct {
* on OEMCrypto's system clock, as described in the document "License * on OEMCrypto's system clock, as described in the document "License
* Duration and Renewal". * Duration and Renewal".
* *
* Fields: * @param time_of_license_signed: Time that the license request was signed,
* time_of_license_signed: Time that the license request was signed, based on * based on OEMCrypto's system clock. This value shall be stored and
* OEMCrypto's system clock. This value shall be stored and reloaded with * reloaded with usage entry as time_of_license_received.
* usage entry as time_of_license_received. * @param time_of_first_decrypt: Time of the first decrypt or call select key,
* time_of_first_decrypt: Time of the first decrypt or call select key, based * based on OEMCrypto's system clock. This is 0 if the license has not
* on OEMCrypto's system clock. This is 0 if the license has not been used to * been used to decrypt any data. This value shall be stored and reloaded
* decrypt any data. This value shall be stored and reloaded with usage entry. * with usage entry.
* time_of_last_decrypt: Time of the most recent decrypt call, based on * @param time_of_last_decrypt: Time of the most recent decrypt call, based on
* OEMCrypto's system clock. This value shall be stored and reloaded with * OEMCrypto's system clock. This value shall be stored and reloaded with
* usage entry. * usage entry.
* time_of_renewal_request: Time of the most recent renewal request, based on * @param time_of_renewal_request: Time of the most recent renewal request,
* OEMCrypto's system clock. This is used to verify that a renewal is not * based on OEMCrypto's system clock. This is used to verify that a
* stale. * renewal is not stale.
* time_when_timer_expires: Time that the current timer expires, based on * @param time_when_timer_expires: Time that the current timer expires, based on
* OEMCrypto's system clock. If the timer is active, this is used by the ODK * OEMCrypto's system clock. If the timer is active, this is used by the
* library to determine if it has expired. * ODK library to determine if it has expired.
* timer_status: Used internally by the ODK library to indicate the current * @param timer_status: Used internally by the ODK library to indicate the
* timer status. * current timer status.
* status: The license or usage entry status. This value shall be stored and * @param status: The license or usage entry status. This value shall be stored
* reloaded with usage entry. * and reloaded with usage entry.
* *
* Version: * @version
* This struct changed in API version 16.2. * This struct changed in API version 16.2.
*/ */
typedef struct { typedef struct {
@@ -122,10 +122,7 @@ typedef struct {
enum OEMCrypto_Usage_Entry_Status status; enum OEMCrypto_Usage_Entry_Status status;
} ODK_ClockValues; } ODK_ClockValues;
/* /**
* ODK_NonceValues Structure
*
* Description:
* Nonce values are used to match a license or provisioning request to a * Nonce values are used to match a license or provisioning request to a
* license or provisioning response. They are also used to match a renewal * license or provisioning response. They are also used to match a renewal
* request and response to a license. For this reason, the api_version might * request and response to a license. For this reason, the api_version might
@@ -137,18 +134,17 @@ typedef struct {
* in the license request and license response, we prevent an attack using * in the license request and license response, we prevent an attack using
* the birthday paradox to generate nonce collisions on a single device. * the birthday paradox to generate nonce collisions on a single device.
* *
* Fields: * @param api_major_version: the API version of the license. This is initialized
* api_major_version: the API version of the license. This is initialized to * to the API version of the ODK library, but may be lower.
* the API version of the ODK library, but may be lower. * @param api_minor_version: the minor version of the ODK library. This is used
* api_minor_version: the minor version of the ODK library. This is used by * by the server to verify that device is not using an obsolete version
* the server to verify that device is not using an obsolete version of the * of the ODK library.
* ODK library. * @param nonce: a randomly generated number used to prevent replay attacks.
* nonce: a randomly generated number used to prevent replay attacks. * @param session_id: the session id of the session which signed the license or
* session_id: the session id of the session which signed the license or
* provisioning request. It is used to prevent replay attacks from one * provisioning request. It is used to prevent replay attacks from one
* session to another. * session to another.
* *
* Version: * @version
* This struct changed in API version 16.2. * This struct changed in API version 16.2.
*/ */
typedef struct { typedef struct {
@@ -158,28 +154,30 @@ typedef struct {
uint32_t session_id; uint32_t session_id;
} ODK_NonceValues; } ODK_NonceValues;
/* /// @}
* ODK_ParsedLicense Structure
* /// @addtogroup odk_parser
* Description: /// @{
/**
* The parsed license structure contains information from the license * The parsed license structure contains information from the license
* message. The function ODK_ParseLicense will fill in the fields of this * message. The function ODK_ParseLicense will fill in the fields of this
* message. All substrings are contained within the message body. * message. All substrings are contained within the message body.
* *
* Fields: * @param enc_mac_keys_iv: IV for decrypting new mac_key. Size is 128 bits.
* enc_mac_keys_iv: IV for decrypting new mac_key. Size is 128 bits. * @param enc_mac_keys: encrypted mac_keys for generating new mac_keys. Size is
* enc_mac_keys: encrypted mac_keys for generating new mac_keys. Size is 512 * 512 bits.
* bits. * @param pst: the Provider Session Token.
* pst: the Provider Session Token. * @param srm_restriction_data: optional data specifying the minimum SRM
* srm_restriction_data: optional data specifying the minimum SRM version. * version.
* license_type: specifies if the license contains content keys or * @param license_type: specifies if the license contains content keys or
* entitlement keys. * entitlement keys.
* nonce_required: indicates if the license requires a nonce. * @param nonce_required: indicates if the license requires a nonce.
* timer_limits: time limits of the for the license. * @param timer_limits: time limits of the for the license.
* key_array_length: number of keys present. * @param key_array_length: number of keys present.
* key_array: set of keys to be installed. * @param key_array: set of keys to be installed.
* *
* Version: * @version
* This struct changed in API version 16.2. * This struct changed in API version 16.2.
*/ */
typedef struct { typedef struct {
@@ -194,21 +192,18 @@ typedef struct {
OEMCrypto_KeyObject key_array[ODK_MAX_NUM_KEYS]; OEMCrypto_KeyObject key_array[ODK_MAX_NUM_KEYS];
} ODK_ParsedLicense; } ODK_ParsedLicense;
/* /**
* ODK_ParsedProvisioning Structure
*
* Description:
* The parsed provisioning structure contains information from the license * The parsed provisioning structure contains information from the license
* message. The function ODK_ParseProvisioning will fill in the fields of * message. The function ODK_ParseProvisioning will fill in the fields of
* this message. All substrings are contained within the message body. * this message. All substrings are contained within the message body.
* *
* Fields: * @param key_type: indicates if this key is an RSA or ECC private key.
* key_type: indicates if this key is an RSA or ECC private key. * @param enc_private_key: encrypted private key for the DRM certificate.
* enc_private_key: encrypted private key for the DRM certificate. * @param enc_private_key_iv: IV for decrypting new private key. Size is 128
* enc_private_key_iv: IV for decrypting new private key. Size is 128 bits. * bits.
* encrypted_message_key: used for provisioning 3.0 to derive keys. * @param encrypted_message_key: used for provisioning 3.0 to derive keys.
* *
* Version: * @version
* This struct changed in API version 16.2. * This struct changed in API version 16.2.
*/ */
typedef struct { typedef struct {
@@ -218,4 +213,6 @@ typedef struct {
OEMCrypto_Substring encrypted_message_key; /* Used for Prov 3.0 */ OEMCrypto_Substring encrypted_message_key; /* Used for Prov 3.0 */
} ODK_ParsedProvisioning; } ODK_ParsedProvisioning;
#endif /* WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_ */ /// @}
#endif // WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_

View File

@@ -1,13 +1,13 @@
/* Copyright 2019 Google LLC. All rights reserved. This file is distributed */ // Copyright 2019 Google LLC. All rights reserved. This file is distributed
/* under the Widevine Master License Agreement. */ // under the Widevine Master License Agreement.
/* Partners are expected to edit this file to support target specific code */ // Partners are expected to edit this file to support target specific code
/* and limits. */ // and limits.
#ifndef WIDEVINE_ODK_INCLUDE_ODK_TARGET_H_ #ifndef WIDEVINE_ODK_INCLUDE_ODK_TARGET_H_
#define WIDEVINE_ODK_INCLUDE_ODK_TARGET_H_ #define WIDEVINE_ODK_INCLUDE_ODK_TARGET_H_
/* Maximum number of keys can be modified to suit target's resource tier. */ // Maximum number of keys can be modified to suit target's resource tier.
#define ODK_MAX_NUM_KEYS 32 #define ODK_MAX_NUM_KEYS 32
#endif /* WIDEVINE_ODK_INCLUDE_ODK_TARGET_H_ */ #endif // WIDEVINE_ODK_INCLUDE_ODK_TARGET_H_

View File

@@ -39,13 +39,11 @@ bool ParseRequest(uint32_t message_type,
reinterpret_cast<const uint8_t*>(oemcrypto_core_message.c_str()); reinterpret_cast<const uint8_t*>(oemcrypto_core_message.c_str());
const size_t buf_length = oemcrypto_core_message.size(); const size_t buf_length = oemcrypto_core_message.size();
Message* msg = nullptr; ODK_Message msg = ODK_Message_Create(const_cast<uint8_t*>(buf), buf_length);
AllocateMessage(&msg, message_block); ODK_Message_SetSize(&msg, buf_length);
InitMessage(msg, const_cast<uint8_t*>(buf), buf_length);
SetSize(msg, buf_length);
unpacker(msg, prepared); unpacker(&msg, prepared);
if (!ValidMessage(msg)) { if (!ODK_Message_IsValid(&msg)) {
return false; return false;
} }
@@ -62,7 +60,7 @@ bool ParseRequest(uint32_t message_type,
} else if (core_request->api_major_version == 16) { } else if (core_request->api_major_version == 16) {
// For version 16, we demand a minor version of at least 2. // For version 16, we demand a minor version of at least 2.
// We accept 16.2, 16.3, or higher. // We accept 16.2, 16.3, or higher.
if (core_request->api_major_version < 2) return false; if (core_request->api_minor_version < 2) return false;
} else { } else {
// Other versions do not (yet) have a restriction on minor number. // Other versions do not (yet) have a restriction on minor number.
// In particular, future versions are accepted for forward compatibility. // In particular, future versions are accepted for forward compatibility.
@@ -70,7 +68,8 @@ bool ParseRequest(uint32_t message_type,
// For v16, a release and a renewal use the same message structure. // For v16, a release and a renewal use the same message structure.
// However, for future API versions, the release might be a separate // However, for future API versions, the release might be a separate
// message. Otherwise, we expect an exact match of message types. // message. Otherwise, we expect an exact match of message types.
if (core_message.message_type != message_type && if (message_type != ODK_Common_Request_Type &&
core_message.message_type != message_type &&
!(message_type == ODK_Renewal_Request_Type && !(message_type == ODK_Renewal_Request_Type &&
core_message.message_type == ODK_Release_Request_Type)) { core_message.message_type == ODK_Release_Request_Type)) {
return false; return false;
@@ -79,7 +78,7 @@ bool ParseRequest(uint32_t message_type,
// than the total message size. We allow the total message size to be larger // than the total message size. We allow the total message size to be larger
// for forward compatibility because future messages might have extra fields // for forward compatibility because future messages might have extra fields
// that we can ignore. // that we can ignore.
if (core_message.message_length < GetOffset(msg)) return false; if (core_message.message_length < ODK_Message_GetOffset(&msg)) return false;
return true; return true;
} }
@@ -129,5 +128,13 @@ bool CoreProvisioningRequestFromMessage(
return true; return true;
} }
bool CoreCommonRequestFromMessage(const std::string& oemcrypto_core_message,
ODK_CommonRequest* common_request) {
const auto unpacker = Unpack_ODK_PreparedCommonRequest;
ODK_PreparedCommonRequest prepared_common = {};
return ParseRequest(ODK_Common_Request_Type, oemcrypto_core_message,
common_request, &prepared_common, unpacker);
}
} // namespace deserialize } // namespace deserialize
} // namespace oemcrypto_core_message } // namespace oemcrypto_core_message

View File

@@ -46,22 +46,23 @@ bool CreateResponse(uint32_t message_type, const S& core_request,
if (core_request.api_major_version > ODK_MAJOR_VERSION) { if (core_request.api_major_version > ODK_MAJOR_VERSION) {
header->nonce_values.api_major_version = ODK_MAJOR_VERSION; header->nonce_values.api_major_version = ODK_MAJOR_VERSION;
header->nonce_values.api_minor_version = ODK_MINOR_VERSION; header->nonce_values.api_minor_version = ODK_MINOR_VERSION;
} else if (core_request.api_major_version == ODK_MAJOR_VERSION &&
core_request.api_minor_version > ODK_MINOR_VERSION) {
header->nonce_values.api_minor_version = ODK_MINOR_VERSION;
} }
static constexpr size_t BUF_CAPACITY = 2048; static constexpr size_t BUF_CAPACITY = 2048;
std::vector<uint8_t> buf(BUF_CAPACITY, 0); std::vector<uint8_t> buf(BUF_CAPACITY, 0);
Message* msg = nullptr; ODK_Message msg = ODK_Message_Create(buf.data(), buf.capacity());
AllocateMessage(&msg, message_block); packer(&msg, &response);
InitMessage(msg, buf.data(), buf.capacity()); if (!ODK_Message_IsValid(&msg)) {
packer(msg, &response);
if (!ValidMessage(msg)) {
return false; return false;
} }
uint32_t message_length = GetSize(msg); uint32_t message_length = ODK_Message_GetSize(&msg);
InitMessage(msg, buf.data() + sizeof(header->message_type), msg = ODK_Message_Create(buf.data() + sizeof(header->message_type),
sizeof(header->message_length)); sizeof(header->message_length));
Pack_uint32_t(msg, &message_length); Pack_uint32_t(&msg, &message_length);
oemcrypto_core_message->assign(reinterpret_cast<const char*>(buf.data()), oemcrypto_core_message->assign(reinterpret_cast<const char*>(buf.data()),
message_length); message_length);
return true; return true;

View File

@@ -41,17 +41,23 @@ OEMCrypto_Substring GetOecSubstring(const std::string& message,
} }
OEMCrypto_KeyObject KeyContainerToOecKey( OEMCrypto_KeyObject KeyContainerToOecKey(
const std::string& proto, const video_widevine::License::KeyContainer& k) { const std::string& proto, const video_widevine::License::KeyContainer& k,
const bool uses_padding) {
OEMCrypto_KeyObject obj = {}; OEMCrypto_KeyObject obj = {};
obj.key_id = GetOecSubstring(proto, k.id()); obj.key_id = GetOecSubstring(proto, k.id());
obj.key_data_iv = GetOecSubstring(proto, k.iv()); obj.key_data_iv = GetOecSubstring(proto, k.iv());
// Strip off PKCS#5 padding - since we know the key is 16 or 32 bytes,
// the padding will always be 16 bytes. OEMCrypto_Substring key_data = GetOecSubstring(proto, k.key());
const std::string& key_data = k.key();
// Strip off PKCS#5 padding. A key can either be 16 of 32 bytes, but that
// makes it hard to know if a key (when 32 bytes) is a 16 byte key with
// padding or a 32 byte key without padding.
if (uses_padding) {
const size_t PKCS5_PADDING_SIZE = 16; const size_t PKCS5_PADDING_SIZE = 16;
obj.key_data = GetOecSubstring( key_data.length -= PKCS5_PADDING_SIZE;
proto, key_data.substr(0, std::max(PKCS5_PADDING_SIZE, key_data.size()) - }
PKCS5_PADDING_SIZE)); obj.key_data = key_data;
if (k.has_key_control()) { if (k.has_key_control()) {
const auto& key_control = k.key_control(); const auto& key_control = k.key_control();
obj.key_control_iv = GetOecSubstring(proto, key_control.iv()); obj.key_control_iv = GetOecSubstring(proto, key_control.iv());
@@ -68,6 +74,7 @@ bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
const ODK_LicenseRequest& core_request, const ODK_LicenseRequest& core_request,
const std::string& core_request_sha256, const std::string& core_request_sha256,
const bool nonce_required, const bool nonce_required,
const bool uses_padding,
std::string* oemcrypto_core_message) { std::string* oemcrypto_core_message) {
video_widevine::License lic; video_widevine::License lic;
if (!lic.ParseFromString(serialized_license)) { if (!lic.ParseFromString(serialized_license)) {
@@ -102,7 +109,8 @@ bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
return false; return false;
} }
uint32_t& n = parsed_lic.key_array_length; uint32_t& n = parsed_lic.key_array_length;
parsed_lic.key_array[n++] = KeyContainerToOecKey(serialized_license, k); parsed_lic.key_array[n++] =
KeyContainerToOecKey(serialized_license, k, uses_padding);
break; break;
} }
default: { default: {

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#include "odk.h" #include "odk.h"
@@ -19,7 +19,7 @@
static OEMCryptoResult ODK_PrepareRequest( static OEMCryptoResult ODK_PrepareRequest(
uint8_t* message, size_t message_length, size_t* core_message_length, uint8_t* message, size_t message_length, size_t* core_message_length,
uint32_t message_type, const ODK_NonceValues* nonce_values, ODK_MessageType message_type, const ODK_NonceValues* nonce_values,
void* prepared_request_buffer, size_t prepared_request_buffer_length) { void* prepared_request_buffer, size_t prepared_request_buffer_length) {
if (nonce_values == NULL || core_message_length == NULL || if (nonce_values == NULL || core_message_length == NULL ||
prepared_request_buffer == NULL || prepared_request_buffer == NULL ||
@@ -27,9 +27,7 @@ static OEMCryptoResult ODK_PrepareRequest(
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
Message* msg = NULL; ODK_Message msg = ODK_Message_Create(message, *core_message_length);
AllocateMessage(&msg, message_block);
InitMessage(msg, message, *core_message_length);
/* The core message should be at the beginning of the buffer, and with a /* The core message should be at the beginning of the buffer, and with a
* shorter length. */ * shorter length. */
@@ -52,7 +50,7 @@ static OEMCryptoResult ODK_PrepareRequest(
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
Pack_ODK_PreparedLicenseRequest( Pack_ODK_PreparedLicenseRequest(
msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer); &msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer);
break; break;
} }
case ODK_Renewal_Request_Type: { case ODK_Renewal_Request_Type: {
@@ -61,7 +59,7 @@ static OEMCryptoResult ODK_PrepareRequest(
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
Pack_ODK_PreparedRenewalRequest( Pack_ODK_PreparedRenewalRequest(
msg, (ODK_PreparedRenewalRequest*)prepared_request_buffer); &msg, (ODK_PreparedRenewalRequest*)prepared_request_buffer);
break; break;
} }
case ODK_Provisioning_Request_Type: { case ODK_Provisioning_Request_Type: {
@@ -71,7 +69,7 @@ static OEMCryptoResult ODK_PrepareRequest(
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
Pack_ODK_PreparedProvisioningRequest( Pack_ODK_PreparedProvisioningRequest(
msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer); &msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
break; break;
} }
default: { default: {
@@ -80,13 +78,13 @@ static OEMCryptoResult ODK_PrepareRequest(
} }
*core_message_length = core_message->message_length; *core_message_length = core_message->message_length;
if (GetStatus(msg) != MESSAGE_STATUS_OK) { if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK) {
/* This is to indicate the caller that the core_message_length has been /* This is to indicate the caller that the core_message_length has been
* appropriately set, but the message buffer is either empty or too small, * appropriately set, but the message buffer is either empty or too small,
* which needs to be initialized and filled in the subsequent call. */ * which needs to be initialized and filled in the subsequent call. */
return OEMCrypto_ERROR_SHORT_BUFFER; return OEMCrypto_ERROR_SHORT_BUFFER;
} }
if (GetSize(msg) != *core_message_length) { if (ODK_Message_GetSize(&msg) != *core_message_length) {
/* This should not happen. Something is wrong. */ /* This should not happen. Something is wrong. */
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
@@ -95,21 +93,18 @@ static OEMCryptoResult ODK_PrepareRequest(
static OEMCryptoResult ODK_ParseResponse( static OEMCryptoResult ODK_ParseResponse(
const uint8_t* message, size_t message_length, size_t core_message_length, const uint8_t* message, size_t message_length, size_t core_message_length,
uint32_t message_type, const ODK_NonceValues* nonce_values, ODK_MessageType message_type, const ODK_NonceValues* nonce_values,
void* response_buffer, uint32_t response_buffer_length) { void* response_buffer, uint32_t response_buffer_length) {
if (message == NULL || response_buffer == NULL || if (message == NULL || response_buffer == NULL ||
core_message_length > message_length) { core_message_length > message_length) {
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
Message* msg = NULL; ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
AllocateMessage(&msg, message_block);
/* We initialize the message buffer with a size of the entire message
* length. */
InitMessage(msg, (uint8_t*)message, message_length);
/* The core message should be at the beginning of the buffer, and with a /* The core message should be at the beginning of the buffer, and with a
* shorter length. The core message is the part we are parsing. */ * shorter length. The core message is the part we are parsing. */
SetSize(msg, core_message_length); ODK_Message_SetSize(&msg, core_message_length);
/* Parse message and unpack it into response buffer. */ /* Parse message and unpack it into response buffer. */
switch (message_type) { switch (message_type) {
@@ -117,14 +112,14 @@ static OEMCryptoResult ODK_ParseResponse(
if (sizeof(ODK_LicenseResponse) > response_buffer_length) { if (sizeof(ODK_LicenseResponse) > response_buffer_length) {
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
Unpack_ODK_LicenseResponse(msg, (ODK_LicenseResponse*)response_buffer); Unpack_ODK_LicenseResponse(&msg, (ODK_LicenseResponse*)response_buffer);
break; break;
} }
case ODK_Renewal_Response_Type: { case ODK_Renewal_Response_Type: {
if (sizeof(ODK_RenewalResponse) > response_buffer_length) { if (sizeof(ODK_RenewalResponse) > response_buffer_length) {
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
Unpack_ODK_RenewalResponse(msg, (ODK_RenewalResponse*)response_buffer); Unpack_ODK_RenewalResponse(&msg, (ODK_RenewalResponse*)response_buffer);
break; break;
} }
case ODK_Provisioning_Response_Type: { case ODK_Provisioning_Response_Type: {
@@ -132,7 +127,7 @@ static OEMCryptoResult ODK_ParseResponse(
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
Unpack_ODK_ProvisioningResponse( Unpack_ODK_ProvisioningResponse(
msg, (ODK_ProvisioningResponse*)response_buffer); &msg, (ODK_ProvisioningResponse*)response_buffer);
break; break;
} }
default: { default: {
@@ -141,9 +136,9 @@ static OEMCryptoResult ODK_ParseResponse(
} }
ODK_CoreMessage* core_message = (ODK_CoreMessage*)response_buffer; ODK_CoreMessage* core_message = (ODK_CoreMessage*)response_buffer;
if (GetStatus(msg) != MESSAGE_STATUS_OK || if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
message_type != core_message->message_type || message_type != core_message->message_type ||
GetOffset(msg) != core_message->message_length) { ODK_Message_GetOffset(&msg) != core_message->message_length) {
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
@@ -168,7 +163,7 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
ODK_PreparedLicenseRequest license_request = { ODK_PreparedLicenseRequest license_request = {
{0}, {0, 0, {}},
}; };
return ODK_PrepareRequest( return ODK_PrepareRequest(
message, message_length, core_message_length, ODK_License_Request_Type, message, message_length, core_message_length, ODK_License_Request_Type,
@@ -197,7 +192,7 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
ODK_PreparedRenewalRequest renewal_request = {{0}, 0}; ODK_PreparedRenewalRequest renewal_request = {{0, 0, {}}, 0};
/* First, we compute the time this request was made relative to the playback /* First, we compute the time this request was made relative to the playback
* clock. */ * clock. */
if (clock_values->time_of_first_decrypt == 0) { if (clock_values->time_of_first_decrypt == 0) {
@@ -231,14 +226,14 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
ODK_PreparedProvisioningRequest provisioning_request = { ODK_PreparedProvisioningRequest provisioning_request = {
{0}, {0, 0, {}},
0, 0,
{0}, {0},
}; };
if (device_id_length > sizeof(provisioning_request.device_id)) { if (device_id_length > sizeof(provisioning_request.device_id)) {
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
provisioning_request.device_id_length = device_id_length; provisioning_request.device_id_length = (uint32_t)device_id_length;
if (device_id) { if (device_id) {
memcpy(provisioning_request.device_id, device_id, device_id_length); memcpy(provisioning_request.device_id, device_id, device_id_length);
} }
@@ -261,7 +256,9 @@ OEMCryptoResult ODK_ParseLicense(
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
ODK_LicenseResponse license_response = {{{0}}, parsed_license, {0}}; ODK_LicenseResponse license_response = {{{0, 0, {}}}, NULL, {0}};
license_response.parsed_license = parsed_license;
const OEMCryptoResult err = ODK_ParseResponse( const OEMCryptoResult err = ODK_ParseResponse(
message, message_length, core_message_length, ODK_License_Response_Type, message, message_length, core_message_length, ODK_License_Response_Type,
NULL, &license_response, sizeof(ODK_LicenseResponse)); NULL, &license_response, sizeof(ODK_LicenseResponse));
@@ -299,21 +296,25 @@ OEMCryptoResult ODK_ParseLicense(
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
if (parsed_license->nonce_required) { /* If this is the first time we load this license, then we verify that the
if (initial_license_load) { * nonce values are the correct, otherwise we copy the nonce values. If the
* nonce values are not required to be correct, then we don't know if this is
* an initial load or not. In that case, we also copy the values so that we
* can use the nonce values later for a renewal.
*/
if (parsed_license->nonce_required && initial_license_load) {
if (nonce_values->nonce != if (nonce_values->nonce !=
license_response.request.core_message.nonce_values.nonce || license_response.request.core_message.nonce_values.nonce ||
nonce_values->session_id != nonce_values->session_id !=
license_response.request.core_message.nonce_values.session_id) { license_response.request.core_message.nonce_values.session_id) {
return OEMCrypto_ERROR_INVALID_NONCE; return OEMCrypto_ERROR_INVALID_NONCE;
} }
} else { /* !initial_license_load */ } else { /* !initial_license_load, or can't tell if initial. */
nonce_values->nonce = nonce_values->nonce =
license_response.request.core_message.nonce_values.nonce; license_response.request.core_message.nonce_values.nonce;
nonce_values->session_id = nonce_values->session_id =
license_response.request.core_message.nonce_values.session_id; license_response.request.core_message.nonce_values.session_id;
} }
}
/* For v16, in order to be backwards compatible with a v15 license server, /* For v16, in order to be backwards compatible with a v15 license server,
* OEMCrypto stores a hash of the core license request and only signs the * OEMCrypto stores a hash of the core license request and only signs the
* message body. Here, when we process the license response, we verify that * message body. Here, when we process the license response, we verify that
@@ -342,7 +343,7 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
} }
ODK_RenewalResponse renewal_response = { ODK_RenewalResponse renewal_response = {
{{0}, 0}, {{0, 0, {}}, 0},
0, 0,
}; };
const OEMCryptoResult err = ODK_ParseResponse( const OEMCryptoResult err = ODK_ParseResponse(
@@ -359,8 +360,11 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
*/ */
/* If a renewal request is lost in transit, we should throw it out and create /* If a renewal request is lost in transit, we should throw it out and create
* a new one. We use the timestamp to make sure we have the latest request. * a new one. We use the timestamp to make sure we have the latest request.
* We only do this if playback has already started. This allows us to reload
* an offline license and also reload a renewal before starting playback.
*/ */
if (clock_values->time_of_renewal_request < if (clock_values->timer_status != ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED &&
clock_values->time_of_renewal_request <
renewal_response.request.playback_time) { renewal_response.request.playback_time) {
return ODK_STALE_RENEWAL; return ODK_STALE_RENEWAL;
} }
@@ -378,8 +382,9 @@ OEMCryptoResult ODK_ParseProvisioning(
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }
ODK_ProvisioningResponse provisioning_response = {{{0}, 0, {0}}, ODK_ProvisioningResponse provisioning_response = {{{0, 0, {}}, 0, {0}}, NULL};
parsed_response}; provisioning_response.parsed_provisioning = parsed_response;
if (device_id_length > ODK_DEVICE_ID_LEN_MAX) { if (device_id_length > ODK_DEVICE_ID_LEN_MAX) {
return ODK_ERROR_CORE_MESSAGE; return ODK_ERROR_CORE_MESSAGE;
} }

View File

@@ -7,6 +7,7 @@
{ {
'sources': [ 'sources': [
'odk.c', 'odk.c',
'odk_message.c',
'odk_overflow.c', 'odk_overflow.c',
'odk_serialize.c', 'odk_serialize.c',
'odk_timer.c', 'odk_timer.c',

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_SRC_ODK_ASSERT_H_ #ifndef WIDEVINE_ODK_SRC_ODK_ASSERT_H_
#define WIDEVINE_ODK_SRC_ODK_ASSERT_H_ #define WIDEVINE_ODK_SRC_ODK_ASSERT_H_
@@ -21,4 +21,4 @@ extern "C" {
} }
#endif #endif
#endif /* WIDEVINE_ODK_SRC_ODK_ASSERT_H_ */ #endif // WIDEVINE_ODK_SRC_ODK_ASSERT_H_

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_SRC_ODK_ENDIAN_H_ #ifndef WIDEVINE_ODK_SRC_ODK_ENDIAN_H_
#define WIDEVINE_ODK_SRC_ODK_ENDIAN_H_ #define WIDEVINE_ODK_SRC_ODK_ENDIAN_H_
@@ -26,4 +26,4 @@ uint64_t oemcrypto_be64toh(uint64_t u64);
} }
#endif #endif
#endif /* WIDEVINE_ODK_SRC_ODK_ENDIAN_H_ */ #endif // WIDEVINE_ODK_SRC_ODK_ENDIAN_H_

View File

@@ -0,0 +1,163 @@
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#include "odk_message.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "odk_message_priv.h"
/*
* C11 defines static_assert in assert.h. If it is available, force a compile
* time error if the abstract ODK_Message struct size does not match its
* implementation. If static_assert is not available, the runtime assert in
* InitMessage will catch the mismatch at the time a message is initialized.
*/
#ifdef static_assert
static_assert(
sizeof(ODK_Message) >= sizeof(ODK_Message_Impl),
"sizeof(ODK_Message) is too small. You can increase "
"SIZE_OF_ODK_MESSAGE_IMPL in odk_message.h to make it large enough.");
#endif
/*
* Create a message structure that references a separate data buffer. An
* initialized message is returned. The caller is responsible for ensuring that
* the buffer remains allocated for the lifetime of the message. If |buffer|
* is NULL or |capacity| is zero, the message is invalid and the status
* will be set to MESSAGE_STATUS_NOT_INITIALIZED.
*/
ODK_Message ODK_Message_Create(uint8_t* buffer, size_t capacity) {
assert(sizeof(ODK_Message) >= sizeof(ODK_Message_Impl));
ODK_Message message;
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)&message;
message_impl->base = buffer;
message_impl->capacity = capacity;
ODK_Message_Clear(&message);
if (buffer == NULL || capacity == 0) {
message_impl->status = MESSAGE_STATUS_NOT_INITIALIZED;
}
return message;
}
/*
* Erase the contents of the message, set it to an empty state by setting the
* message size and read offset to 0, effectively erasing the contents of the
* message. The message data buffer pointer remains unchanged, i.e. the message
* retains ownership of the buffer. The message status is reset to
* MESSAGE_STATUS_OK.
*/
void ODK_Message_Clear(ODK_Message* message) {
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
assert(message_impl != NULL);
ODK_Message_Reset(message);
message_impl->size = 0;
}
/*
* Reset read pointer to the beginning of the message and clear status
* so that parsing of the message will restart at the beginning of the
* message. The message status is reset to MESSAGE_STATUS_OK.
*/
void ODK_Message_Reset(ODK_Message* message) {
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
assert(message_impl != NULL);
message_impl->read_offset = 0;
message_impl->status = MESSAGE_STATUS_OK;
}
/*
* Return a pointer to the message data buffer, i.e. the message payload.
* This is the buffer address that was passed into ODK_Message_Create.
*/
uint8_t* ODK_Message_GetBase(ODK_Message* message) {
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
assert(message_impl != NULL);
return message_impl->base;
}
/*
* Get the maximum number of bytes the message can hold.
*/
size_t ODK_Message_GetCapacity(ODK_Message* message) {
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
assert(message_impl != NULL);
return message_impl->capacity;
}
/*
* Get the number of bytes currently in the message
*/
size_t ODK_Message_GetSize(ODK_Message* message) {
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
assert(message_impl != NULL);
return message_impl->size;
}
/*
* Get the offset of where the next bytes will be read from the message data
* buffer.
*/
size_t ODK_Message_GetOffset(ODK_Message* message) {
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
assert(message_impl != NULL);
return message_impl->read_offset;
}
/*
* Return the status of the message
*/
ODK_MessageStatus ODK_Message_GetStatus(ODK_Message* message) {
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
assert(message_impl != NULL);
return message_impl->status;
}
/*
* Set the message status to a specific value
*/
void ODK_Message_SetStatus(ODK_Message* message, ODK_MessageStatus status) {
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
assert(message_impl != NULL);
message_impl->status = status;
}
/*
* Set the size of the message to a value. This may be needed after writing data
* into the message data buffer.
*/
void ODK_Message_SetSize(ODK_Message* message, size_t size) {
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
assert(message_impl != NULL);
message_impl->size = size;
}
/*
* Test if the integrity of a message. This means that the status must be
* MESSAGE_STATUS_OK and that the base, read_offset, size and capacity of the
* message are within the range of valid values.
*/
bool ODK_Message_IsValid(ODK_Message* message) {
assert(message);
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
if (message_impl == NULL) {
return false;
}
if (message_impl->status != MESSAGE_STATUS_OK) {
return false;
}
if (message_impl->base == NULL) {
message_impl->status = MESSAGE_STATUS_NULL_POINTER_ERROR;
return false;
}
if (message_impl->read_offset > message_impl->capacity ||
message_impl->size > message_impl->capacity ||
message_impl->read_offset > message_impl->size) {
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
return false;
}
return true;
}

View File

@@ -0,0 +1,41 @@
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#ifndef WIDEVINE_ODK_SRC_ODK_MESSAGE_PRIV_H_
#define WIDEVINE_ODK_SRC_ODK_MESSAGE_PRIV_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
* This file must only be included by odk_message.c and serialization_base.c.
*/
#include <stddef.h>
#include <stdint.h>
#include "odk_message.h"
/*
* This is the implementation of a message. This structure is private, i.e. it
* should only be included by files that are allowed to modify the internals of
* a message, that being odk_message.c and serialization_base.c. To ensure
* proper alignment and message size, an ODK_Message_Impl should never be
* allocated directly, instead allocate ODK_Message and cast to ODK_Message_Impl
* because ODK_Message_Impl may be smaller than ODK_Message.
*/
typedef struct {
uint8_t* base;
size_t capacity;
size_t size;
size_t read_offset;
ODK_MessageStatus status;
} ODK_Message_Impl;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WIDEVINE_ODK_SRC_ODK_MESSAGE_PRIV_H_

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_ #ifndef WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_
#define WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_ #define WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_
@@ -20,4 +20,4 @@ int odk_add_overflow_ux(size_t a, size_t b, size_t* c);
} }
#endif #endif
#endif /* WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_ */ #endif // WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
/* /*
* This code is auto-generated, do not edit * This code is auto-generated, do not edit
@@ -13,20 +13,20 @@
/* @@ private serialize */ /* @@ private serialize */
static void Pack_ODK_NonceValues(Message* msg, ODK_NonceValues const* obj) { static void Pack_ODK_NonceValues(ODK_Message* msg, ODK_NonceValues const* obj) {
Pack_uint16_t(msg, &obj->api_minor_version); Pack_uint16_t(msg, &obj->api_minor_version);
Pack_uint16_t(msg, &obj->api_major_version); Pack_uint16_t(msg, &obj->api_major_version);
Pack_uint32_t(msg, &obj->nonce); Pack_uint32_t(msg, &obj->nonce);
Pack_uint32_t(msg, &obj->session_id); Pack_uint32_t(msg, &obj->session_id);
} }
static void Pack_ODK_CoreMessage(Message* msg, ODK_CoreMessage const* obj) { static void Pack_ODK_CoreMessage(ODK_Message* msg, ODK_CoreMessage const* obj) {
Pack_uint32_t(msg, &obj->message_type); Pack_uint32_t(msg, &obj->message_type);
Pack_uint32_t(msg, &obj->message_length); Pack_uint32_t(msg, &obj->message_length);
Pack_ODK_NonceValues(msg, &obj->nonce_values); Pack_ODK_NonceValues(msg, &obj->nonce_values);
} }
static void Pack_OEMCrypto_KeyObject(Message* msg, static void Pack_OEMCrypto_KeyObject(ODK_Message* msg,
OEMCrypto_KeyObject const* obj) { OEMCrypto_KeyObject const* obj) {
Pack_OEMCrypto_Substring(msg, &obj->key_id); Pack_OEMCrypto_Substring(msg, &obj->key_id);
Pack_OEMCrypto_Substring(msg, &obj->key_data_iv); Pack_OEMCrypto_Substring(msg, &obj->key_data_iv);
@@ -35,7 +35,7 @@ static void Pack_OEMCrypto_KeyObject(Message* msg,
Pack_OEMCrypto_Substring(msg, &obj->key_control); Pack_OEMCrypto_Substring(msg, &obj->key_control);
} }
static void Pack_ODK_TimerLimits(Message* msg, ODK_TimerLimits const* obj) { static void Pack_ODK_TimerLimits(ODK_Message* msg, ODK_TimerLimits const* obj) {
Pack_bool(msg, &obj->soft_enforce_rental_duration); Pack_bool(msg, &obj->soft_enforce_rental_duration);
Pack_bool(msg, &obj->soft_enforce_playback_duration); Pack_bool(msg, &obj->soft_enforce_playback_duration);
Pack_uint64_t(msg, &obj->earliest_playback_start_seconds); Pack_uint64_t(msg, &obj->earliest_playback_start_seconds);
@@ -44,10 +44,11 @@ static void Pack_ODK_TimerLimits(Message* msg, ODK_TimerLimits const* obj) {
Pack_uint64_t(msg, &obj->initial_renewal_duration_seconds); Pack_uint64_t(msg, &obj->initial_renewal_duration_seconds);
} }
static void Pack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense const* obj) { static void Pack_ODK_ParsedLicense(ODK_Message* msg,
ODK_ParsedLicense const* obj) {
/* hand-coded */ /* hand-coded */
if (obj->key_array_length > ODK_MAX_NUM_KEYS) { if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR); ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
return; return;
} }
Pack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv); Pack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv);
@@ -64,7 +65,7 @@ static void Pack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense const* obj) {
} }
} }
static void Pack_ODK_ParsedProvisioning(Message* msg, static void Pack_ODK_ParsedProvisioning(ODK_Message* msg,
ODK_ParsedProvisioning const* obj) { ODK_ParsedProvisioning const* obj) {
Pack_enum(msg, obj->key_type); Pack_enum(msg, obj->key_type);
Pack_OEMCrypto_Substring(msg, &obj->enc_private_key); Pack_OEMCrypto_Substring(msg, &obj->enc_private_key);
@@ -74,19 +75,19 @@ static void Pack_ODK_ParsedProvisioning(Message* msg,
/* @@ odk serialize */ /* @@ odk serialize */
void Pack_ODK_PreparedLicenseRequest(Message* msg, void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg,
ODK_PreparedLicenseRequest const* obj) { ODK_PreparedLicenseRequest const* obj) {
Pack_ODK_CoreMessage(msg, &obj->core_message); Pack_ODK_CoreMessage(msg, &obj->core_message);
} }
void Pack_ODK_PreparedRenewalRequest(Message* msg, void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
ODK_PreparedRenewalRequest const* obj) { ODK_PreparedRenewalRequest const* obj) {
Pack_ODK_CoreMessage(msg, &obj->core_message); Pack_ODK_CoreMessage(msg, &obj->core_message);
Pack_uint64_t(msg, &obj->playback_time); Pack_uint64_t(msg, &obj->playback_time);
} }
void Pack_ODK_PreparedProvisioningRequest( void Pack_ODK_PreparedProvisioningRequest(
Message* msg, ODK_PreparedProvisioningRequest const* obj) { ODK_Message* msg, ODK_PreparedProvisioningRequest const* obj) {
Pack_ODK_CoreMessage(msg, &obj->core_message); Pack_ODK_CoreMessage(msg, &obj->core_message);
Pack_uint32_t(msg, &obj->device_id_length); Pack_uint32_t(msg, &obj->device_id_length);
PackArray(msg, &obj->device_id[0], sizeof(obj->device_id)); PackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
@@ -94,18 +95,20 @@ void Pack_ODK_PreparedProvisioningRequest(
/* @@ kdo serialize */ /* @@ kdo serialize */
void Pack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse const* obj) { void Pack_ODK_LicenseResponse(ODK_Message* msg,
ODK_LicenseResponse const* obj) {
Pack_ODK_PreparedLicenseRequest(msg, &obj->request); Pack_ODK_PreparedLicenseRequest(msg, &obj->request);
Pack_ODK_ParsedLicense(msg, (const ODK_ParsedLicense*)obj->parsed_license); Pack_ODK_ParsedLicense(msg, (const ODK_ParsedLicense*)obj->parsed_license);
PackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash)); PackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
} }
void Pack_ODK_RenewalResponse(Message* msg, ODK_RenewalResponse const* obj) { void Pack_ODK_RenewalResponse(ODK_Message* msg,
ODK_RenewalResponse const* obj) {
Pack_ODK_PreparedRenewalRequest(msg, &obj->request); Pack_ODK_PreparedRenewalRequest(msg, &obj->request);
Pack_uint64_t(msg, &obj->renewal_duration_seconds); Pack_uint64_t(msg, &obj->renewal_duration_seconds);
} }
void Pack_ODK_ProvisioningResponse(Message* msg, void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
ODK_ProvisioningResponse const* obj) { ODK_ProvisioningResponse const* obj) {
Pack_ODK_PreparedProvisioningRequest(msg, &obj->request); Pack_ODK_PreparedProvisioningRequest(msg, &obj->request);
Pack_ODK_ParsedProvisioning( Pack_ODK_ParsedProvisioning(
@@ -116,20 +119,21 @@ void Pack_ODK_ProvisioningResponse(Message* msg,
/* @@ private deserialize */ /* @@ private deserialize */
static void Unpack_ODK_NonceValues(Message* msg, ODK_NonceValues* obj) { static void Unpack_ODK_NonceValues(ODK_Message* msg, ODK_NonceValues* obj) {
Unpack_uint16_t(msg, &obj->api_minor_version); Unpack_uint16_t(msg, &obj->api_minor_version);
Unpack_uint16_t(msg, &obj->api_major_version); Unpack_uint16_t(msg, &obj->api_major_version);
Unpack_uint32_t(msg, &obj->nonce); Unpack_uint32_t(msg, &obj->nonce);
Unpack_uint32_t(msg, &obj->session_id); Unpack_uint32_t(msg, &obj->session_id);
} }
static void Unpack_ODK_CoreMessage(Message* msg, ODK_CoreMessage* obj) { static void Unpack_ODK_CoreMessage(ODK_Message* msg, ODK_CoreMessage* obj) {
Unpack_uint32_t(msg, &obj->message_type); Unpack_uint32_t(msg, &obj->message_type);
Unpack_uint32_t(msg, &obj->message_length); Unpack_uint32_t(msg, &obj->message_length);
Unpack_ODK_NonceValues(msg, &obj->nonce_values); Unpack_ODK_NonceValues(msg, &obj->nonce_values);
} }
static void Unpack_OEMCrypto_KeyObject(Message* msg, OEMCrypto_KeyObject* obj) { static void Unpack_OEMCrypto_KeyObject(ODK_Message* msg,
OEMCrypto_KeyObject* obj) {
Unpack_OEMCrypto_Substring(msg, &obj->key_id); Unpack_OEMCrypto_Substring(msg, &obj->key_id);
Unpack_OEMCrypto_Substring(msg, &obj->key_data_iv); Unpack_OEMCrypto_Substring(msg, &obj->key_data_iv);
Unpack_OEMCrypto_Substring(msg, &obj->key_data); Unpack_OEMCrypto_Substring(msg, &obj->key_data);
@@ -137,7 +141,7 @@ static void Unpack_OEMCrypto_KeyObject(Message* msg, OEMCrypto_KeyObject* obj) {
Unpack_OEMCrypto_Substring(msg, &obj->key_control); Unpack_OEMCrypto_Substring(msg, &obj->key_control);
} }
static void Unpack_ODK_TimerLimits(Message* msg, ODK_TimerLimits* obj) { static void Unpack_ODK_TimerLimits(ODK_Message* msg, ODK_TimerLimits* obj) {
Unpack_bool(msg, &obj->soft_enforce_rental_duration); Unpack_bool(msg, &obj->soft_enforce_rental_duration);
Unpack_bool(msg, &obj->soft_enforce_playback_duration); Unpack_bool(msg, &obj->soft_enforce_playback_duration);
Unpack_uint64_t(msg, &obj->earliest_playback_start_seconds); Unpack_uint64_t(msg, &obj->earliest_playback_start_seconds);
@@ -146,7 +150,7 @@ static void Unpack_ODK_TimerLimits(Message* msg, ODK_TimerLimits* obj) {
Unpack_uint64_t(msg, &obj->initial_renewal_duration_seconds); Unpack_uint64_t(msg, &obj->initial_renewal_duration_seconds);
} }
static void Unpack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense* obj) { static void Unpack_ODK_ParsedLicense(ODK_Message* msg, ODK_ParsedLicense* obj) {
Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv); Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv);
Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys); Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys);
Unpack_OEMCrypto_Substring(msg, &obj->pst); Unpack_OEMCrypto_Substring(msg, &obj->pst);
@@ -156,7 +160,7 @@ static void Unpack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense* obj) {
Unpack_ODK_TimerLimits(msg, &obj->timer_limits); Unpack_ODK_TimerLimits(msg, &obj->timer_limits);
Unpack_uint32_t(msg, &obj->key_array_length); Unpack_uint32_t(msg, &obj->key_array_length);
if (obj->key_array_length > ODK_MAX_NUM_KEYS) { if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR); ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
return; return;
} }
uint32_t i; uint32_t i;
@@ -165,7 +169,7 @@ static void Unpack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense* obj) {
} }
} }
static void Unpack_ODK_ParsedProvisioning(Message* msg, static void Unpack_ODK_ParsedProvisioning(ODK_Message* msg,
ODK_ParsedProvisioning* obj) { ODK_ParsedProvisioning* obj) {
obj->key_type = (OEMCrypto_PrivateKeyType)Unpack_enum(msg); obj->key_type = (OEMCrypto_PrivateKeyType)Unpack_enum(msg);
Unpack_OEMCrypto_Substring(msg, &obj->enc_private_key); Unpack_OEMCrypto_Substring(msg, &obj->enc_private_key);
@@ -175,38 +179,42 @@ static void Unpack_ODK_ParsedProvisioning(Message* msg,
/* @ kdo deserialize */ /* @ kdo deserialize */
void Unpack_ODK_PreparedLicenseRequest(Message* msg, void Unpack_ODK_PreparedLicenseRequest(ODK_Message* msg,
ODK_PreparedLicenseRequest* obj) { ODK_PreparedLicenseRequest* obj) {
Unpack_ODK_CoreMessage(msg, &obj->core_message); Unpack_ODK_CoreMessage(msg, &obj->core_message);
} }
void Unpack_ODK_PreparedRenewalRequest(Message* msg, void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
ODK_PreparedRenewalRequest* obj) { ODK_PreparedRenewalRequest* obj) {
Unpack_ODK_CoreMessage(msg, &obj->core_message); Unpack_ODK_CoreMessage(msg, &obj->core_message);
Unpack_uint64_t(msg, &obj->playback_time); Unpack_uint64_t(msg, &obj->playback_time);
} }
void Unpack_ODK_PreparedProvisioningRequest( void Unpack_ODK_PreparedProvisioningRequest(
Message* msg, ODK_PreparedProvisioningRequest* obj) { ODK_Message* msg, ODK_PreparedProvisioningRequest* obj) {
Unpack_ODK_CoreMessage(msg, &obj->core_message); Unpack_ODK_CoreMessage(msg, &obj->core_message);
Unpack_uint32_t(msg, &obj->device_id_length); Unpack_uint32_t(msg, &obj->device_id_length);
UnpackArray(msg, &obj->device_id[0], sizeof(obj->device_id)); UnpackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
} }
void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
ODK_PreparedCommonRequest* obj) {
Unpack_ODK_CoreMessage(msg, &obj->core_message);
}
/* @@ odk deserialize */ /* @@ odk deserialize */
void Unpack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse* obj) { void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj) {
Unpack_ODK_PreparedLicenseRequest(msg, &obj->request); Unpack_ODK_PreparedLicenseRequest(msg, &obj->request);
Unpack_ODK_ParsedLicense(msg, obj->parsed_license); Unpack_ODK_ParsedLicense(msg, obj->parsed_license);
UnpackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash)); UnpackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
} }
void Unpack_ODK_RenewalResponse(Message* msg, ODK_RenewalResponse* obj) { void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj) {
Unpack_ODK_PreparedRenewalRequest(msg, &obj->request); Unpack_ODK_PreparedRenewalRequest(msg, &obj->request);
Unpack_uint64_t(msg, &obj->renewal_duration_seconds); Unpack_uint64_t(msg, &obj->renewal_duration_seconds);
} }
void Unpack_ODK_ProvisioningResponse(Message* msg, void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
ODK_ProvisioningResponse* obj) { ODK_ProvisioningResponse* obj) {
Unpack_ODK_PreparedProvisioningRequest(msg, &obj->request); Unpack_ODK_PreparedProvisioningRequest(msg, &obj->request);
Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning); Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning);

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
/* /*
* This code is auto-generated, do not edit * This code is auto-generated, do not edit
@@ -16,34 +16,37 @@ extern "C" {
#endif #endif
/* odk pack */ /* odk pack */
void Pack_ODK_PreparedLicenseRequest(Message* msg, void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg,
const ODK_PreparedLicenseRequest* obj); const ODK_PreparedLicenseRequest* obj);
void Pack_ODK_PreparedRenewalRequest(Message* msg, void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
const ODK_PreparedRenewalRequest* obj); const ODK_PreparedRenewalRequest* obj);
void Pack_ODK_PreparedProvisioningRequest( void Pack_ODK_PreparedProvisioningRequest(
Message* msg, const ODK_PreparedProvisioningRequest* obj); ODK_Message* msg, const ODK_PreparedProvisioningRequest* obj);
/* odk unpack */ /* odk unpack */
void Unpack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse* obj); void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj);
void Unpack_ODK_RenewalResponse(Message* msg, ODK_RenewalResponse* obj); void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj);
void Unpack_ODK_ProvisioningResponse(Message* msg, void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
ODK_ProvisioningResponse* obj); ODK_ProvisioningResponse* obj);
/* kdo pack */ /* kdo pack */
void Pack_ODK_LicenseResponse(Message* msg, const ODK_LicenseResponse* obj); void Pack_ODK_LicenseResponse(ODK_Message* msg, const ODK_LicenseResponse* obj);
void Pack_ODK_RenewalResponse(Message* msg, const ODK_RenewalResponse* obj); void Pack_ODK_RenewalResponse(ODK_Message* msg, const ODK_RenewalResponse* obj);
void Pack_ODK_ProvisioningResponse(Message* msg, void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
const ODK_ProvisioningResponse* obj); const ODK_ProvisioningResponse* obj);
/* kdo unpack */ /* kdo unpack */
void Unpack_ODK_PreparedLicenseRequest(Message* msg, void Unpack_ODK_PreparedLicenseRequest(ODK_Message* msg,
ODK_PreparedLicenseRequest* obj); ODK_PreparedLicenseRequest* obj);
void Unpack_ODK_PreparedRenewalRequest(Message* msg, void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
ODK_PreparedRenewalRequest* obj); ODK_PreparedRenewalRequest* obj);
void Unpack_ODK_PreparedProvisioningRequest( void Unpack_ODK_PreparedProvisioningRequest(
Message* msg, ODK_PreparedProvisioningRequest* obj); ODK_Message* msg, ODK_PreparedProvisioningRequest* obj);
void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
ODK_PreparedCommonRequest* obj);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } // extern "C"
#endif #endif
#endif /* WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_ */ #endif // WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_ #ifndef WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_
#define WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_ #define WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_
@@ -22,9 +22,11 @@ typedef enum {
ODK_Provisioning_Request_Type = 5, ODK_Provisioning_Request_Type = 5,
ODK_Provisioning_Response_Type = 6, ODK_Provisioning_Response_Type = 6,
/* Reserve future message types to support forward compatibility. */ // Reserve future message types to support forward compatibility.
ODK_Release_Request_Type = 7, ODK_Release_Request_Type = 7,
ODK_Release_Response_Type = 8, ODK_Release_Response_Type = 8,
ODK_Common_Request_Type = 9,
ODK_Common_Response_Type = 10,
} ODK_MessageType; } ODK_MessageType;
typedef struct { typedef struct {
@@ -48,6 +50,10 @@ typedef struct {
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX]; uint8_t device_id[ODK_DEVICE_ID_LEN_MAX];
} ODK_PreparedProvisioningRequest; } ODK_PreparedProvisioningRequest;
typedef struct {
ODK_CoreMessage core_message;
} ODK_PreparedCommonRequest;
typedef struct { typedef struct {
ODK_PreparedLicenseRequest request; ODK_PreparedLicenseRequest request;
ODK_ParsedLicense* parsed_license; ODK_ParsedLicense* parsed_license;
@@ -64,33 +70,32 @@ typedef struct {
ODK_ParsedProvisioning* parsed_provisioning; ODK_ParsedProvisioning* parsed_provisioning;
} ODK_ProvisioningResponse; } ODK_ProvisioningResponse;
/* These are the sum of sizeof of each individual member of the request structs // These are the sum of sizeof of each individual member of the request structs
*/ // without any padding added by the compiler. Make sure they get updated when
/* without any padding added by the compiler. Make sure they get updated when */ // request structs change. Refer to test suite OdkSizeTest in
/* request structs change. Refer to test suite OdkSizeTest in */ // ../test/odk_test.cpp for validations of each of the defined request sizes.
/* ../test/odk_test.cpp for validations of each of the defined request sizes. */
#define ODK_LICENSE_REQUEST_SIZE 20 #define ODK_LICENSE_REQUEST_SIZE 20
#define ODK_RENEWAL_REQUEST_SIZE 28 #define ODK_RENEWAL_REQUEST_SIZE 28
#define ODK_PROVISIONING_REQUEST_SIZE 88 #define ODK_PROVISIONING_REQUEST_SIZE 88
/* These are the possible timer status values. */ // These are the possible timer status values.
#define ODK_CLOCK_TIMER_STATUS_UNDEFINED 0 /* Should not happen. */ #define ODK_CLOCK_TIMER_STATUS_UNDEFINED 0 // Should not happen.
/* When the structure has been initialized, but no license is loaded. */ // When the structure has been initialized, but no license is loaded.
#define ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED 1 #define ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED 1
/* After the license is loaded, before a successful decrypt. */ // After the license is loaded, before a successful decrypt.
#define ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED 2 #define ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED 2
/* After the license is loaded, if a renewal has also been loaded. */ // After the license is loaded, if a renewal has also been loaded.
#define ODK_CLOCK_TIMER_STATUS_RENEWAL_LOADED 3 #define ODK_CLOCK_TIMER_STATUS_RENEWAL_LOADED 3
/* The first decrypt has occurred and the timer is active. */ // The first decrypt has occurred and the timer is active.
#define ODK_CLOCK_TIMER_STATUS_ACTIVE 4 #define ODK_CLOCK_TIMER_STATUS_ACTIVE 4
/* The first decrypt has occurred and the timer is unlimited. */ // The first decrypt has occurred and the timer is unlimited.
#define ODK_CLOCK_TIMER_STATUS_UNLIMITED 5 #define ODK_CLOCK_TIMER_STATUS_UNLIMITED 5
/* The timer has transitioned from active to expired. */ // The timer has transitioned from active to expired.
#define ODK_CLOCK_TIMER_STATUS_EXPIRED 6 #define ODK_CLOCK_TIMER_STATUS_EXPIRED 6
/* The license has been marked as inactive. */ // The license has been marked as inactive.
#define ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE 7 #define ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE 7
/* A helper function for computing timer limits when a renewal is loaded. */ // A helper function for computing timer limits when a renewal is loaded.
OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits, OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values, ODK_ClockValues* clock_values,
uint64_t system_time_seconds, uint64_t system_time_seconds,
@@ -101,4 +106,4 @@ OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
} }
#endif #endif
#endif /* WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_ */ #endif // WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_

View File

@@ -1,11 +1,12 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "odk.h" #include "odk.h"
#include "odk_attributes.h"
#include "odk_overflow.h" #include "odk_overflow.h"
#include "odk_structs_priv.h" #include "odk_structs_priv.h"
@@ -311,7 +312,7 @@ OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
uint64_t time_of_first_decrypt, uint64_t time_of_first_decrypt,
uint64_t time_of_last_decrypt, uint64_t time_of_last_decrypt,
enum OEMCrypto_Usage_Entry_Status status, enum OEMCrypto_Usage_Entry_Status status,
uint64_t system_time_seconds) { uint64_t system_time_seconds UNUSED) {
if (clock_values == NULL) { if (clock_values == NULL) {
return OEMCrypto_ERROR_INVALID_CONTEXT; return OEMCrypto_ERROR_INVALID_CONTEXT;
} }

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#include "odk_util.h" #include "odk_util.h"

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_SRC_ODK_UTIL_H_ #ifndef WIDEVINE_ODK_SRC_ODK_UTIL_H_
#define WIDEVINE_ODK_SRC_ODK_UTIL_H_ #define WIDEVINE_ODK_SRC_ODK_UTIL_H_
@@ -23,6 +23,6 @@ int crypto_memcmp(const void* a, const void* b, size_t len);
bool ODK_NonceValuesEqual(const ODK_NonceValues* a, const ODK_NonceValues* b); bool ODK_NonceValuesEqual(const ODK_NonceValues* a, const ODK_NonceValues* b);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } // extern "C"
#endif #endif
#endif /* WIDEVINE_ODK_SRC_ODK_UTIL_H_ */ #endif // WIDEVINE_ODK_SRC_ODK_UTIL_H_

View File

@@ -1,82 +1,63 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#include "serialization_base.h" #include "serialization_base.h"
#include <assert.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "OEMCryptoCENCCommon.h" #include "OEMCryptoCENCCommon.h"
#include "odk_assert.h" #include "odk_message.h"
#include "odk_message_priv.h"
#include "odk_overflow.h" #include "odk_overflow.h"
struct _Message {
uint8_t* base;
size_t capacity;
size_t size; /* bytes written */
size_t read_offset; /* bytes read */
MessageStatus status;
};
/* TODO(b/150776214): this can be removed once AllocateMessage gets cleaned up
*/
/* /*
* odk_static_assert(SIZE_OF_MESSAGE_STRUCT >= sizeof(struct _Message), * An ODK_Message_Impl pointer must only be obtained by calling GetMessageImpl.
* "SIZE_OF_MESSAGE_STRUCT too small"); * This forces any message to pass the validity check before being operated on,
* which means that no function can modify or access the internals of a message
* without having it be validated first.
*/ */
static ODK_Message_Impl* GetMessageImpl(ODK_Message* message) {
bool ValidMessage(Message* message) { if (!ODK_Message_IsValid(message)) return NULL;
if (message == NULL) { return (ODK_Message_Impl*)message;
return false;
}
if (message->status != MESSAGE_STATUS_OK) {
return false;
}
if (message->base == NULL) {
message->status = MESSAGE_STATUS_NULL_POINTER_ERROR;
return false;
}
if (message->size > message->capacity ||
message->read_offset > message->size) {
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
return false;
}
return true;
} }
static void PackBytes(Message* message, const uint8_t* ptr, size_t count) { static void PackBytes(ODK_Message* message, const uint8_t* ptr, size_t count) {
if (count <= message->capacity - message->size) { ODK_Message_Impl* message_impl = GetMessageImpl(message);
memcpy((void*)(message->base + message->size), (void*)ptr, count); if (!message_impl) return;
message->size += count; if (count <= message_impl->capacity - message_impl->size) {
memcpy((void*)(message_impl->base + message_impl->size), (void*)ptr, count);
message_impl->size += count;
} else { } else {
message->status = MESSAGE_STATUS_OVERFLOW_ERROR; message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
} }
} }
void Pack_enum(Message* message, int value) { void Pack_enum(ODK_Message* message, int value) {
uint32_t v32 = value; uint32_t v32 = value;
Pack_uint32_t(message, &v32); Pack_uint32_t(message, &v32);
} }
void Pack_bool(Message* message, const bool* value) { void Pack_bool(ODK_Message* message, const bool* value) {
if (!ValidMessage(message)) return; assert(value);
uint8_t data[4] = {0}; uint8_t data[4] = {0};
data[3] = *value ? 1 : 0; data[3] = *value ? 1 : 0;
PackBytes(message, data, sizeof(data)); PackBytes(message, data, sizeof(data));
} }
void Pack_uint16_t(Message* message, const uint16_t* value) { void Pack_uint16_t(ODK_Message* message, const uint16_t* value) {
if (!ValidMessage(message)) return; assert(value);
uint8_t data[2] = {0}; uint8_t data[2] = {0};
data[0] = *value >> 8; data[0] = *value >> 8;
data[1] = *value >> 0; data[1] = *value >> 0;
PackBytes(message, data, sizeof(data)); PackBytes(message, data, sizeof(data));
} }
void Pack_uint32_t(Message* message, const uint32_t* value) { void Pack_uint32_t(ODK_Message* message, const uint32_t* value) {
if (!ValidMessage(message)) return; assert(value);
uint8_t data[4] = {0}; uint8_t data[4] = {0};
data[0] = *value >> 24; data[0] = *value >> 24;
data[1] = *value >> 16; data[1] = *value >> 16;
@@ -85,175 +66,112 @@ void Pack_uint32_t(Message* message, const uint32_t* value) {
PackBytes(message, data, sizeof(data)); PackBytes(message, data, sizeof(data));
} }
void Pack_uint64_t(Message* message, const uint64_t* value) { void Pack_uint64_t(ODK_Message* message, const uint64_t* value) {
if (!ValidMessage(message)) return; assert(value);
uint32_t hi = *value >> 32; uint32_t hi = *value >> 32;
uint32_t lo = *value; uint32_t lo = *value;
Pack_uint32_t(message, &hi); Pack_uint32_t(message, &hi);
Pack_uint32_t(message, &lo); Pack_uint32_t(message, &lo);
} }
void PackArray(Message* message, const uint8_t* base, size_t size) { void PackArray(ODK_Message* message, const uint8_t* base, size_t size) {
if (!ValidMessage(message)) return;
PackBytes(message, base, size); PackBytes(message, base, size);
} }
void Pack_OEMCrypto_Substring(Message* msg, const OEMCrypto_Substring* obj) { void Pack_OEMCrypto_Substring(ODK_Message* message,
uint32_t offset = obj->offset; const OEMCrypto_Substring* obj) {
uint32_t length = obj->length; assert(obj);
Pack_uint32_t(msg, &offset); uint32_t offset = (uint32_t)obj->offset;
Pack_uint32_t(msg, &length); uint32_t length = (uint32_t)obj->length;
Pack_uint32_t(message, &offset);
Pack_uint32_t(message, &length);
} }
static void UnpackBytes(Message* message, uint8_t* ptr, size_t count) { static void UnpackBytes(ODK_Message* message, uint8_t* ptr, size_t count) {
if (count <= message->size - message->read_offset) { assert(ptr);
memcpy((void*)ptr, (void*)(message->base + message->read_offset), count); ODK_Message_Impl* message_impl = GetMessageImpl(message);
message->read_offset += count; if (!message_impl) return;
if (count <= message_impl->size - message_impl->read_offset) {
memcpy((void*)ptr, (void*)(message_impl->base + message_impl->read_offset),
count);
message_impl->read_offset += count;
} else { } else {
message->status = MESSAGE_STATUS_UNDERFLOW_ERROR; message_impl->status = MESSAGE_STATUS_UNDERFLOW_ERROR;
} }
} }
int Unpack_enum(Message* message) { int Unpack_enum(ODK_Message* message) {
uint32_t v32; uint32_t v32;
Unpack_uint32_t(message, &v32); Unpack_uint32_t(message, &v32);
return v32; return v32;
} }
void Unpack_bool(Message* message, bool* value) { void Unpack_bool(ODK_Message* message, bool* value) {
if (!ValidMessage(message)) return;
uint8_t data[4] = {0}; uint8_t data[4] = {0};
UnpackBytes(message, data, sizeof(data)); UnpackBytes(message, data, sizeof(data));
assert(value);
*value = (0 != data[3]); *value = (0 != data[3]);
} }
void Unpack_uint16_t(Message* message, uint16_t* value) { void Unpack_uint16_t(ODK_Message* message, uint16_t* value) {
if (!ValidMessage(message)) return; assert(value);
uint8_t data[2] = {0}; uint8_t data[2] = {0};
UnpackBytes(message, data, sizeof(data)); UnpackBytes(message, data, sizeof(data));
*value = data[0]; *value = data[0];
*value = *value << 8 | data[1]; *value = *value << 8 | data[1];
} }
void Unpack_uint32_t(Message* message, uint32_t* value) { void Unpack_uint32_t(ODK_Message* message, uint32_t* value) {
if (!ValidMessage(message)) return; ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
if (!message_impl) return;
uint8_t data[4] = {0}; uint8_t data[4] = {0};
UnpackBytes(message, data, sizeof(data)); UnpackBytes(message, data, sizeof(data));
assert(value);
*value = data[0]; *value = data[0];
*value = *value << 8 | data[1]; *value = *value << 8 | data[1];
*value = *value << 8 | data[2]; *value = *value << 8 | data[2];
*value = *value << 8 | data[3]; *value = *value << 8 | data[3];
} }
void Unpack_uint64_t(Message* message, uint64_t* value) { void Unpack_uint64_t(ODK_Message* message, uint64_t* value) {
if (!ValidMessage(message)) return;
uint32_t hi = 0; uint32_t hi = 0;
uint32_t lo = 0; uint32_t lo = 0;
Unpack_uint32_t(message, &hi); Unpack_uint32_t(message, &hi);
Unpack_uint32_t(message, &lo); Unpack_uint32_t(message, &lo);
assert(value);
*value = hi; *value = hi;
*value = *value << 32 | lo; *value = *value << 32 | lo;
} }
void Unpack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring* obj) { void Unpack_OEMCrypto_Substring(ODK_Message* message,
OEMCrypto_Substring* obj) {
uint32_t offset = 0, length = 0; uint32_t offset = 0, length = 0;
Unpack_uint32_t(msg, &offset); Unpack_uint32_t(message, &offset);
Unpack_uint32_t(msg, &length); Unpack_uint32_t(message, &length);
if (!ValidMessage(msg)) return; ODK_Message_Impl* message_impl = GetMessageImpl(message);
if (!message_impl) return;
/* Each substring should be contained within the message body, which is in the /* Each substring should be contained within the message body, which is in the
* total message, just after the core message. The offset of a substring is * total message, just after the core message. The offset of a substring is
* relative to the message body. So we need to verify: * relative to the message body. So we need to verify:
* 0 < offset and offset + length < message->capacity - message->size * 0 < offset and offset + length < message_impl->capacity -
* or offset + length + message->size < message->capacity * message_impl->size or offset + length + message_impl->size <
* message_impl->capacity
*/ */
size_t substring_end = 0; /* = offset + length; */ size_t substring_end = 0; /* = offset + length; */
size_t end = 0; /* = substring_end + message->size; */ size_t end = 0; /* = substring_end + message_impl->size; */
if (odk_add_overflow_ux(offset, length, &substring_end) || if (odk_add_overflow_ux(offset, length, &substring_end) ||
odk_add_overflow_ux(substring_end, msg->size, &end) || odk_add_overflow_ux(substring_end, message_impl->size, &end) ||
end > msg->capacity) { end > message_impl->capacity) {
msg->status = MESSAGE_STATUS_OVERFLOW_ERROR; message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
return; return;
} }
assert(obj);
obj->offset = offset; obj->offset = offset;
obj->length = length; obj->length = length;
} }
/* copy out */ /* copy out */
void UnpackArray(Message* message, uint8_t* address, size_t size) { void UnpackArray(ODK_Message* message, uint8_t* address, size_t size) {
if (!ValidMessage(message)) return;
UnpackBytes(message, address, size); UnpackBytes(message, address, size);
} }
/*
* The message structure, which is separate from the buffer,
* is initialized to reference the buffer
*/
void InitMessage(Message* message, uint8_t* buffer, size_t capacity) {
if (message == NULL) return;
memset(message, 0, sizeof(Message));
message->base = buffer;
message->capacity = capacity;
message->size = 0;
message->read_offset = 0;
message->status = MESSAGE_STATUS_OK;
}
/*
* The message structure is in the first sizeof(Memory) bytes
* of the buffer
*/
Message* CreateMessage(uint8_t* buffer, size_t buffer_size) {
if (buffer == NULL || buffer_size < sizeof(Message)) return NULL;
Message* message = (Message*)buffer;
message->base = buffer + sizeof(Message);
message->capacity = buffer_size - sizeof(Message);
message->size = 0;
message->read_offset = 0;
message->status = MESSAGE_STATUS_OK;
return message;
}
/*
* Set the message to an empty state
*/
void ResetMessage(Message* message) {
message->size = 0;
message->read_offset = 0;
message->status = MESSAGE_STATUS_OK;
}
uint8_t* GetBase(Message* message) {
if (message == NULL) return NULL;
return message->base;
}
size_t GetCapacity(Message* message) {
if (message == NULL) return 0;
return message->capacity;
}
size_t GetSize(Message* message) {
if (message == NULL) return 0;
return message->size;
}
void SetSize(Message* message, size_t size) {
if (message == NULL) return;
if (size > message->capacity)
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
else
message->size = size;
}
MessageStatus GetStatus(Message* message) { return message->status; }
void SetStatus(Message* message, MessageStatus status) {
message->status = status;
}
size_t GetOffset(Message* message) {
if (message == NULL) return 0;
return message->read_offset;
}
size_t SizeOfMessageStruct() { return sizeof(Message); }

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_ #ifndef WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
#define WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_ #define WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
@@ -13,84 +13,28 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#include "OEMCryptoCENCCommon.h" #include "OEMCryptoCENCCommon.h"
#include "odk_message.h"
#define SIZE_OF_MESSAGE_STRUCT 64 void Pack_enum(ODK_Message* message, int value);
void Pack_bool(ODK_Message* message, const bool* value);
void Pack_uint16_t(ODK_Message* message, const uint16_t* value);
void Pack_uint32_t(ODK_Message* message, const uint32_t* value);
void Pack_uint64_t(ODK_Message* message, const uint64_t* value);
void PackArray(ODK_Message* message, const uint8_t* base, size_t size);
void Pack_OEMCrypto_Substring(ODK_Message* message,
const OEMCrypto_Substring* obj);
/* int Unpack_enum(ODK_Message* message);
* Description: void Unpack_bool(ODK_Message* message, bool* value);
* Point |msg| to stack-array |blk|. void Unpack_uint16_t(ODK_Message* message, uint16_t* value);
* |blk| is guaranteed large enough to hold a |Message| struct. void Unpack_uint32_t(ODK_Message* message, uint32_t* value);
* |blk| cannot be used in the same scope as a variable name. void Unpack_uint64_t(ODK_Message* message, uint64_t* value);
* |msg| points to valid memory in the same scope |AllocateMessage| is used. void UnpackArray(ODK_Message* message, uint8_t* address,
* Parameters:
* msg: pointer to pointer to |Message| struct
* blk: variable name for stack-array
*/
#define AllocateMessage(msg, blk) \
uint8_t blk[SIZE_OF_MESSAGE_STRUCT]; \
*(msg) = (Message*)(blk)
typedef struct _Message Message;
typedef enum {
MESSAGE_STATUS_OK,
MESSAGE_STATUS_UNKNOWN_ERROR,
MESSAGE_STATUS_OVERFLOW_ERROR,
MESSAGE_STATUS_UNDERFLOW_ERROR,
MESSAGE_STATUS_PARSE_ERROR,
MESSAGE_STATUS_NULL_POINTER_ERROR,
MESSAGE_STATUS_API_VALUE_ERROR
} MessageStatus;
bool ValidMessage(Message* message);
void Pack_enum(Message* message, int value);
void Pack_bool(Message* message, const bool* value);
void Pack_uint16_t(Message* message, const uint16_t* value);
void Pack_uint32_t(Message* message, const uint32_t* value);
void Pack_uint64_t(Message* message, const uint64_t* value);
void PackArray(Message* message, const uint8_t* base, size_t size);
void Pack_OEMCrypto_Substring(Message* msg, const OEMCrypto_Substring* obj);
int Unpack_enum(Message* message);
void Unpack_bool(Message* message, bool* value);
void Unpack_uint16_t(Message* message, uint16_t* value);
void Unpack_uint32_t(Message* message, uint32_t* value);
void Unpack_uint64_t(Message* message, uint64_t* value);
void UnpackArray(Message* message, uint8_t* address,
size_t size); /* copy out */ size_t size); /* copy out */
void Unpack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring* obj); void Unpack_OEMCrypto_Substring(ODK_Message* message, OEMCrypto_Substring* obj);
/*
* Create a message from a buffer. The message structure consumes the first
* sizeof(Message) bytes of the buffer. The caller is responsible for ensuring
* that the buffer remains allocated for the lifetime of the message.
*/
Message* CreateMessage(uint8_t* buffer, size_t buffer_size);
/*
* Initialize a message structure to reference a separate buffer. The caller
* is responsible for ensuring that the buffer remains allocated for the
* lifetime of the message.
*/
void InitMessage(Message* message, uint8_t* buffer, size_t capacity);
/*
* Reset an existing the message to an empty state
*/
void ResetMessage(Message* message);
uint8_t* GetBase(Message* message);
size_t GetCapacity(Message* message);
size_t GetSize(Message* message);
void SetSize(Message* message, size_t size);
MessageStatus GetStatus(Message* message);
void SetStatus(Message* message, MessageStatus status);
size_t GetOffset(Message* message);
size_t SizeOfMessageStruct();
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } // extern "C"
#endif #endif
#endif /* WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_ */ #endif // WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_

View File

@@ -1,8 +1,8 @@
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2020 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
/* We must define this macro to get RTLD_NEXT definition from <dlfcn.h> */ // We must define this macro to get RTLD_NEXT definition from <dlfcn.h>
#define _GNU_SOURCE #define _GNU_SOURCE
#include <dlfcn.h> #include <dlfcn.h>
@@ -21,7 +21,7 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
message, message_length, core_message_length, nonce_values); message, message_length, core_message_length, nonce_values);
char* file_name = GetFileName("license_request_corpus"); char* file_name = GetFileName("license_request_corpus");
/* License Request format expected by fuzzer - [Core License Request] */ // License Request format expected by fuzzer - [Core License Request]
AppendToFile(file_name, (const char*)message, *core_message_length); AppendToFile(file_name, (const char*)message, *core_message_length);
free(file_name); free(file_name);
return oem_crypto_result; return oem_crypto_result;
@@ -50,9 +50,8 @@ OEMCryptoResult ODK_ParseLicense(
nonce_values, parsed_license); nonce_values, parsed_license);
char* file_name = GetFileName("license_response_corpus"); char* file_name = GetFileName("license_response_corpus");
/* License Response format expected by fuzzer - [ODK_ParseLicense_Args][Core // License Response format expected by fuzzer - [ODK_ParseLicense_Args][Core
*/ // License Response]
/* License Response] */
AppendToFile(file_name, (const char*)&parse_license_args, AppendToFile(file_name, (const char*)&parse_license_args,
sizeof(struct ODK_ParseLicense_Args)); sizeof(struct ODK_ParseLicense_Args));
AppendToFile(file_name, (const char*)message, core_message_length); AppendToFile(file_name, (const char*)message, core_message_length);
@@ -74,8 +73,8 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
nonce_values, clock_values, system_time_seconds); nonce_values, clock_values, system_time_seconds);
char* file_name = GetFileName("renewal_request_corpus"); char* file_name = GetFileName("renewal_request_corpus");
/* License Request format expected by fuzzer - [ODK_ClockValues][Core */ // License Request format expected by fuzzer - [ODK_ClockValues][Core
/* License Request] */ // License Request]
AppendToFile(file_name, (const char*)clock_values, sizeof(ODK_ClockValues)); AppendToFile(file_name, (const char*)clock_values, sizeof(ODK_ClockValues));
AppendToFile(file_name, (const char*)message, *core_message_size); AppendToFile(file_name, (const char*)message, *core_message_size);
free(file_name); free(file_name);
@@ -103,9 +102,8 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
timer_limits, clock_values, timer_value); timer_limits, clock_values, timer_value);
char* file_name = GetFileName("renewal_response_corpus"); char* file_name = GetFileName("renewal_response_corpus");
/* Renewal Response format expected by fuzzer - [ODK_ParseRenewal_Args][Core // Renewal Response format expected by fuzzer - [ODK_ParseRenewal_Args][Core
*/ // Renewal Response]
/* Renewal Response] */
AppendToFile(file_name, (const char*)&parse_renewal_args, AppendToFile(file_name, (const char*)&parse_renewal_args,
sizeof(struct ODK_ParseRenewal_Args)); sizeof(struct ODK_ParseRenewal_Args));
AppendToFile(file_name, (const char*)message, core_message_length); AppendToFile(file_name, (const char*)message, core_message_length);
@@ -126,8 +124,8 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
nonce_values, device_id, device_id_length); nonce_values, device_id, device_id_length);
char* file_name = GetFileName("provisioning_request_corpus"); char* file_name = GetFileName("provisioning_request_corpus");
/* Provisioning Request format expected by fuzzer - [Core Provisioning */ // Provisioning Request format expected by fuzzer - [Core Provisioning
/* Request] */ // Request]
AppendToFile(file_name, (const char*)message, *core_message_length); AppendToFile(file_name, (const char*)message, *core_message_length);
free(file_name); free(file_name);
return oem_crypto_result; return oem_crypto_result;
@@ -150,8 +148,8 @@ OEMCryptoResult ODK_ParseProvisioning(
device_id_length, parsed_response); device_id_length, parsed_response);
char* file_name = GetFileName("provisioning_response_corpus"); char* file_name = GetFileName("provisioning_response_corpus");
/* Provisioning Response format expected by fuzzer - */ // Provisioning Response format expected by fuzzer -
/* [ODK_ParseProvisioning_Args][Core Provisioning Response] */ // [ODK_ParseProvisioning_Args][Core Provisioning Response]
AppendToFile(file_name, (const char*)&parse_provisioning_args, AppendToFile(file_name, (const char*)&parse_provisioning_args,
sizeof(struct ODK_ParseProvisioning_Args)); sizeof(struct ODK_ParseProvisioning_Args));
AppendToFile(file_name, (const char*)message, core_message_length); AppendToFile(file_name, (const char*)message, core_message_length);

View File

@@ -1,6 +1,6 @@
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2020 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#include "fuzzing/corpus_generator/odk_corpus_generator_helper.h" #include "fuzzing/corpus_generator/odk_corpus_generator_helper.h"
void AppendToFile(const char* file_name, const char* message, void AppendToFile(const char* file_name, const char* message,

View File

@@ -1,6 +1,6 @@
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2020 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_ #ifndef WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_
#define WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_ #define WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_
@@ -15,5 +15,4 @@ void AppendToFile(const char* file_name, const char* message,
char* GetFileName(const char* directory); char* GetFileName(const char* directory);
#endif /* WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_ \ #endif // WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_
*/

View File

@@ -28,13 +28,13 @@ void ConvertDataToValidBools(ODK_ParsedLicense* t) {
&t->timer_limits.soft_enforce_rental_duration); &t->timer_limits.soft_enforce_rental_duration);
} }
void ConvertDataToValidBools(ODK_PreparedRenewalRequest* t) {} void ConvertDataToValidBools(ODK_PreparedRenewalRequest* t UNUSED) {}
void ConvertDataToValidBools(ODK_ParsedProvisioning* t) {} void ConvertDataToValidBools(ODK_ParsedProvisioning* t UNUSED) {}
OEMCryptoResult odk_serialize_LicenseRequest( OEMCryptoResult odk_serialize_LicenseRequest(
const void* in, uint8_t* out, size_t* size, const void* in UNUSED, uint8_t* out, size_t* size,
const ODK_LicenseRequest& core_license_request, const ODK_LicenseRequest& core_license_request UNUSED,
const ODK_NonceValues* nonce_values) { const ODK_NonceValues* nonce_values) {
return ODK_PrepareCoreLicenseRequest(out, SIZE_MAX, size, nonce_values); return ODK_PrepareCoreLicenseRequest(out, SIZE_MAX, size, nonce_values);
} }
@@ -50,7 +50,7 @@ OEMCryptoResult odk_serialize_RenewalRequest(
} }
OEMCryptoResult odk_serialize_ProvisioningRequest( OEMCryptoResult odk_serialize_ProvisioningRequest(
const void* in, uint8_t* out, size_t* size, const void* in UNUSED, uint8_t* out, size_t* size,
const ODK_ProvisioningRequest& core_provisioning, const ODK_ProvisioningRequest& core_provisioning,
const ODK_NonceValues* nonce_values) { const ODK_NonceValues* nonce_values) {
const std::string& device_id = core_provisioning.device_id; const std::string& device_id = core_provisioning.device_id;
@@ -99,11 +99,9 @@ OEMCryptoResult odk_deserialize_RenewalResponse(
// odk_kdo method, we call Unpack_ODK_PreparedRenewalRequest private method. // odk_kdo method, we call Unpack_ODK_PreparedRenewalRequest private method.
// playback_time cannot be captured from publicly exposed API // playback_time cannot be captured from publicly exposed API
// ODK_ParseRenewal. // ODK_ParseRenewal.
Message* msg = nullptr; ODK_Message msg = ODK_Message_Create(const_cast<uint8_t*>(buf), len);
AllocateMessage(&msg, message_block); ODK_Message_SetSize(&msg, len);
InitMessage(msg, const_cast<uint8_t*>(buf), len); Unpack_ODK_PreparedRenewalRequest(&msg, renewal_msg);
SetSize(msg, len);
Unpack_ODK_PreparedRenewalRequest(msg, renewal_msg);
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }

View File

@@ -1,6 +1,6 @@
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2020 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_ #ifndef WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_
#define WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_ #define WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_
@@ -9,6 +9,7 @@
#include "core_message_serialize.h" #include "core_message_serialize.h"
#include "fuzzing/odk_fuzz_structs.h" #include "fuzzing/odk_fuzz_structs.h"
#include "odk_attributes.h"
#include "odk_serialize.h" #include "odk_serialize.h"
namespace oemcrypto_core_message { namespace oemcrypto_core_message {
@@ -56,24 +57,23 @@ bool kdo_serialize_ProvisioningResponse(
const ODK_ParsedProvisioning& parsed_prov, const ODK_ParsedProvisioning& parsed_prov,
std::string* oemcrypto_core_message); std::string* oemcrypto_core_message);
/* Idea behind having three different functions is: */ // Idea behind having three different functions is:
/* Only ODK_ParseLicense structure had fields which needed additional */ // Only ODK_ParseLicense structure had fields which needed additional
/* procession. Having a single function with templated parameter T was */ // procession. Having a single function with templated parameter T was
/* failing during compile time because other two structures doesn't have */ // failing during compile time because other two structures doesn't have
/* fields that need additional processing. Hence to reduce code redundance and // fields that need additional processing. Hence to reduce code redundance and
*/ // make us of common FuzzerMutateResponse across three response fuzzers,
/* make us of common FuzzerMutateResponse across three response fuzzers, */ // three independent functions were defined and renewal and provisioning
/* three independent functions were defined and renewal and provisioning */ // functions would be empty as no additional processing is needed for them.
/* functions would be empty as no additional processing is needed for them. */
void ConvertDataToValidBools(ODK_ParsedLicense* t); void ConvertDataToValidBools(ODK_ParsedLicense* t);
void ConvertDataToValidBools(ODK_PreparedRenewalRequest* t); void ConvertDataToValidBools(ODK_PreparedRenewalRequest* t);
void ConvertDataToValidBools(ODK_ParsedProvisioning* t); void ConvertDataToValidBools(ODK_ParsedProvisioning* t);
/* Forward-declare the libFuzzer's mutator callback. Mark it weak so that */ // Forward-declare the libFuzzer's mutator callback. Mark it weak so that
/* the program links successfully even outside of --config=asan-fuzzer */ // the program links successfully even outside of --config=asan-fuzzer
/* (apparently the only config in which LLVM uses our custom mutator). */ // (apparently the only config in which LLVM uses our custom mutator).
extern "C" size_t LLVMFuzzerMutate(uint8_t* Data, size_t Size, size_t MaxSize) extern "C" size_t LLVMFuzzerMutate(uint8_t* Data, size_t Size, size_t MaxSize)
__attribute__((weak)); __attribute__((weak));
@@ -85,8 +85,8 @@ size_t FuzzerMutateResponse(uint8_t* data, size_t size, size_t max_size,
const size_t kCoreResponseSize = sizeof(T); const size_t kCoreResponseSize = sizeof(T);
const size_t kTotalResponseSize = kArgsSize + kCoreResponseSize; const size_t kTotalResponseSize = kArgsSize + kCoreResponseSize;
/* Deserializing data in order to make sure it deserializes properly. */ // Deserializing data in order to make sure it deserializes properly.
/* Input byte array format: [function arguments][data to parse]. */ // Input byte array format: [function arguments][data to parse].
std::shared_ptr<A> _args(new A()); std::shared_ptr<A> _args(new A());
A* args = _args.get(); A* args = _args.get();
memcpy(args, data, kArgsSize); memcpy(args, data, kArgsSize);
@@ -97,17 +97,16 @@ size_t FuzzerMutateResponse(uint8_t* data, size_t size, size_t max_size,
OEMCryptoResult result = OEMCryptoResult result =
odk_deserialize_fun(buf, size - kArgsSize, args, &nonce_values, &t); odk_deserialize_fun(buf, size - kArgsSize, args, &nonce_values, &t);
/* If data doesn't deserialize successfully, We copy random bytes into */ // If data doesn't deserialize successfully, We copy random bytes into
/* T and serialize using kdo function */ // T and serialize using kdo function
/* which will create a valid oemcrypto core message using */ // which will create a valid oemcrypto core message using
/* nonce and request hash from function args. OEMCrypto core message acts as // nonce and request hash from function args. OEMCrypto core message acts as
*/ // input to odk_kdo.
/* input to odk_kdo. */
if (result != OEMCrypto_SUCCESS) { if (result != OEMCrypto_SUCCESS) {
if (max_size < kTotalResponseSize) { if (max_size < kTotalResponseSize) {
return 0; return 0;
} }
/* Initialize remaining bytes needed in data to zero. */ // Initialize remaining bytes needed in data to zero.
if (size < kTotalResponseSize) { if (size < kTotalResponseSize) {
memset(data + size, 0, kTotalResponseSize - size); memset(data + size, 0, kTotalResponseSize - size);
} }
@@ -115,24 +114,24 @@ size_t FuzzerMutateResponse(uint8_t* data, size_t size, size_t max_size,
memcpy(&t, buf, kCoreResponseSize); memcpy(&t, buf, kCoreResponseSize);
} }
/* Ask LLVM to run its usual mutations, hopefully giving us interesting */ // Ask LLVM to run its usual mutations, hopefully giving us interesting
/* inputs. We copy deserialized data into pointer data, run mutations */ // inputs. We copy deserialized data into pointer data, run mutations
/* and copy back the mutated data to args and t */ // and copy back the mutated data to args and t
memcpy(data + kArgsSize, &t, kCoreResponseSize); memcpy(data + kArgsSize, &t, kCoreResponseSize);
LLVMFuzzerMutate(data, kTotalResponseSize, kTotalResponseSize); LLVMFuzzerMutate(data, kTotalResponseSize, kTotalResponseSize);
memcpy(args, data, kArgsSize); memcpy(args, data, kArgsSize);
memcpy(&t, data + kArgsSize, kCoreResponseSize); memcpy(&t, data + kArgsSize, kCoreResponseSize);
/* Convert boolean flags in parsed message to valid bytes to */ // Convert boolean flags in parsed message to valid bytes to
/* avoid errors from msan. Only needed for parsed license. */ // avoid errors from msan. Only needed for parsed license.
ConvertDataToValidBools(&t); ConvertDataToValidBools(&t);
/* Serialize the data after mutation. */ // Serialize the data after mutation.
std::string oemcrypto_core_message; std::string oemcrypto_core_message;
if (!kdo_serialize_fun(args, t, &oemcrypto_core_message)) { if (!kdo_serialize_fun(args, t, &oemcrypto_core_message)) {
return 0; return 0;
} }
/* Copy mutated and serialized oemcrypto_core_message to data */ // Copy mutated and serialized oemcrypto_core_message to data
/* so that it acts as input to odk_kdo function. */ // so that it acts as input to odk_kdo function.
memcpy(data + kArgsSize, oemcrypto_core_message.data(), memcpy(data + kArgsSize, oemcrypto_core_message.data(),
oemcrypto_core_message.size()); oemcrypto_core_message.size());
return kArgsSize + oemcrypto_core_message.size(); return kArgsSize + oemcrypto_core_message.size();
@@ -149,9 +148,9 @@ size_t FuzzerMutateResponse(uint8_t* data, size_t size, size_t max_size,
*/ */
template <typename A, typename T, typename F, typename G> template <typename A, typename T, typename F, typename G>
void odk_kdo(const F& odk_fun, const G& kdo_fun, const uint8_t* in, void odk_kdo(const F& odk_fun, const G& kdo_fun, const uint8_t* in,
const size_t size, const size_t args_size, uint8_t* out) { const size_t size, const size_t args_size, uint8_t* out UNUSED) {
T t = {}; T t = {};
/* Input byte array format: [function arguments][data to parse] */ // Input byte array format: [function arguments][data to parse]
if (size < args_size) { if (size < args_size) {
return; return;
} }
@@ -187,8 +186,8 @@ static void kdo_odk(const F& kdo_fun, const G& odk_fun, const uint8_t* in,
if (size <= clock_value_size) { if (size <= clock_value_size) {
return; return;
} }
/* Input byte array format: [Clock Values][data to parse]. */ // Input byte array format: [Clock Values][data to parse].
/* Only Renewal Request expects clock values to be present. */ // Only Renewal Request expects clock values to be present.
std::string input(reinterpret_cast<const char*>(in) + clock_value_size, std::string input(reinterpret_cast<const char*>(in) + clock_value_size,
size - clock_value_size); size - clock_value_size);
T t = {}; T t = {};
@@ -202,5 +201,5 @@ static void kdo_odk(const F& kdo_fun, const G& odk_fun, const uint8_t* in,
return; return;
} }
} }
} /* namespace oemcrypto_core_message */ } // namespace oemcrypto_core_message
#endif /* WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_ */ #endif // WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_

View File

@@ -1,6 +1,6 @@
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2020 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_ #ifndef WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_
#define WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_ #define WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_
@@ -25,4 +25,4 @@ struct ODK_ParseProvisioning_Args {
size_t device_id_length; size_t device_id_length;
uint8_t device_id[64]; uint8_t device_id[64];
}; };
#endif /* WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_ */ #endif // WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_

View File

@@ -12,7 +12,8 @@ namespace oemcrypto_core_message {
// The custom mutator: Ensure that each input can be deserialized properly // The custom mutator: Ensure that each input can be deserialized properly
// by ODK function after mutation. // by ODK function after mutation.
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size, extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
size_t max_size, unsigned int seed) { size_t max_size,
unsigned int seed UNUSED) {
const size_t kLicenseResponseArgsSize = sizeof(ODK_ParseLicense_Args); const size_t kLicenseResponseArgsSize = sizeof(ODK_ParseLicense_Args);
if (size < kLicenseResponseArgsSize) { if (size < kLicenseResponseArgsSize) {
return 0; return 0;

View File

@@ -35,6 +35,16 @@ using oemcrypto_core_message::serialize::CreateCoreRenewalResponse;
constexpr uint32_t kExtraPayloadSize = 128u; constexpr uint32_t kExtraPayloadSize = 128u;
/* Used to parameterize tests by version number. The request is given one
* version number, and we will expect the response to have another version
* number. */
struct VersionParameters {
uint16_t request_major_version;
uint16_t request_minor_version;
uint16_t response_major_version;
uint16_t response_minor_version;
};
template <typename T, typename F, typename G> template <typename T, typename F, typename G>
void ValidateRequest(uint32_t message_type, void ValidateRequest(uint32_t message_type,
const std::vector<ODK_Field>& extra_fields, const std::vector<ODK_Field>& extra_fields,
@@ -113,12 +123,13 @@ void ValidateRequest(uint32_t message_type,
* G: kdo serializer * G: kdo serializer
*/ */
template <typename T, typename F, typename G> template <typename T, typename F, typename G>
void ValidateResponse(ODK_CoreMessage* core_message, void ValidateResponse(const VersionParameters& versions,
ODK_CoreMessage* core_message,
const std::vector<ODK_Field>& extra_fields, const std::vector<ODK_Field>& extra_fields,
const F& odk_parse_func, const G& kdo_prepare_func) { const F& odk_parse_func, const G& kdo_prepare_func) {
T t = {}; T t = {};
t.api_minor_version = core_message->nonce_values.api_minor_version; t.api_major_version = versions.request_major_version;
t.api_major_version = core_message->nonce_values.api_major_version; t.api_minor_version = versions.request_minor_version;
t.nonce = core_message->nonce_values.nonce; t.nonce = core_message->nonce_values.nonce;
t.session_id = core_message->nonce_values.session_id; t.session_id = core_message->nonce_values.session_id;
@@ -132,7 +143,7 @@ void ValidateResponse(ODK_CoreMessage* core_message,
EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_READ, zero, buf_size, EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_READ, zero, buf_size,
&bytes_read, extra_fields)); &bytes_read, extra_fields));
// parse buf with odk // Parse buf with odk
EXPECT_EQ(OEMCrypto_SUCCESS, odk_parse_func(buf, buf_size)); EXPECT_EQ(OEMCrypto_SUCCESS, odk_parse_func(buf, buf_size));
size_t size_out = 0; size_t size_out = 0;
@@ -209,8 +220,10 @@ TEST(OdkTest, SerializeFieldsStress) {
TEST(OdkTest, NullRequestTest) { TEST(OdkTest, NullRequestTest) {
size_t core_message_length = 0; size_t core_message_length = 0;
ODK_NonceValues nonce_values{0}; ODK_NonceValues nonce_values;
ODK_ClockValues clock_values{0}; memset(&nonce_values, 0, sizeof(nonce_values));
ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
// Assert that nullptr does not cause a core dump. // Assert that nullptr does not cause a core dump.
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, ODK_PrepareCoreLicenseRequest( EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, ODK_PrepareCoreLicenseRequest(
@@ -250,10 +263,12 @@ TEST(OdkTest, NullResponseTest) {
uint8_t message[message_size] = {0}; uint8_t message[message_size] = {0};
size_t core_message_length = message_size; size_t core_message_length = message_size;
uint8_t request_hash[ODK_SHA256_HASH_SIZE] = {0}; uint8_t request_hash[ODK_SHA256_HASH_SIZE] = {0};
ODK_TimerLimits timer_limits{0}; ODK_TimerLimits timer_limits;
ODK_ParsedLicense parsed_license; ODK_ParsedLicense parsed_license;
ODK_NonceValues nonce_values{0}; ODK_NonceValues nonce_values;
ODK_ClockValues clock_values{0}; memset(&nonce_values, 0, sizeof(nonce_values));
ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
// Assert that nullptr does not cause a core dump. // Assert that nullptr does not cause a core dump.
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
@@ -322,7 +337,8 @@ TEST(OdkTest, NullResponseTest) {
TEST(OdkTest, PrepareCoreLicenseRequest) { TEST(OdkTest, PrepareCoreLicenseRequest) {
uint8_t license_message[ODK_LICENSE_REQUEST_SIZE] = {0}; uint8_t license_message[ODK_LICENSE_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(license_message); size_t core_message_length = sizeof(license_message);
ODK_NonceValues nonce_values{0}; ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
EXPECT_EQ(OEMCrypto_SUCCESS, ODK_PrepareCoreLicenseRequest( EXPECT_EQ(OEMCrypto_SUCCESS, ODK_PrepareCoreLicenseRequest(
license_message, sizeof(license_message), license_message, sizeof(license_message),
&core_message_length, &nonce_values)); &core_message_length, &nonce_values));
@@ -331,7 +347,8 @@ TEST(OdkTest, PrepareCoreLicenseRequest) {
TEST(OdkTest, PrepareCoreLicenseRequestSize) { TEST(OdkTest, PrepareCoreLicenseRequestSize) {
uint8_t license_message[ODK_LICENSE_REQUEST_SIZE] = {0}; uint8_t license_message[ODK_LICENSE_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(license_message); size_t core_message_length = sizeof(license_message);
ODK_NonceValues nonce_values{0}; ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
// message length smaller than core message length // message length smaller than core message length
size_t core_message_length_invalid = core_message_length + 1; size_t core_message_length_invalid = core_message_length + 1;
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
@@ -349,8 +366,10 @@ TEST(OdkTest, PrepareCoreLicenseRequestSize) {
TEST(OdkTest, PrepareCoreRenewalRequest) { TEST(OdkTest, PrepareCoreRenewalRequest) {
uint8_t renewal_message[ODK_RENEWAL_REQUEST_SIZE] = {0}; uint8_t renewal_message[ODK_RENEWAL_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(renewal_message); size_t core_message_length = sizeof(renewal_message);
ODK_NonceValues nonce_values{0}; ODK_NonceValues nonce_values;
ODK_ClockValues clock_values{0}; memset(&nonce_values, 0, sizeof(nonce_values));
ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
constexpr uint64_t system_time_seconds = 10; constexpr uint64_t system_time_seconds = 10;
EXPECT_EQ(OEMCrypto_SUCCESS, EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreRenewalRequest( ODK_PrepareCoreRenewalRequest(
@@ -363,7 +382,8 @@ TEST(OdkTest, PrepareCoreRenewalRequestTimer) {
size_t core_message_length = sizeof(renewal_message); size_t core_message_length = sizeof(renewal_message);
ODK_NonceValues nonce_values{2, 16, 0, 0}; ODK_NonceValues nonce_values{2, 16, 0, 0};
constexpr uint64_t system_time_seconds = 10; constexpr uint64_t system_time_seconds = 10;
ODK_ClockValues clock_values_updated{0}; ODK_ClockValues clock_values_updated;
memset(&clock_values_updated, 0, sizeof(clock_values_updated));
// system time smaller than first decrypt time // system time smaller than first decrypt time
clock_values_updated.time_of_first_decrypt = system_time_seconds + 1; clock_values_updated.time_of_first_decrypt = system_time_seconds + 1;
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
@@ -383,7 +403,8 @@ TEST(OdkTest, PrepareCoreRenewalRequestTimer) {
TEST(OdkTest, PrepareCoreProvisioningRequest) { TEST(OdkTest, PrepareCoreProvisioningRequest) {
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0}; uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(provisioning_message); size_t core_message_length = sizeof(provisioning_message);
ODK_NonceValues nonce_values{0}; ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0}; uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
EXPECT_EQ( EXPECT_EQ(
OEMCrypto_SUCCESS, OEMCrypto_SUCCESS,
@@ -395,7 +416,8 @@ TEST(OdkTest, PrepareCoreProvisioningRequest) {
TEST(OdkTest, PrepareCoreProvisioningRequestDeviceId) { TEST(OdkTest, PrepareCoreProvisioningRequestDeviceId) {
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0}; uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(provisioning_message); size_t core_message_length = sizeof(provisioning_message);
ODK_NonceValues nonce_values{0}; ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
uint8_t device_id_invalid[ODK_DEVICE_ID_LEN_MAX + 1] = {0}; uint8_t device_id_invalid[ODK_DEVICE_ID_LEN_MAX + 1] = {0};
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreProvisioningRequest( ODK_PrepareCoreProvisioningRequest(
@@ -423,7 +445,8 @@ TEST(OdkTest, RenewalRequestRoundtrip) {
const std::vector<ODK_Field> extra_fields = { const std::vector<ODK_Field> extra_fields = {
{ODK_UINT64, &playback_time, "playback_time"}, {ODK_UINT64, &playback_time, "playback_time"},
}; };
ODK_ClockValues clock_values = {0}; ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
clock_values.time_of_first_decrypt = playback_start; clock_values.time_of_first_decrypt = playback_start;
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size, auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
ODK_NonceValues* nonce_values) { ODK_NonceValues* nonce_values) {
@@ -550,10 +573,23 @@ TEST(OdkTest, ParsePrivisioningErrorDeviceId) {
delete[] buf; delete[] buf;
} }
class OdkVersionTest : public ::testing::Test,
public ::testing::WithParamInterface<VersionParameters> {
protected:
template <typename P>
void SetRequestVersion(P* params) {
params->core_message.nonce_values.api_major_version =
GetParam().response_major_version;
params->core_message.nonce_values.api_minor_version =
GetParam().response_minor_version;
}
};
// Serialize and de-serialize license response // Serialize and de-serialize license response
TEST(OdkTest, LicenseResponseRoundtrip) { TEST_P(OdkVersionTest, LicenseResponseRoundtrip) {
ODK_LicenseResponseParams params; ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(&params); ODK_SetDefaultLicenseResponseParams(&params);
SetRequestVersion(&params);
// save a copy of params.request_hash as it will be zero out during the test // save a copy of params.request_hash as it will be zero out during the test
uint8_t request_hash_read[ODK_SHA256_HASH_SIZE]; uint8_t request_hash_read[ODK_SHA256_HASH_SIZE];
memcpy(request_hash_read, params.request_hash, sizeof(request_hash_read)); memcpy(request_hash_read, params.request_hash, sizeof(request_hash_read));
@@ -573,14 +609,15 @@ TEST(OdkTest, LicenseResponseRoundtrip) {
request_hash_string, request_hash_string,
oemcrypto_core_message); oemcrypto_core_message);
}; };
ValidateResponse<ODK_LicenseRequest>(&(params.core_message), ValidateResponse<ODK_LicenseRequest>(GetParam(), &(params.core_message),
params.extra_fields, odk_parse_func, params.extra_fields, odk_parse_func,
kdo_prepare_func); kdo_prepare_func);
} }
TEST(OdkTest, RenewalResponseRoundtrip) { TEST_P(OdkVersionTest, RenewalResponseRoundtrip) {
ODK_RenewalResponseParams params; ODK_RenewalResponseParams params;
ODK_SetDefaultRenewalResponseParams(&params); ODK_SetDefaultRenewalResponseParams(&params);
SetRequestVersion(&params);
const uint64_t playback_clock = params.playback_clock; const uint64_t playback_clock = params.playback_clock;
const uint64_t renewal_duration = params.renewal_duration; const uint64_t renewal_duration = params.renewal_duration;
auto odk_parse_func = [&](const uint8_t* buf, size_t size) { auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
@@ -602,14 +639,15 @@ TEST(OdkTest, RenewalResponseRoundtrip) {
return CreateCoreRenewalResponse(core_request, renewal_duration, return CreateCoreRenewalResponse(core_request, renewal_duration,
oemcrypto_core_message); oemcrypto_core_message);
}; };
ValidateResponse<ODK_RenewalRequest>(&(params.core_message), ValidateResponse<ODK_RenewalRequest>(GetParam(), &(params.core_message),
params.extra_fields, odk_parse_func, params.extra_fields, odk_parse_func,
kdo_prepare_func); kdo_prepare_func);
} }
TEST(OdkTest, ProvisionResponseRoundtrip) { TEST_P(OdkVersionTest, ProvisionResponseRoundtrip) {
ODK_ProvisioningResponseParams params; ODK_ProvisioningResponseParams params;
ODK_SetDefaultProvisioningResponseParams(&params); ODK_SetDefaultProvisioningResponseParams(&params);
SetRequestVersion(&params);
// save a copy of params.device_id as it will be zero out during the test // save a copy of params.device_id as it will be zero out during the test
const uint32_t device_id_length = params.device_id_length; const uint32_t device_id_length = params.device_id_length;
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0}; uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
@@ -628,11 +666,48 @@ TEST(OdkTest, ProvisionResponseRoundtrip) {
return CreateCoreProvisioningResponse(params.parsed_provisioning, return CreateCoreProvisioningResponse(params.parsed_provisioning,
core_request, oemcrypto_core_message); core_request, oemcrypto_core_message);
}; };
ValidateResponse<ODK_ProvisioningRequest>(&(params.core_message), ValidateResponse<ODK_ProvisioningRequest>(GetParam(), &(params.core_message),
params.extra_fields, odk_parse_func, params.extra_fields, odk_parse_func,
kdo_prepare_func); kdo_prepare_func);
} }
// If the minor version is positive, we can test an older minor version.
const uint16_t kOldMinor = ODK_MINOR_VERSION > 0 ? ODK_MINOR_VERSION - 1 : 0;
// Similarly, if this isn't the first major version, we can test an older major
// version.
// TODO(b/163416999): Remove it in the future. This will be unecessarily
// complicated after we upgrade to version 17.
const uint16_t kOldMajor = ODK_MAJOR_VERSION > ODK_FIRST_VERSION
? ODK_MAJOR_VERSION - 1
: ODK_FIRST_VERSION;
// If there is an older major, then we should accept any minor version.
// Otherwise, this test won't make sense and we should just use a minor of 0.
const uint16_t kOldMajorMinor = ODK_MAJOR_VERSION > ODK_FIRST_VERSION ? 42 : 0;
// List of major and minor versions to test.
std::vector<VersionParameters> TestCases() {
std::vector<VersionParameters> test_cases{
// Fields: request major, request minor, response major, response minor
{ODK_MAJOR_VERSION, ODK_MINOR_VERSION, ODK_MAJOR_VERSION,
ODK_MINOR_VERSION},
{ODK_MAJOR_VERSION, ODK_MINOR_VERSION + 1, ODK_MAJOR_VERSION,
ODK_MINOR_VERSION},
{ODK_MAJOR_VERSION, kOldMinor, ODK_MAJOR_VERSION, kOldMinor},
{ODK_MAJOR_VERSION, 0, ODK_MAJOR_VERSION, 0},
{ODK_MAJOR_VERSION + 1, 42, ODK_MAJOR_VERSION, ODK_MINOR_VERSION},
{kOldMajor, 0, kOldMajor, 0},
{kOldMajor, kOldMajorMinor, kOldMajor, kOldMajorMinor},
// Here are some known good versions. Make extra sure they work.
{16, 3, 16, 3},
{16, 4, 16, 4},
{16, 5, 16, 5},
};
return test_cases;
}
INSTANTIATE_TEST_CASE_P(OdkVersionTests, OdkVersionTest,
::testing::ValuesIn(TestCases()));
TEST(OdkSizeTest, LicenseRequest) { TEST(OdkSizeTest, LicenseRequest) {
uint8_t* message = nullptr; uint8_t* message = nullptr;
size_t message_length = 0; size_t message_length = 0;

View File

@@ -409,9 +409,30 @@ OEMCryptoResult ODK_IterFields(ODK_FieldMode mode, uint8_t* buf,
return OEMCrypto_SUCCESS; return OEMCrypto_SUCCESS;
} }
std::vector<ODK_Field> ODK_MakeTotalFields(
const std::vector<ODK_Field>& extra_fields, ODK_CoreMessage* core_message) {
std::vector<ODK_Field> total_fields = {
{ODK_UINT32, &(core_message->message_type), "message_type"},
{ODK_UINT32, &(core_message->message_length), "message_size"},
{ODK_UINT16, &(core_message->nonce_values.api_minor_version),
"api_minor_version"},
{ODK_UINT16, &(core_message->nonce_values.api_major_version),
"api_major_version"},
{ODK_UINT32, &(core_message->nonce_values.nonce), "nonce"},
{ODK_UINT32, &(core_message->nonce_values.session_id), "session_id"},
};
total_fields.insert(total_fields.end(), extra_fields.begin(),
extra_fields.end());
return total_fields;
}
// Expect the two buffers of size n to be equal. If not, dump the messages.
void ODK_ExpectEqualBuf(const void* s1, const void* s2, size_t n, void ODK_ExpectEqualBuf(const void* s1, const void* s2, size_t n,
const std::vector<ODK_Field>& fields) { const std::vector<ODK_Field>& fields) {
if (memcmp(s1, s2, n) != 0) { if (memcmp(s1, s2, n) != 0) {
ODK_CoreMessage core_message;
std::vector<ODK_Field> total_fields =
ODK_MakeTotalFields(fields, &core_message);
const void* buffers[] = {s1, s2}; const void* buffers[] = {s1, s2};
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
char _tmp[] = "/tmp/fileXXXXXX"; char _tmp[] = "/tmp/fileXXXXXX";
@@ -430,7 +451,7 @@ void ODK_ExpectEqualBuf(const void* s1, const void* s2, size_t n,
size_t bytes_written; size_t bytes_written;
uint8_t* buf = uint8_t* buf =
const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(buffers[i])); const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(buffers[i]));
ODK_IterFields(ODK_DUMP, buf, n, &bytes_written, fields); ODK_IterFields(ODK_DUMP, buf, n, &bytes_written, total_fields);
} }
FAIL(); FAIL();
} }
@@ -453,24 +474,9 @@ void ODK_BuildMessageBuffer(ODK_CoreMessage* core_message,
uint8_t** buf, uint32_t* buf_size) { uint8_t** buf, uint32_t* buf_size) {
ASSERT_TRUE(core_message != nullptr); ASSERT_TRUE(core_message != nullptr);
ASSERT_TRUE(buf_size != nullptr); ASSERT_TRUE(buf_size != nullptr);
std::vector<ODK_Field> total_fields = { std::vector<ODK_Field> total_fields =
{ODK_UINT32, &(core_message->message_type), "message_type"}, ODK_MakeTotalFields(extra_fields, core_message);
{ODK_UINT32, &(core_message->message_length), "message_size"},
{ODK_UINT16, &(core_message->nonce_values.api_minor_version),
"api_minor_version"},
{ODK_UINT16, &(core_message->nonce_values.api_major_version),
"api_major_version"},
{ODK_UINT32, &(core_message->nonce_values.nonce), "nonce"},
{ODK_UINT32, &(core_message->nonce_values.session_id), "session_id"},
};
uint32_t header_size = 0;
for (auto& field : total_fields) {
header_size += ODK_FieldLength(field.type);
}
total_fields.insert(total_fields.end(), extra_fields.begin(),
extra_fields.end());
for (auto& field : total_fields) { for (auto& field : total_fields) {
*buf_size += ODK_FieldLength(field.type); *buf_size += ODK_FieldLength(field.type);
} }

View File

@@ -1,6 +1,6 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */ // Copyright 2019 Google LLC. All rights reserved. This file and proprietary
/* source code may only be used and distributed under the Widevine Master */ // source code may only be used and distributed under the Widevine Master
/* License Agreement. */ // License Agreement.
#ifndef WIDEVINE_ODK_TEST_ODK_TEST_HELPER_H_ #ifndef WIDEVINE_ODK_TEST_ODK_TEST_HELPER_H_
#define WIDEVINE_ODK_TEST_ODK_TEST_HELPER_H_ #define WIDEVINE_ODK_TEST_ODK_TEST_HELPER_H_
@@ -66,7 +66,7 @@ struct ODK_ProvisioningResponseParams {
std::vector<ODK_Field> extra_fields; std::vector<ODK_Field> extra_fields;
}; };
/* Default values in core_message for testing */ // Default values in core_message for testing
void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message, void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message,
uint32_t message_type); uint32_t message_type);
void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params); void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params);
@@ -77,9 +77,9 @@ void ODK_SetDefaultProvisioningResponseParams(
size_t ODK_FieldLength(ODK_FieldType type); size_t ODK_FieldLength(ODK_FieldType type);
size_t ODK_AllocSize(ODK_FieldType type); size_t ODK_AllocSize(ODK_FieldType type);
/* Copy ODK_Field to buf */ // Copy ODK_Field to buf
OEMCryptoResult ODK_WriteSingleField(uint8_t* buf, const ODK_Field* field); OEMCryptoResult ODK_WriteSingleField(uint8_t* buf, const ODK_Field* field);
/* Load buf to ODK_Field */ // Load buf to ODK_Field
OEMCryptoResult ODK_ReadSingleField(const uint8_t* buf, const ODK_Field* field); OEMCryptoResult ODK_ReadSingleField(const uint8_t* buf, const ODK_Field* field);
OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf, const ODK_Field* field); OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf, const ODK_Field* field);
OEMCryptoResult ODK_IterFields(ODK_FieldMode mode, uint8_t* buf, OEMCryptoResult ODK_IterFields(ODK_FieldMode mode, uint8_t* buf,
@@ -89,11 +89,11 @@ void ODK_ExpectEqualBuf(const void* s1, const void* s2, size_t n,
const std::vector<ODK_Field>& fields); const std::vector<ODK_Field>& fields);
void ODK_ResetOdkFields(std::vector<ODK_Field>* fields); void ODK_ResetOdkFields(std::vector<ODK_Field>* fields);
/* Serialize core_message and extra_fields into buf */ // Serialize core_message and extra_fields into buf
void ODK_BuildMessageBuffer(ODK_CoreMessage* core_message, void ODK_BuildMessageBuffer(ODK_CoreMessage* core_message,
const std::vector<ODK_Field>& extra_fields, const std::vector<ODK_Field>& extra_fields,
uint8_t** buf, uint32_t* buf_size); uint8_t** buf, uint32_t* buf_size);
} /* namespace wvodk_test */ } // namespace wvodk_test
#endif /* WIDEVINE_ODK_TEST_ODK_TEST_HELPER_H_ */ #endif // WIDEVINE_ODK_TEST_ODK_TEST_HELPER_H_

View File

@@ -35,6 +35,7 @@ TEST(OdkTimerBasicTest, NullTest) {
TEST(OdkTimerBasicTest, Init) { TEST(OdkTimerBasicTest, Init) {
// Verify that basic initialization sets all of the fields. // Verify that basic initialization sets all of the fields.
ODK_ClockValues clock_values; ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
uint64_t time = 42; uint64_t time = 42;
ODK_InitializeClockValues(&clock_values, time); ODK_InitializeClockValues(&clock_values, time);
EXPECT_EQ(clock_values.time_of_license_signed, time); EXPECT_EQ(clock_values.time_of_license_signed, time);
@@ -50,6 +51,7 @@ TEST(OdkTimerBasicTest, Reload) {
// Verify that reloading clock values uses the same values // Verify that reloading clock values uses the same values
// for fields that can be saved, and sets others to 0. // for fields that can be saved, and sets others to 0.
ODK_ClockValues clock_values; ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
uint64_t time = 42u; uint64_t time = 42u;
uint64_t lic_signed = 1u; uint64_t lic_signed = 1u;
uint64_t first_decrypt = 2u; uint64_t first_decrypt = 2u;
@@ -1223,6 +1225,7 @@ TEST_F(ODKUseCase_LimitedDurationLicense, Case5) {
TEST_F(RenewalTest, V15Test) { TEST_F(RenewalTest, V15Test) {
const uint32_t key_duration = 25; const uint32_t key_duration = 25;
ODK_NonceValues nonce_values; ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
const uint64_t license_loaded = GetSystemTime(10); const uint64_t license_loaded = GetSystemTime(10);
EXPECT_EQ( EXPECT_EQ(
ODK_InitializeV15Values(&timer_limits_, &clock_values_, &nonce_values, ODK_InitializeV15Values(&timer_limits_, &clock_values_, &nonce_values,