Update Partner Repo
This update brings the partner repo up-to-date with commit ae93405f980295f9a783bd04e2132a2370720107 in the internal repo.
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
This ODK Library is used to generate and parse core OEMCrypto messages for
|
||||
OEMCrypto v16 and above.
|
||||
|
||||
This library is used by both OEMCrypto on a device, and by Widevine license and
|
||||
provisioning servers.
|
||||
OEMCrypto v16 and above. 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
|
||||
edit these files in the Android directory tree or in the Widevine Git
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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.
|
||||
|
||||
/*********************************************************************
|
||||
* OEMCryptoCENCCommon.h
|
||||
@@ -20,7 +20,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// @addtogroup common_types
|
||||
/// @{
|
||||
|
||||
/* clang-format off */
|
||||
/** Error and result codes returned by OEMCrypto functions. */
|
||||
typedef enum OEMCryptoResult {
|
||||
OEMCrypto_SUCCESS = 0,
|
||||
OEMCrypto_ERROR_INIT_FAILED = 1,
|
||||
@@ -83,6 +87,7 @@ typedef enum OEMCryptoResult {
|
||||
OEMCrypto_ERROR_LICENSE_RELOAD = 57,
|
||||
OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES = 58,
|
||||
OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION = 59,
|
||||
OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION = 60,
|
||||
/* ODK return values */
|
||||
ODK_ERROR_BASE = 1000,
|
||||
ODK_ERROR_CORE_MESSAGE = ODK_ERROR_BASE,
|
||||
@@ -94,8 +99,7 @@ typedef enum OEMCryptoResult {
|
||||
} OEMCryptoResult;
|
||||
/* clang-format on */
|
||||
|
||||
/*
|
||||
* OEMCrypto_Usage_Entry_Status.
|
||||
/**
|
||||
* Valid values for status in the usage table.
|
||||
*/
|
||||
typedef enum OEMCrypto_Usage_Entry_Status {
|
||||
@@ -106,7 +110,7 @@ typedef enum OEMCrypto_Usage_Entry_Status {
|
||||
kInactiveUnused = 4,
|
||||
} OEMCrypto_Usage_Entry_Status;
|
||||
|
||||
/*
|
||||
/**
|
||||
* OEMCrypto_LicenseType is used in the license message to indicate if the key
|
||||
* objects are for content keys, or for entitlement keys.
|
||||
*/
|
||||
@@ -122,9 +126,7 @@ typedef enum OEMCrypto_PrivateKeyType {
|
||||
OEMCrypto_ECC_Private_Key = 1,
|
||||
} OEMCrypto_PrivateKeyType;
|
||||
|
||||
/*
|
||||
* OEMCrypto_Substring
|
||||
*
|
||||
/**
|
||||
* 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
|
||||
* signed message.
|
||||
@@ -134,23 +136,22 @@ typedef struct {
|
||||
size_t length;
|
||||
} OEMCrypto_Substring;
|
||||
|
||||
/*
|
||||
* OEMCrypto_KeyObject
|
||||
/**
|
||||
* Points to the relevant fields for a content key. The fields are extracted
|
||||
* from the License Response message offered to OEMCrypto_LoadKeys(). Each
|
||||
* field points to one of the components of the key. Key data, key control,
|
||||
* and both IV fields are 128 bits (16 bytes):
|
||||
* 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: the unique id of this key.
|
||||
* @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
|
||||
* 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 - 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.
|
||||
* 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 - 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 memory for the OEMCrypto_KeyObject fields is allocated and freed
|
||||
@@ -164,8 +165,10 @@ typedef struct {
|
||||
OEMCrypto_Substring key_control;
|
||||
} OEMCrypto_KeyObject;
|
||||
|
||||
/// @}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_INCLUDE_OEMCRYPTOCENCCOMMON_H_ */
|
||||
#endif // WIDEVINE_ODK_INCLUDE_OEMCRYPTOCENCCOMMON_H_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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.
|
||||
|
||||
/*********************************************************************
|
||||
* core_message_deserialize.h
|
||||
@@ -53,7 +53,17 @@ bool CoreProvisioningRequestFromMessage(
|
||||
const std::string& oemcrypto_core_message,
|
||||
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_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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.
|
||||
|
||||
/*********************************************************************
|
||||
* core_message_serialize.h
|
||||
@@ -62,7 +62,7 @@ bool CreateCoreRenewalResponse(const ODK_RenewalRequest& core_request,
|
||||
bool CreateCoreProvisioningResponse(const ODK_ParsedProvisioning& parsed_prov,
|
||||
const ODK_ProvisioningRequest& core_request,
|
||||
std::string* oemcrypto_core_message);
|
||||
} /* namespace serialize */
|
||||
} /* namespace oemcrypto_core_message */
|
||||
} // namespace serialize
|
||||
} // namespace oemcrypto_core_message
|
||||
|
||||
#endif /* WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_H_ */
|
||||
#endif // WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_H_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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.
|
||||
|
||||
/*********************************************************************
|
||||
* core_message_serialize_proto.h
|
||||
@@ -23,7 +23,7 @@
|
||||
namespace oemcrypto_core_message {
|
||||
namespace serialize {
|
||||
|
||||
/* @ public create response (serializer) functions accepting proto input */
|
||||
// @ public create response (serializer) functions accepting proto input
|
||||
|
||||
/**
|
||||
* Counterpart (serializer) of ODK_ParseLicense (deserializer)
|
||||
@@ -34,12 +34,14 @@ namespace serialize {
|
||||
* [in] core_request oemcrypto core message from request.
|
||||
* [in] core_request_sha256 - hash of serialized core request.
|
||||
* [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.
|
||||
*/
|
||||
bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
|
||||
const ODK_LicenseRequest& core_request,
|
||||
const std::string& core_request_sha256,
|
||||
const bool nonce_required,
|
||||
const bool uses_padding,
|
||||
std::string* oemcrypto_core_message);
|
||||
|
||||
/**
|
||||
@@ -56,7 +58,7 @@ bool CreateCoreProvisioningResponseFromProto(
|
||||
const ODK_ProvisioningRequest& core_request,
|
||||
std::string* oemcrypto_core_message);
|
||||
|
||||
} /* namespace serialize */
|
||||
} /* namespace oemcrypto_core_message */
|
||||
} // namespace serialize
|
||||
} // namespace oemcrypto_core_message
|
||||
|
||||
#endif /* WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_PROTO_H_ */
|
||||
#endif // WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_PROTO_H_
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* 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. */
|
||||
// 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.
|
||||
|
||||
/* clang-format off */
|
||||
// clang-format off
|
||||
/*********************************************************************
|
||||
* core_message_types.h
|
||||
*
|
||||
@@ -38,6 +38,8 @@
|
||||
* | | ODK_PrepareCoreRenewalRequest | | CoreRenewalRequestFromMessage |
|
||||
* | +------------------------------------+ +-----------------------------------+
|
||||
* | | ODK_PrepareCoreProvisioningRequest | | CoreProvisioningRequestFromMessage|
|
||||
* | +------------------------------------+ +-----------------------------------+
|
||||
* | | ODK_PrepareCommonRequest | | CoreCommonRequestFromMessage |
|
||||
* +---+------------------------------------+---+-----------------------------------+
|
||||
* | d | ODK_ParseLicense | s | CreateCoreLicenseResponse |
|
||||
* | +------------------------------------+ +-----------------------------------+
|
||||
@@ -47,7 +49,7 @@
|
||||
* +---+------------------------------------+---+-----------------------------------+
|
||||
*
|
||||
*********************************************************************/
|
||||
/* clang-format on */
|
||||
// clang-format on
|
||||
|
||||
#ifndef WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_TYPES_H_
|
||||
#define WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_TYPES_H_
|
||||
@@ -57,7 +59,18 @@
|
||||
|
||||
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
|
||||
@@ -94,6 +107,6 @@ struct ODK_ProvisioningRequest {
|
||||
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_
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
/* 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. */
|
||||
// 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.
|
||||
|
||||
/*********************************************************************
|
||||
* odk.h
|
||||
*
|
||||
* OEMCrypto v16 Core Message Serialization library
|
||||
/**
|
||||
* @mainpage OEMCrypto v16 Core Message Serialization library
|
||||
*
|
||||
* For Widevine Modular DRM, there are six message types between a server 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
|
||||
* modification by any process running the REE.
|
||||
*
|
||||
* See the documents "Widevine Core Message Serialization" and "License
|
||||
* Duration and Renewal" for a detailed description of the ODK API. You can
|
||||
* See the documents
|
||||
* <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
|
||||
* docs/Widevine_Core_Message_Serialization.pdf and
|
||||
* 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_
|
||||
@@ -54,25 +70,23 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ODK_InitializeSessionValues
|
||||
*
|
||||
* Description:
|
||||
/// @addtogroup odk_timer
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* This function initializes the session's data structures. It shall be
|
||||
* called from OEMCrypto_OpenSession.
|
||||
*
|
||||
* Parameters:
|
||||
* [out] timer_limits: the session's timer limits.
|
||||
* [out] clock_values: the session's clock values.
|
||||
* [out] nonce_values: the session's ODK nonce values.
|
||||
* [in] api_major_version: the API version of OEMCrypto.
|
||||
* [in] session_id: the session id of the newly created session.
|
||||
* @param[out] timer_limits: the session's timer limits.
|
||||
* @param[out] clock_values: the session's clock values.
|
||||
* @param[out] nonce_values: the session's ODK nonce values.
|
||||
* @param[in] api_major_version: the API version of OEMCrypto.
|
||||
* @param[in] session_id: the session id of the newly created session.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
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 session_id);
|
||||
|
||||
/*
|
||||
* ODK_SetNonceValues
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* This function sets the nonce value in the session's nonce structure. It
|
||||
* shall be called from OEMCrypto_GenerateNonce.
|
||||
*
|
||||
* Parameters:
|
||||
* [in/out] nonce_values: the session's nonce data.
|
||||
* [in] nonce: the new nonce that was just generated.
|
||||
* @param[in,out] nonce_values: the session's nonce data.
|
||||
* @param[in] nonce: the new nonce that was just generated.
|
||||
*
|
||||
* Returns:
|
||||
* true on success
|
||||
* @retval true on success
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_SetNonceValues(ODK_NonceValues* nonce_values,
|
||||
uint32_t nonce);
|
||||
|
||||
/*
|
||||
* ODK_InitializeClockValues
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* This function initializes the clock values in the session clock_values
|
||||
* structure. It shall be called from OEMCrypto_PrepAndSignLicenseRequest.
|
||||
*
|
||||
* Parameters:
|
||||
* [in/out] clock_values: the session's clock data.
|
||||
* [in] system_time_seconds: the current time on OEMCrypto's monotonic clock.
|
||||
* @param[in,out] clock_values: the session's clock data.
|
||||
* @param[in] system_time_seconds: the current time on OEMCrypto's monotonic
|
||||
* clock.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
|
||||
uint64_t system_time_seconds);
|
||||
|
||||
/*
|
||||
* ODK_ReloadClockValues
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* 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
|
||||
* earlier license is loaded, the value time_of_license_loaded shall be used
|
||||
* in place of time_of_license_signed.
|
||||
*
|
||||
* Parameters:
|
||||
* [in/out] clock_values: the session's clock data.
|
||||
* [in] time_of_license_signed: the value time_license_received from the
|
||||
* @param[in,out] clock_values: the session's clock data.
|
||||
* @param[in] time_of_license_signed: the value time_license_received from the
|
||||
* 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.
|
||||
* [in] time_of_last_decrypt: the value time_of_last_decrypt from the loaded
|
||||
* usage entry.
|
||||
* [in] status: the value status from the loaded usage entry.
|
||||
* [in] system_time_seconds: the current time on OEMCrypto's monotonic clock.
|
||||
* @param[in] time_of_last_decrypt: the value time_of_last_decrypt from the
|
||||
* loaded usage entry.
|
||||
* @param[in] status: the value status from the loaded usage entry.
|
||||
* @param[in] system_time_seconds: the current time on OEMCrypto's monotonic
|
||||
* clock.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
|
||||
@@ -156,10 +158,7 @@ OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
|
||||
enum OEMCrypto_Usage_Entry_Status status,
|
||||
uint64_t system_time_seconds);
|
||||
|
||||
/*
|
||||
* ODK_AttemptFirstPlayback
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
* timer_value.
|
||||
*
|
||||
* Parameters:
|
||||
* [in] system_time_seconds: the current time on OEMCrypto's monotonic clock,
|
||||
* in seconds.
|
||||
* [in] timer_limits: timer limits specified in the license.
|
||||
* [in/out] clock_values: the sessions clock values.
|
||||
* [out] timer_value: set to the new timer value. Only used if the return
|
||||
* @param[in] system_time_seconds: the current time on OEMCrypto's monotonic
|
||||
* clock, in seconds.
|
||||
* @param[in] timer_limits: timer limits specified in the license.
|
||||
* @param[in,out] clock_values: the sessions clock values.
|
||||
* @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
|
||||
* hardware timer.
|
||||
*
|
||||
* Returns:
|
||||
* ODK_SET_TIMER: Success. The timer should be reset to the specified value
|
||||
* and playback is allowed.
|
||||
* ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
|
||||
* @retval ODK_SET_TIMER: Success. The timer should be reset to the specified
|
||||
* value and playback is allowed.
|
||||
* @retval ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
|
||||
* 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.
|
||||
*/
|
||||
OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
|
||||
@@ -196,10 +193,7 @@ OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
|
||||
ODK_ClockValues* clock_values,
|
||||
uint64_t* timer_value);
|
||||
|
||||
/*
|
||||
* ODK_UpdateLastPlaybackTime
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* Vendors that do not implement their own timer should call
|
||||
* ODK_UpdateLastPlaybackTime regularly during playback. This updates the
|
||||
* 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
|
||||
* clock values are accurate.
|
||||
*
|
||||
* Parameters:
|
||||
* [in] system_time_seconds: the current time on OEMCrypto's monotonic clock,
|
||||
* in seconds.
|
||||
* [in] timer_limits: timer limits specified in the license.
|
||||
* [in/out] clock_values: the sessions clock values.
|
||||
* @param[in] system_time_seconds: the current time on OEMCrypto's monotonic
|
||||
* clock, in seconds.
|
||||
* @param[in] timer_limits: timer limits specified in the license.
|
||||
* @param[in,out] clock_values: the sessions clock values.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS: Success. Playback is allowed.
|
||||
* ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
|
||||
* @retval OEMCrypto_SUCCESS: Success. Playback is 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.
|
||||
*/
|
||||
OEMCryptoResult ODK_UpdateLastPlaybackTime(uint64_t system_time_seconds,
|
||||
const ODK_TimerLimits* timer_limits,
|
||||
ODK_ClockValues* clock_values);
|
||||
|
||||
/*
|
||||
* ODK_DeactivateUsageEntry
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* This function modifies the session's clock values to indicate that the
|
||||
* license has been deactivated. It shall be called from
|
||||
* OEMCrypto_DeactivateUsageEntry
|
||||
*
|
||||
* Parameters:
|
||||
* [in/out] clock_values: the sessions clock values.
|
||||
* @param[in,out] clock_values: the sessions clock values.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values);
|
||||
|
||||
/*
|
||||
* ODK_PrepareCoreLicenseRequest
|
||||
*
|
||||
* Description:
|
||||
/// @}
|
||||
|
||||
/// @addtogroup odk_packer
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* 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
|
||||
* message.
|
||||
@@ -262,31 +252,26 @@ OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values);
|
||||
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
|
||||
* core_message_size to the size needed.
|
||||
*
|
||||
* Parameters:
|
||||
* [in/out] message: Pointer to memory for the entire message. Modified by
|
||||
* @param[in,out] message: Pointer to memory for the entire message. Modified by
|
||||
* the ODK library.
|
||||
* [in] message_length: length of the entire message buffer.
|
||||
* [in/out] core_message_size: length of the core message at the beginning of
|
||||
* the message. (in) size of buffer reserved for the core message, in
|
||||
* @param[in] message_length: length of the entire message buffer.
|
||||
* @param[in,out] core_message_size: length of the core message at the beginning
|
||||
* of the message. (in) size of buffer reserved for the core message, in
|
||||
* 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:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
|
||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
||||
uint8_t* message, size_t message_length, size_t* core_message_size,
|
||||
const ODK_NonceValues* nonce_values);
|
||||
|
||||
/*
|
||||
* ODK_PrepareCoreRenewalRequest
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* Modifies the message to include a core renewal request at the beginning of
|
||||
* the message buffer. The values in nonce_values, clock_values and
|
||||
* 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
|
||||
* core_message_size to the size needed.
|
||||
*
|
||||
* Parameters:
|
||||
* [in/out] message: Pointer to memory for the entire message. Modified by
|
||||
* @param[in,out] message: Pointer to memory for the entire message. Modified by
|
||||
* the ODK library.
|
||||
* [in] message_length: length of the entire message buffer.
|
||||
* [in/out] core_message_size: length of the core message at the beginning of
|
||||
* the message. (in) size of buffer reserved for the core message, in
|
||||
* @param[in] message_length: length of the entire message buffer.
|
||||
* @param[in,out] core_message_size: length of the core message at the beginning
|
||||
* of the message. (in) size of buffer reserved for the core message, in
|
||||
* bytes. (out) actual length of the core message, in bytes.
|
||||
* [in/out] nonce_values: pointer to the session's nonce data.
|
||||
* [in/out] clock_values: the session's clock values.
|
||||
* [in] system_time_seconds: the current time on OEMCrypto's clock, in
|
||||
* @param[in,out] nonce_values: pointer to the session's nonce data.
|
||||
* @param[in,out] clock_values: the session's clock values.
|
||||
* @param[in] system_time_seconds: the current time on OEMCrypto's clock, in
|
||||
* seconds.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
|
||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
||||
@@ -331,10 +314,7 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
||||
ODK_ClockValues* clock_values,
|
||||
uint64_t system_time_seconds);
|
||||
|
||||
/*
|
||||
* ODK_PrepareCoreProvisioningRequest
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* Modifies the message to include a core provisioning request at the
|
||||
* beginning of the message buffer. The values in nonce_values are used to
|
||||
* populate the message.
|
||||
@@ -350,26 +330,24 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
||||
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
|
||||
* core_message_size to the size needed.
|
||||
*
|
||||
* Parameters:
|
||||
* [in/out] message: Pointer to memory for the entire message. Modified by
|
||||
* @param[in,out] message: Pointer to memory for the entire message. Modified by
|
||||
* the ODK library.
|
||||
* [in] message_length: length of the entire message buffer.
|
||||
* [in/out] core_message_size: length of the core message at the beginning of
|
||||
* the message. (in) size of buffer reserved for the core message, in
|
||||
* @param[in] message_length: length of the entire message buffer.
|
||||
* @param[in,out] core_message_size: length of the core message at the beginning
|
||||
* of the message. (in) size of buffer reserved for the core message, in
|
||||
* bytes. (out) actual length of the core message, in bytes.
|
||||
* [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
|
||||
* keybox. For devices with an OEM Certificate, this is a device unique
|
||||
* id string.
|
||||
* [in] device_id_length: length of device_id. The device ID can be at most
|
||||
* 64 bytes.
|
||||
* @param[in] nonce_values: pointer to the session's nonce data.
|
||||
* @param[in] device_id: For devices with a keybox, this is the device ID from
|
||||
* the keybox. For devices with an OEM Certificate, this is a device
|
||||
* unique id string.
|
||||
* @param[in] device_id_length: length of device_id. The device ID can be at
|
||||
* most 64 bytes.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
|
||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
||||
@@ -377,30 +355,30 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
||||
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
||||
size_t device_id_length);
|
||||
|
||||
/*
|
||||
* ODK_InitializeV15Values
|
||||
*
|
||||
* Description:
|
||||
/// @}
|
||||
|
||||
/// @addtogroup odk_timer
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* This function sets all limits in the timer_limits struct to the
|
||||
* key_duration and initializes the other values. The field
|
||||
* nonce_values.api_major_version will be set to 15. It shall be called from
|
||||
* OEMCrypto_LoadKeys when loading a legacy license.
|
||||
*
|
||||
* Parameters:
|
||||
* [out] timer_limits: The session's timer limits.
|
||||
* [in/out] clock_values: The session's clock values.
|
||||
* [in/out] nonce_values: The session's ODK nonce values.
|
||||
* [in] key_duration: The duration from the first key's key control block. In
|
||||
* practice, the key duration is the same for all keys and is the same
|
||||
* as the license duration.
|
||||
* [in] system_time_seconds: The current time on the system clock, as
|
||||
* @param[out] timer_limits: The session's timer limits.
|
||||
* @param[in,out] clock_values: The session's clock values.
|
||||
* @param[in,out] nonce_values: The session's ODK nonce values.
|
||||
* @param[in] key_duration: The duration from the first key's key control
|
||||
* block. In practice, the key duration is the same for all keys and is
|
||||
* the same as the license duration.
|
||||
* @param[in] system_time_seconds: The current time on the system clock, as
|
||||
* described in the document "License Duration and Renewal".
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
|
||||
@@ -409,10 +387,7 @@ OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
|
||||
uint32_t key_duration,
|
||||
uint64_t system_time_seconds);
|
||||
|
||||
/*
|
||||
* ODK_RefreshV15Values
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@@ -420,28 +395,26 @@ OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
|
||||
* OEMCrypto shall pass in the current system time, and the key duration from
|
||||
* the first object in the OEMCrypto_KeyRefreshObject.
|
||||
*
|
||||
* Parameters:
|
||||
* [in] timer_limits: The session's timer limits.
|
||||
* [in/out] clock_values: The session's clock values.
|
||||
* [in] nonce_values: The session's ODK nonce values.
|
||||
* [in] system_time_seconds: The current time on the system clock, as
|
||||
* @param[in] timer_limits: The session's timer limits.
|
||||
* @param[in,out] clock_values: The session's clock values.
|
||||
* @param[in] nonce_values: The session's ODK nonce values.
|
||||
* @param[in] system_time_seconds: The current time on the system clock, as
|
||||
* 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.
|
||||
* [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
|
||||
* hardware timer.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
* ODK_SET_TIMER: Success. The timer should be reset to the specified value
|
||||
* and playback is allowed.
|
||||
* ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
* @retval ODK_SET_TIMER: Success. The timer should be reset to the specified
|
||||
* value and playback is allowed.
|
||||
* @retval ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
|
||||
* 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.
|
||||
*/
|
||||
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,
|
||||
uint64_t* timer_value);
|
||||
|
||||
/*
|
||||
* ODK_ParseLicense
|
||||
*
|
||||
* Description:
|
||||
/// @}
|
||||
|
||||
/// @addtogroup odk_parser
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* The function ODK_ParseLicense will parse the message and verify fields in
|
||||
* 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
|
||||
* the pst in the license has a nonzero length.
|
||||
*
|
||||
* Parameters:
|
||||
* [in] message: pointer to the message buffer.
|
||||
* [in] message_length: length of the entire message buffer.
|
||||
* [in] core_message_size: length of the core message, at the beginning of
|
||||
* @param[in] message: pointer to the message buffer.
|
||||
* @param[in] message_length: length of the entire message buffer.
|
||||
* @param[in] core_message_size: length of the core message, at the beginning of
|
||||
* the message buffer.
|
||||
* [in] initial_license_load: true when called for OEMCrypto_LoadLicense and
|
||||
* false when called for OEMCrypto_ReloadLicense.
|
||||
* [in] usage_entry_present: true if the session has a new usage entry
|
||||
* @param[in] initial_license_load: true when called for OEMCrypto_LoadLicense
|
||||
* and false when called for OEMCrypto_ReloadLicense.
|
||||
* @param[in] usage_entry_present: true if the session has a new usage entry
|
||||
* associated with it created via OEMCrypto_CreateNewUsageEntry.
|
||||
* [in] request_hash: the hash of the license request core message. This was
|
||||
* computed by OEMCrypto when the license request was signed.
|
||||
* [in/out] timer_limits: The session's timer limits. These will be updated.
|
||||
* [in/out] clock_values: The session's clock values. These will be updated.
|
||||
* [in/out] nonce_values: The session's nonce values. These will be updated.
|
||||
* [out] parsed_license: the destination for the data.
|
||||
* @param[in] request_hash: the hash of the license request core message. This
|
||||
* was computed by OEMCrypto when the license request was signed.
|
||||
* @param[in,out] timer_limits: The session's timer limits. These will be
|
||||
* updated.
|
||||
* @param[in,out] clock_values: The session's clock values. These will be
|
||||
* 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:
|
||||
* OEMCrypto_SUCCESS
|
||||
* ODK_ERROR_CORE_MESSAGE: if the message did not parse correctly, or there
|
||||
* were other incorrect values. An error should be returned to the CDM
|
||||
* layer.
|
||||
* ODK_UNSUPPORTED_API
|
||||
* OEMCrypto_ERROR_INVALID_NONCE
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval ODK_ERROR_CORE_MESSAGE: if the message did not parse correctly, or
|
||||
* there were other incorrect values. An error should be returned to the
|
||||
* CDM layer.
|
||||
* @retval ODK_UNSUPPORTED_API
|
||||
* @retval OEMCrypto_ERROR_INVALID_NONCE
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_ParseLicense(
|
||||
@@ -520,10 +496,7 @@ OEMCryptoResult ODK_ParseLicense(
|
||||
ODK_TimerLimits* timer_limits, ODK_ClockValues* clock_values,
|
||||
ODK_NonceValues* nonce_values, ODK_ParsedLicense* parsed_license);
|
||||
|
||||
/*
|
||||
* ODK_ParseRenewal
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* The function ODK_ParseRenewal will parse the message and verify its
|
||||
* contents. If the message does not parse correctly, an error of
|
||||
* 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
|
||||
* by timer_value.
|
||||
*
|
||||
* Parameters:
|
||||
* [in] message: pointer to the message buffer.
|
||||
* [in] message_length: length of the entire message buffer.
|
||||
* [in] core_message_size: length of the core message, at the beginning of
|
||||
* @param[in] message: pointer to the message buffer.
|
||||
* @param[in] message_length: length of the entire message buffer.
|
||||
* @param[in] core_message_size: length of the core message, at the beginning of
|
||||
* the message buffer.
|
||||
* [in] nonce_values: pointer to the session's nonce data.
|
||||
* [in] system_time_seconds: the current time on OEMCrypto's clock, in
|
||||
* @param[in] nonce_values: pointer to the session's nonce data.
|
||||
* @param[in] system_time_seconds: the current time on OEMCrypto's clock, in
|
||||
* seconds.
|
||||
* [in] timer_limits: timer limits specified in the license.
|
||||
* [in/out] clock_values: the sessions clock values.
|
||||
* [out] timer_value: set to the new timer value. Only used if the return
|
||||
* @param[in] timer_limits: timer limits specified in the license.
|
||||
* @param[in,out] clock_values: the sessions clock values.
|
||||
* @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
|
||||
* hardware timer.
|
||||
*
|
||||
* Returns:
|
||||
* ODK_ERROR_CORE_MESSAGE: the message did not parse correctly, or there were
|
||||
* other incorrect values. An error should be returned to the CDM layer.
|
||||
* ODK_SET_TIMER: Success. The timer should be reset to the specified timer
|
||||
* value.
|
||||
* ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
|
||||
* @retval ODK_ERROR_CORE_MESSAGE: the message did not parse correctly, or there
|
||||
* were other incorrect values. An error should be returned to the CDM
|
||||
* layer.
|
||||
* @retval ODK_SET_TIMER: Success. The timer should be reset to the specified
|
||||
* timer value.
|
||||
* @retval ODK_DISABLE_TIMER: Success, but disable timer. Unlimited playback is
|
||||
* allowed.
|
||||
* ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
|
||||
* ODK_UNSUPPORTED_API
|
||||
* ODK_STALE_RENEWAL: This renewal is not the most recently signed. It is
|
||||
* rejected.
|
||||
* OEMCrypto_ERROR_INVALID_NONCE
|
||||
* @retval ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
|
||||
* @retval ODK_UNSUPPORTED_API
|
||||
* @retval ODK_STALE_RENEWAL: This renewal is not the most recently signed. It
|
||||
* is rejected.
|
||||
* @retval OEMCrypto_ERROR_INVALID_NONCE
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
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,
|
||||
uint64_t* timer_value);
|
||||
|
||||
/*
|
||||
* ODK_ParseProvisioning
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* The function ODK_ParseProvisioning will parse the message and verify the
|
||||
* 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 -
|
||||
* core_message_length.
|
||||
*
|
||||
* Parameters:
|
||||
* [in] message: pointer to the message buffer.
|
||||
* [in] message_length: length of the entire message buffer.
|
||||
* [in] core_message_size: length of the core message, at the beginning of
|
||||
* @param[in] message: pointer to the message buffer.
|
||||
* @param[in] message_length: length of the entire message buffer.
|
||||
* @param[in] core_message_size: length of the core message, at the beginning of
|
||||
* the message buffer.
|
||||
* [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] nonce_values: pointer to the session's nonce data.
|
||||
* @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.
|
||||
* [in] device_id_length: the length of the device ID.
|
||||
* [out] parsed_response: destination for the parse data.
|
||||
* @param[in] device_id_length: the length of the device ID.
|
||||
* @param[out] parsed_response: destination for the parse data.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* ODK_ERROR_CORE_MESSAGE: the message did not parse correctly, or there were
|
||||
* other incorrect values. An error should be returned to the CDM layer.
|
||||
* ODK_UNSUPPORTED_API
|
||||
* OEMCrypto_ERROR_INVALID_NONCE
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval ODK_ERROR_CORE_MESSAGE: the message did not parse correctly, or there
|
||||
* were other incorrect values. An error should be returned to the CDM
|
||||
* layer.
|
||||
* @retval ODK_UNSUPPORTED_API
|
||||
* @retval OEMCrypto_ERROR_INVALID_NONCE
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This method is new in version 16 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_ParseProvisioning(
|
||||
@@ -630,8 +598,10 @@ OEMCryptoResult ODK_ParseProvisioning(
|
||||
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
||||
size_t device_id_length, ODK_ParsedProvisioning* parsed_response);
|
||||
|
||||
/// @}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_INCLUDE_ODK_H_ */
|
||||
#endif // WIDEVINE_ODK_INCLUDE_ODK_H_
|
||||
|
||||
14
oemcrypto/odk/include/odk_attributes.h
Normal file
14
oemcrypto/odk/include/odk_attributes.h
Normal 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_
|
||||
138
oemcrypto/odk/include/odk_message.h
Normal file
138
oemcrypto/odk/include/odk_message.h
Normal 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_
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_STRUCTS_H_
|
||||
#define WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
|
||||
@@ -12,10 +12,13 @@
|
||||
|
||||
/* The version of this library. */
|
||||
#define ODK_MAJOR_VERSION 16
|
||||
#define ODK_MINOR_VERSION 3
|
||||
#define ODK_MINOR_VERSION 5
|
||||
|
||||
/* 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. */
|
||||
#define ODK_FIRST_VERSION 16
|
||||
@@ -24,10 +27,10 @@
|
||||
#define ODK_DEVICE_ID_LEN_MAX 64
|
||||
#define ODK_SHA256_HASH_SIZE 32
|
||||
|
||||
/*
|
||||
* ODK_TimerLimits Structure
|
||||
*
|
||||
* Description:
|
||||
/// @addtogroup odk_timer
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
* ODK_ParseLicense or ODK_InitializeV15Values.
|
||||
*
|
||||
* Fields:
|
||||
* soft_enforce_rental_duration: A boolean controlling the soft or hard
|
||||
* @param soft_enforce_rental_duration: A boolean controlling the soft or hard
|
||||
* 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.
|
||||
* earliest_playback_start_seconds: The earliest time that the first playback
|
||||
* is allowed. Measured in seconds since the license request was signed. For
|
||||
* most use cases, this is zero.
|
||||
* rental_duration_seconds: Window of time for the allowed first playback.
|
||||
* Measured in seconds since the earliest playback start. If
|
||||
* @param earliest_playback_start_seconds: The earliest time that the first
|
||||
* playback is allowed. Measured in seconds since the license request was
|
||||
* signed. For most use cases, this is zero.
|
||||
* @param rental_duration_seconds: Window of time for the allowed first
|
||||
* playback. Measured in seconds since the earliest playback start. If
|
||||
* soft_enforce_rental_duration is true, this applies only to the first
|
||||
* playback. If soft_enforce_rental_duration is false, then this restricts
|
||||
* any playback. A value of zero means no limit.
|
||||
* total_playback_duration_seconds: Window of time for allowed playback.
|
||||
* playback. If soft_enforce_rental_duration is false, then this
|
||||
* restricts any playback. A value of zero means no limit.
|
||||
* @param total_playback_duration_seconds: Window of time for allowed playback.
|
||||
* Measured in seconds since the first playback start. If
|
||||
* soft_enforce_playback_duration is true, this applies only to the start of
|
||||
* playback for any session. If soft_enforce_playback_duration is false, then
|
||||
* this restricts any playback. A value of zero means no limit.
|
||||
* initial_renewal_duration_seconds: Window of time for allowed playback.
|
||||
* soft_enforce_playback_duration is true, this applies only to the start
|
||||
* of playback for any session. If soft_enforce_playback_duration is
|
||||
* false, then this restricts any playback. A value of zero means no
|
||||
* limit.
|
||||
* @param initial_renewal_duration_seconds: Window of time for allowed playback.
|
||||
* 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
|
||||
* timer will be reset. A value of zero means no limit.
|
||||
* used to start the renewal timer. After a renewal message is loaded,
|
||||
* the timer will be reset. A value of zero means no limit.
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This struct changed in API version 16.2.
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -70,10 +73,7 @@ typedef struct {
|
||||
uint64_t initial_renewal_duration_seconds;
|
||||
} ODK_TimerLimits;
|
||||
|
||||
/*
|
||||
* ODK_ClockValues Structure
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* Clock values are modified when decryption occurs or when a renewal is
|
||||
* 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
|
||||
@@ -88,28 +88,28 @@ typedef struct {
|
||||
* on OEMCrypto's system clock, as described in the document "License
|
||||
* Duration and Renewal".
|
||||
*
|
||||
* Fields:
|
||||
* time_of_license_signed: Time that the license request was signed, based on
|
||||
* OEMCrypto's system clock. This value shall be stored and reloaded with
|
||||
* usage entry as time_of_license_received.
|
||||
* time_of_first_decrypt: Time of the first decrypt or call select key, based
|
||||
* on OEMCrypto's system clock. This is 0 if the license has not been used to
|
||||
* decrypt any data. This value shall be stored and reloaded with usage entry.
|
||||
* time_of_last_decrypt: Time of the most recent decrypt call, based on
|
||||
* @param time_of_license_signed: Time that the license request was signed,
|
||||
* based on OEMCrypto's system clock. This value shall be stored and
|
||||
* reloaded with usage entry as time_of_license_received.
|
||||
* @param time_of_first_decrypt: Time of the first decrypt or call select key,
|
||||
* based on OEMCrypto's system clock. This is 0 if the license has not
|
||||
* been used to decrypt any data. This value shall be stored and reloaded
|
||||
* with usage entry.
|
||||
* @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
|
||||
* usage entry.
|
||||
* time_of_renewal_request: Time of the most recent renewal request, based on
|
||||
* OEMCrypto's system clock. This is used to verify that a renewal is not
|
||||
* stale.
|
||||
* 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
|
||||
* library to determine if it has expired.
|
||||
* timer_status: Used internally by the ODK library to indicate the current
|
||||
* timer status.
|
||||
* status: The license or usage entry status. This value shall be stored and
|
||||
* reloaded with usage entry.
|
||||
* @param time_of_renewal_request: Time of the most recent renewal request,
|
||||
* based on OEMCrypto's system clock. This is used to verify that a
|
||||
* renewal is not stale.
|
||||
* @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 library to determine if it has expired.
|
||||
* @param timer_status: Used internally by the ODK library to indicate the
|
||||
* current timer status.
|
||||
* @param status: The license or usage entry status. This value shall be stored
|
||||
* and reloaded with usage entry.
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This struct changed in API version 16.2.
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -122,10 +122,7 @@ typedef struct {
|
||||
enum OEMCrypto_Usage_Entry_Status status;
|
||||
} ODK_ClockValues;
|
||||
|
||||
/*
|
||||
* ODK_NonceValues Structure
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
* the birthday paradox to generate nonce collisions on a single device.
|
||||
*
|
||||
* Fields:
|
||||
* api_major_version: the API version of the license. This is initialized to
|
||||
* the API version of the ODK library, but may be lower.
|
||||
* api_minor_version: the minor version of the ODK library. This is used by
|
||||
* the server to verify that device is not using an obsolete version of the
|
||||
* ODK library.
|
||||
* nonce: a randomly generated number used to prevent replay attacks.
|
||||
* session_id: the session id of the session which signed the license or
|
||||
* @param api_major_version: the API version of the license. This is initialized
|
||||
* to 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
|
||||
* by the server to verify that device is not using an obsolete version
|
||||
* of the ODK library.
|
||||
* @param nonce: a randomly generated number used to prevent replay attacks.
|
||||
* @param session_id: the session id of the session which signed the license or
|
||||
* provisioning request. It is used to prevent replay attacks from one
|
||||
* session to another.
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This struct changed in API version 16.2.
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -158,28 +154,30 @@ typedef struct {
|
||||
uint32_t session_id;
|
||||
} ODK_NonceValues;
|
||||
|
||||
/*
|
||||
* ODK_ParsedLicense Structure
|
||||
*
|
||||
* Description:
|
||||
/// @}
|
||||
|
||||
/// @addtogroup odk_parser
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* The parsed license structure contains information from the license
|
||||
* message. The function ODK_ParseLicense will fill in the fields of this
|
||||
* message. All substrings are contained within the message body.
|
||||
*
|
||||
* Fields:
|
||||
* enc_mac_keys_iv: IV for decrypting new mac_key. Size is 128 bits.
|
||||
* enc_mac_keys: encrypted mac_keys for generating new mac_keys. Size is 512
|
||||
* bits.
|
||||
* pst: the Provider Session Token.
|
||||
* srm_restriction_data: optional data specifying the minimum SRM version.
|
||||
* license_type: specifies if the license contains content keys or
|
||||
* @param 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
|
||||
* 512 bits.
|
||||
* @param pst: the Provider Session Token.
|
||||
* @param srm_restriction_data: optional data specifying the minimum SRM
|
||||
* version.
|
||||
* @param license_type: specifies if the license contains content keys or
|
||||
* entitlement keys.
|
||||
* nonce_required: indicates if the license requires a nonce.
|
||||
* timer_limits: time limits of the for the license.
|
||||
* key_array_length: number of keys present.
|
||||
* key_array: set of keys to be installed.
|
||||
* @param nonce_required: indicates if the license requires a nonce.
|
||||
* @param timer_limits: time limits of the for the license.
|
||||
* @param key_array_length: number of keys present.
|
||||
* @param key_array: set of keys to be installed.
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This struct changed in API version 16.2.
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -194,21 +192,18 @@ typedef struct {
|
||||
OEMCrypto_KeyObject key_array[ODK_MAX_NUM_KEYS];
|
||||
} ODK_ParsedLicense;
|
||||
|
||||
/*
|
||||
* ODK_ParsedProvisioning Structure
|
||||
*
|
||||
* Description:
|
||||
/**
|
||||
* The parsed provisioning structure contains information from the license
|
||||
* message. The function ODK_ParseProvisioning will fill in the fields of
|
||||
* this message. All substrings are contained within the message body.
|
||||
*
|
||||
* Fields:
|
||||
* key_type: indicates if this key is an RSA or ECC private key.
|
||||
* enc_private_key: encrypted private key for the DRM certificate.
|
||||
* enc_private_key_iv: IV for decrypting new private key. Size is 128 bits.
|
||||
* encrypted_message_key: used for provisioning 3.0 to derive keys.
|
||||
* @param key_type: indicates if this key is an RSA or ECC private key.
|
||||
* @param enc_private_key: encrypted private key for the DRM certificate.
|
||||
* @param enc_private_key_iv: IV for decrypting new private key. Size is 128
|
||||
* bits.
|
||||
* @param encrypted_message_key: used for provisioning 3.0 to derive keys.
|
||||
*
|
||||
* Version:
|
||||
* @version
|
||||
* This struct changed in API version 16.2.
|
||||
*/
|
||||
typedef struct {
|
||||
@@ -218,4 +213,6 @@ typedef struct {
|
||||
OEMCrypto_Substring encrypted_message_key; /* Used for Prov 3.0 */
|
||||
} ODK_ParsedProvisioning;
|
||||
|
||||
#endif /* WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_ */
|
||||
/// @}
|
||||
|
||||
#endif // WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* Copyright 2019 Google LLC. All rights reserved. This file is distributed */
|
||||
/* under the Widevine Master License Agreement. */
|
||||
// Copyright 2019 Google LLC. All rights reserved. This file is distributed
|
||||
// under the Widevine Master License Agreement.
|
||||
|
||||
/* Partners are expected to edit this file to support target specific code */
|
||||
/* and limits. */
|
||||
// Partners are expected to edit this file to support target specific code
|
||||
// and limits.
|
||||
|
||||
#ifndef 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
|
||||
|
||||
#endif /* WIDEVINE_ODK_INCLUDE_ODK_TARGET_H_ */
|
||||
#endif // WIDEVINE_ODK_INCLUDE_ODK_TARGET_H_
|
||||
|
||||
@@ -39,13 +39,11 @@ bool ParseRequest(uint32_t message_type,
|
||||
reinterpret_cast<const uint8_t*>(oemcrypto_core_message.c_str());
|
||||
const size_t buf_length = oemcrypto_core_message.size();
|
||||
|
||||
Message* msg = nullptr;
|
||||
AllocateMessage(&msg, message_block);
|
||||
InitMessage(msg, const_cast<uint8_t*>(buf), buf_length);
|
||||
SetSize(msg, buf_length);
|
||||
ODK_Message msg = ODK_Message_Create(const_cast<uint8_t*>(buf), buf_length);
|
||||
ODK_Message_SetSize(&msg, buf_length);
|
||||
|
||||
unpacker(msg, prepared);
|
||||
if (!ValidMessage(msg)) {
|
||||
unpacker(&msg, prepared);
|
||||
if (!ODK_Message_IsValid(&msg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -62,7 +60,7 @@ bool ParseRequest(uint32_t message_type,
|
||||
} else if (core_request->api_major_version == 16) {
|
||||
// For version 16, we demand a minor version of at least 2.
|
||||
// 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 {
|
||||
// Other versions do not (yet) have a restriction on minor number.
|
||||
// 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.
|
||||
// However, for future API versions, the release might be a separate
|
||||
// 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 &&
|
||||
core_message.message_type == ODK_Release_Request_Type)) {
|
||||
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
|
||||
// for forward compatibility because future messages might have extra fields
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -129,5 +128,13 @@ bool CoreProvisioningRequestFromMessage(
|
||||
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 oemcrypto_core_message
|
||||
|
||||
@@ -46,22 +46,23 @@ bool CreateResponse(uint32_t message_type, const S& core_request,
|
||||
if (core_request.api_major_version > ODK_MAJOR_VERSION) {
|
||||
header->nonce_values.api_major_version = ODK_MAJOR_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;
|
||||
std::vector<uint8_t> buf(BUF_CAPACITY, 0);
|
||||
Message* msg = nullptr;
|
||||
AllocateMessage(&msg, message_block);
|
||||
InitMessage(msg, buf.data(), buf.capacity());
|
||||
packer(msg, &response);
|
||||
if (!ValidMessage(msg)) {
|
||||
ODK_Message msg = ODK_Message_Create(buf.data(), buf.capacity());
|
||||
packer(&msg, &response);
|
||||
if (!ODK_Message_IsValid(&msg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t message_length = GetSize(msg);
|
||||
InitMessage(msg, buf.data() + sizeof(header->message_type),
|
||||
uint32_t message_length = ODK_Message_GetSize(&msg);
|
||||
msg = ODK_Message_Create(buf.data() + sizeof(header->message_type),
|
||||
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()),
|
||||
message_length);
|
||||
return true;
|
||||
|
||||
@@ -41,17 +41,23 @@ OEMCrypto_Substring GetOecSubstring(const std::string& message,
|
||||
}
|
||||
|
||||
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 = {};
|
||||
obj.key_id = GetOecSubstring(proto, k.id());
|
||||
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.
|
||||
const std::string& key_data = k.key();
|
||||
|
||||
OEMCrypto_Substring key_data = GetOecSubstring(proto, 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;
|
||||
obj.key_data = GetOecSubstring(
|
||||
proto, key_data.substr(0, std::max(PKCS5_PADDING_SIZE, key_data.size()) -
|
||||
PKCS5_PADDING_SIZE));
|
||||
key_data.length -= PKCS5_PADDING_SIZE;
|
||||
}
|
||||
obj.key_data = key_data;
|
||||
|
||||
if (k.has_key_control()) {
|
||||
const auto& key_control = k.key_control();
|
||||
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 std::string& core_request_sha256,
|
||||
const bool nonce_required,
|
||||
const bool uses_padding,
|
||||
std::string* oemcrypto_core_message) {
|
||||
video_widevine::License lic;
|
||||
if (!lic.ParseFromString(serialized_license)) {
|
||||
@@ -102,7 +109,8 @@ bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
default: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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.h"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
static OEMCryptoResult ODK_PrepareRequest(
|
||||
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) {
|
||||
if (nonce_values == NULL || core_message_length == NULL ||
|
||||
prepared_request_buffer == NULL ||
|
||||
@@ -27,9 +27,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
Message* msg = NULL;
|
||||
AllocateMessage(&msg, message_block);
|
||||
InitMessage(msg, message, *core_message_length);
|
||||
ODK_Message msg = ODK_Message_Create(message, *core_message_length);
|
||||
|
||||
/* The core message should be at the beginning of the buffer, and with a
|
||||
* shorter length. */
|
||||
@@ -52,7 +50,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedLicenseRequest(
|
||||
msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer);
|
||||
&msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Renewal_Request_Type: {
|
||||
@@ -61,7 +59,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedRenewalRequest(
|
||||
msg, (ODK_PreparedRenewalRequest*)prepared_request_buffer);
|
||||
&msg, (ODK_PreparedRenewalRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Provisioning_Request_Type: {
|
||||
@@ -71,7 +69,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedProvisioningRequest(
|
||||
msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
||||
&msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -80,13 +78,13 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
}
|
||||
|
||||
*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
|
||||
* appropriately set, but the message buffer is either empty or too small,
|
||||
* which needs to be initialized and filled in the subsequent call. */
|
||||
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. */
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
@@ -95,21 +93,18 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
|
||||
static OEMCryptoResult ODK_ParseResponse(
|
||||
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) {
|
||||
if (message == NULL || response_buffer == NULL ||
|
||||
core_message_length > message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
Message* msg = NULL;
|
||||
AllocateMessage(&msg, message_block);
|
||||
/* We initialize the message buffer with a size of the entire message
|
||||
* length. */
|
||||
InitMessage(msg, (uint8_t*)message, message_length);
|
||||
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||
|
||||
/* 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. */
|
||||
SetSize(msg, core_message_length);
|
||||
ODK_Message_SetSize(&msg, core_message_length);
|
||||
|
||||
/* Parse message and unpack it into response buffer. */
|
||||
switch (message_type) {
|
||||
@@ -117,14 +112,14 @@ static OEMCryptoResult ODK_ParseResponse(
|
||||
if (sizeof(ODK_LicenseResponse) > response_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Unpack_ODK_LicenseResponse(msg, (ODK_LicenseResponse*)response_buffer);
|
||||
Unpack_ODK_LicenseResponse(&msg, (ODK_LicenseResponse*)response_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Renewal_Response_Type: {
|
||||
if (sizeof(ODK_RenewalResponse) > response_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Unpack_ODK_RenewalResponse(msg, (ODK_RenewalResponse*)response_buffer);
|
||||
Unpack_ODK_RenewalResponse(&msg, (ODK_RenewalResponse*)response_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Provisioning_Response_Type: {
|
||||
@@ -132,7 +127,7 @@ static OEMCryptoResult ODK_ParseResponse(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Unpack_ODK_ProvisioningResponse(
|
||||
msg, (ODK_ProvisioningResponse*)response_buffer);
|
||||
&msg, (ODK_ProvisioningResponse*)response_buffer);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -141,9 +136,9 @@ static OEMCryptoResult ODK_ParseResponse(
|
||||
}
|
||||
|
||||
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 ||
|
||||
GetOffset(msg) != core_message->message_length) {
|
||||
ODK_Message_GetOffset(&msg) != core_message->message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
@@ -168,7 +163,7 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedLicenseRequest license_request = {
|
||||
{0},
|
||||
{0, 0, {}},
|
||||
};
|
||||
return ODK_PrepareRequest(
|
||||
message, message_length, core_message_length, ODK_License_Request_Type,
|
||||
@@ -197,7 +192,7 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
||||
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
|
||||
* clock. */
|
||||
if (clock_values->time_of_first_decrypt == 0) {
|
||||
@@ -231,14 +226,14 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedProvisioningRequest provisioning_request = {
|
||||
{0},
|
||||
{0, 0, {}},
|
||||
0,
|
||||
{0},
|
||||
};
|
||||
if (device_id_length > sizeof(provisioning_request.device_id)) {
|
||||
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) {
|
||||
memcpy(provisioning_request.device_id, device_id, device_id_length);
|
||||
}
|
||||
@@ -261,7 +256,9 @@ OEMCryptoResult ODK_ParseLicense(
|
||||
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(
|
||||
message, message_length, core_message_length, ODK_License_Response_Type,
|
||||
NULL, &license_response, sizeof(ODK_LicenseResponse));
|
||||
@@ -299,21 +296,25 @@ OEMCryptoResult ODK_ParseLicense(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
if (parsed_license->nonce_required) {
|
||||
if (initial_license_load) {
|
||||
/* If this is the first time we load this license, then we verify that the
|
||||
* 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 !=
|
||||
license_response.request.core_message.nonce_values.nonce ||
|
||||
nonce_values->session_id !=
|
||||
license_response.request.core_message.nonce_values.session_id) {
|
||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
} else { /* !initial_license_load */
|
||||
} else { /* !initial_license_load, or can't tell if initial. */
|
||||
nonce_values->nonce =
|
||||
license_response.request.core_message.nonce_values.nonce;
|
||||
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,
|
||||
* 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
|
||||
@@ -342,7 +343,7 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
||||
}
|
||||
|
||||
ODK_RenewalResponse renewal_response = {
|
||||
{{0}, 0},
|
||||
{{0, 0, {}}, 0},
|
||||
0,
|
||||
};
|
||||
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
|
||||
* 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) {
|
||||
return ODK_STALE_RENEWAL;
|
||||
}
|
||||
@@ -378,8 +382,9 @@ OEMCryptoResult ODK_ParseProvisioning(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
ODK_ProvisioningResponse provisioning_response = {{{0}, 0, {0}},
|
||||
parsed_response};
|
||||
ODK_ProvisioningResponse provisioning_response = {{{0, 0, {}}, 0, {0}}, NULL};
|
||||
provisioning_response.parsed_provisioning = parsed_response;
|
||||
|
||||
if (device_id_length > ODK_DEVICE_ID_LEN_MAX) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
{
|
||||
'sources': [
|
||||
'odk.c',
|
||||
'odk_message.c',
|
||||
'odk_overflow.c',
|
||||
'odk_serialize.c',
|
||||
'odk_timer.c',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_ASSERT_H_
|
||||
#define WIDEVINE_ODK_SRC_ODK_ASSERT_H_
|
||||
@@ -21,4 +21,4 @@ extern "C" {
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_ASSERT_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_ASSERT_H_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_ENDIAN_H_
|
||||
#define WIDEVINE_ODK_SRC_ODK_ENDIAN_H_
|
||||
@@ -26,4 +26,4 @@ uint64_t oemcrypto_be64toh(uint64_t u64);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_ENDIAN_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_ENDIAN_H_
|
||||
|
||||
163
oemcrypto/odk/src/odk_message.c
Normal file
163
oemcrypto/odk/src/odk_message.c
Normal 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;
|
||||
}
|
||||
41
oemcrypto/odk/src/odk_message_priv.h
Normal file
41
oemcrypto/odk/src/odk_message_priv.h
Normal 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_
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_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 /* WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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.
|
||||
|
||||
/*
|
||||
* This code is auto-generated, do not edit
|
||||
@@ -13,20 +13,20 @@
|
||||
|
||||
/* @@ 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_major_version);
|
||||
Pack_uint32_t(msg, &obj->nonce);
|
||||
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_length);
|
||||
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) {
|
||||
Pack_OEMCrypto_Substring(msg, &obj->key_id);
|
||||
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);
|
||||
}
|
||||
|
||||
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_playback_duration);
|
||||
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);
|
||||
}
|
||||
|
||||
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 */
|
||||
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
||||
SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||
ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
Pack_enum(msg, obj->key_type);
|
||||
Pack_OEMCrypto_Substring(msg, &obj->enc_private_key);
|
||||
@@ -74,19 +75,19 @@ static void Pack_ODK_ParsedProvisioning(Message* msg,
|
||||
|
||||
/* @@ odk serialize */
|
||||
|
||||
void Pack_ODK_PreparedLicenseRequest(Message* msg,
|
||||
void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||
ODK_PreparedLicenseRequest const* obj) {
|
||||
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
}
|
||||
|
||||
void Pack_ODK_PreparedRenewalRequest(Message* msg,
|
||||
void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||
ODK_PreparedRenewalRequest const* obj) {
|
||||
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
Pack_uint64_t(msg, &obj->playback_time);
|
||||
}
|
||||
|
||||
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_uint32_t(msg, &obj->device_id_length);
|
||||
PackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
||||
@@ -94,18 +95,20 @@ void Pack_ODK_PreparedProvisioningRequest(
|
||||
|
||||
/* @@ 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_ParsedLicense(msg, (const ODK_ParsedLicense*)obj->parsed_license);
|
||||
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_uint64_t(msg, &obj->renewal_duration_seconds);
|
||||
}
|
||||
|
||||
void Pack_ODK_ProvisioningResponse(Message* msg,
|
||||
void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||
ODK_ProvisioningResponse const* obj) {
|
||||
Pack_ODK_PreparedProvisioningRequest(msg, &obj->request);
|
||||
Pack_ODK_ParsedProvisioning(
|
||||
@@ -116,20 +119,21 @@ void Pack_ODK_ProvisioningResponse(Message* msg,
|
||||
|
||||
/* @@ 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_major_version);
|
||||
Unpack_uint32_t(msg, &obj->nonce);
|
||||
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_length);
|
||||
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_data_iv);
|
||||
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);
|
||||
}
|
||||
|
||||
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_playback_duration);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
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_uint32_t(msg, &obj->key_array_length);
|
||||
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
||||
SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||
ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
obj->key_type = (OEMCrypto_PrivateKeyType)Unpack_enum(msg);
|
||||
Unpack_OEMCrypto_Substring(msg, &obj->enc_private_key);
|
||||
@@ -175,38 +179,42 @@ static void Unpack_ODK_ParsedProvisioning(Message* msg,
|
||||
|
||||
/* @ kdo deserialize */
|
||||
|
||||
void Unpack_ODK_PreparedLicenseRequest(Message* msg,
|
||||
void Unpack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||
ODK_PreparedLicenseRequest* obj) {
|
||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
}
|
||||
|
||||
void Unpack_ODK_PreparedRenewalRequest(Message* msg,
|
||||
void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||
ODK_PreparedRenewalRequest* obj) {
|
||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
Unpack_uint64_t(msg, &obj->playback_time);
|
||||
}
|
||||
|
||||
void Unpack_ODK_PreparedProvisioningRequest(
|
||||
Message* msg, ODK_PreparedProvisioningRequest* obj) {
|
||||
ODK_Message* msg, ODK_PreparedProvisioningRequest* obj) {
|
||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
Unpack_uint32_t(msg, &obj->device_id_length);
|
||||
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 */
|
||||
|
||||
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_ParsedLicense(msg, obj->parsed_license);
|
||||
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_uint64_t(msg, &obj->renewal_duration_seconds);
|
||||
}
|
||||
|
||||
void Unpack_ODK_ProvisioningResponse(Message* msg,
|
||||
void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||
ODK_ProvisioningResponse* obj) {
|
||||
Unpack_ODK_PreparedProvisioningRequest(msg, &obj->request);
|
||||
Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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.
|
||||
|
||||
/*
|
||||
* This code is auto-generated, do not edit
|
||||
@@ -16,34 +16,37 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* odk pack */
|
||||
void Pack_ODK_PreparedLicenseRequest(Message* msg,
|
||||
void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||
const ODK_PreparedLicenseRequest* obj);
|
||||
void Pack_ODK_PreparedRenewalRequest(Message* msg,
|
||||
void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||
const ODK_PreparedRenewalRequest* obj);
|
||||
void Pack_ODK_PreparedProvisioningRequest(
|
||||
Message* msg, const ODK_PreparedProvisioningRequest* obj);
|
||||
ODK_Message* msg, const ODK_PreparedProvisioningRequest* obj);
|
||||
|
||||
/* odk unpack */
|
||||
void Unpack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse* obj);
|
||||
void Unpack_ODK_RenewalResponse(Message* msg, ODK_RenewalResponse* obj);
|
||||
void Unpack_ODK_ProvisioningResponse(Message* msg,
|
||||
void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj);
|
||||
void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj);
|
||||
void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||
ODK_ProvisioningResponse* obj);
|
||||
|
||||
/* kdo pack */
|
||||
void Pack_ODK_LicenseResponse(Message* msg, const ODK_LicenseResponse* obj);
|
||||
void Pack_ODK_RenewalResponse(Message* msg, const ODK_RenewalResponse* obj);
|
||||
void Pack_ODK_ProvisioningResponse(Message* msg,
|
||||
void Pack_ODK_LicenseResponse(ODK_Message* msg, const ODK_LicenseResponse* obj);
|
||||
void Pack_ODK_RenewalResponse(ODK_Message* msg, const ODK_RenewalResponse* obj);
|
||||
void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||
const ODK_ProvisioningResponse* obj);
|
||||
|
||||
/* kdo unpack */
|
||||
void Unpack_ODK_PreparedLicenseRequest(Message* msg,
|
||||
void Unpack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||
ODK_PreparedLicenseRequest* obj);
|
||||
void Unpack_ODK_PreparedRenewalRequest(Message* msg,
|
||||
void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||
ODK_PreparedRenewalRequest* obj);
|
||||
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
|
||||
} /* extern "C" */
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_STRUCTS_PRIV_H_
|
||||
#define WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_
|
||||
@@ -22,9 +22,11 @@ typedef enum {
|
||||
ODK_Provisioning_Request_Type = 5,
|
||||
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_Response_Type = 8,
|
||||
ODK_Common_Request_Type = 9,
|
||||
ODK_Common_Response_Type = 10,
|
||||
} ODK_MessageType;
|
||||
|
||||
typedef struct {
|
||||
@@ -48,6 +50,10 @@ typedef struct {
|
||||
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX];
|
||||
} ODK_PreparedProvisioningRequest;
|
||||
|
||||
typedef struct {
|
||||
ODK_CoreMessage core_message;
|
||||
} ODK_PreparedCommonRequest;
|
||||
|
||||
typedef struct {
|
||||
ODK_PreparedLicenseRequest request;
|
||||
ODK_ParsedLicense* parsed_license;
|
||||
@@ -64,33 +70,32 @@ typedef struct {
|
||||
ODK_ParsedProvisioning* parsed_provisioning;
|
||||
} ODK_ProvisioningResponse;
|
||||
|
||||
/* 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 */
|
||||
/* request structs change. Refer to test suite OdkSizeTest in */
|
||||
/* ../test/odk_test.cpp for validations of each of the defined request sizes. */
|
||||
// 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
|
||||
// request structs change. Refer to test suite OdkSizeTest in
|
||||
// ../test/odk_test.cpp for validations of each of the defined request sizes.
|
||||
#define ODK_LICENSE_REQUEST_SIZE 20
|
||||
#define ODK_RENEWAL_REQUEST_SIZE 28
|
||||
#define ODK_PROVISIONING_REQUEST_SIZE 88
|
||||
|
||||
/* These are the possible timer status values. */
|
||||
#define ODK_CLOCK_TIMER_STATUS_UNDEFINED 0 /* Should not happen. */
|
||||
/* When the structure has been initialized, but no license is loaded. */
|
||||
// These are the possible timer status values.
|
||||
#define ODK_CLOCK_TIMER_STATUS_UNDEFINED 0 // Should not happen.
|
||||
// When the structure has been initialized, but no license is loaded.
|
||||
#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
|
||||
/* 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
|
||||
/* 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
|
||||
/* 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
|
||||
/* The timer has transitioned from active to expired. */
|
||||
// The timer has transitioned from active to expired.
|
||||
#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
|
||||
|
||||
/* 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,
|
||||
ODK_ClockValues* clock_values,
|
||||
uint64_t system_time_seconds,
|
||||
@@ -101,4 +106,4 @@ OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/* 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. */
|
||||
// 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "odk.h"
|
||||
#include "odk_attributes.h"
|
||||
#include "odk_overflow.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_last_decrypt,
|
||||
enum OEMCrypto_Usage_Entry_Status status,
|
||||
uint64_t system_time_seconds) {
|
||||
uint64_t system_time_seconds UNUSED) {
|
||||
if (clock_values == NULL) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_util.h"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_UTIL_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_UTIL_H_
|
||||
|
||||
@@ -1,82 +1,63 @@
|
||||
/* 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. */
|
||||
// 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 "serialization_base.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "OEMCryptoCENCCommon.h"
|
||||
#include "odk_assert.h"
|
||||
#include "odk_message.h"
|
||||
#include "odk_message_priv.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),
|
||||
* "SIZE_OF_MESSAGE_STRUCT too small");
|
||||
* An ODK_Message_Impl pointer must only be obtained by calling GetMessageImpl.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
bool ValidMessage(Message* message) {
|
||||
if (message == NULL) {
|
||||
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 ODK_Message_Impl* GetMessageImpl(ODK_Message* message) {
|
||||
if (!ODK_Message_IsValid(message)) return NULL;
|
||||
return (ODK_Message_Impl*)message;
|
||||
}
|
||||
|
||||
static void PackBytes(Message* message, const uint8_t* ptr, size_t count) {
|
||||
if (count <= message->capacity - message->size) {
|
||||
memcpy((void*)(message->base + message->size), (void*)ptr, count);
|
||||
message->size += count;
|
||||
static void PackBytes(ODK_Message* message, const uint8_t* ptr, size_t count) {
|
||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||
if (!message_impl) return;
|
||||
if (count <= message_impl->capacity - message_impl->size) {
|
||||
memcpy((void*)(message_impl->base + message_impl->size), (void*)ptr, count);
|
||||
message_impl->size += count;
|
||||
} 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;
|
||||
Pack_uint32_t(message, &v32);
|
||||
}
|
||||
|
||||
void Pack_bool(Message* message, const bool* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_bool(ODK_Message* message, const bool* value) {
|
||||
assert(value);
|
||||
uint8_t data[4] = {0};
|
||||
data[3] = *value ? 1 : 0;
|
||||
PackBytes(message, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Pack_uint16_t(Message* message, const uint16_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_uint16_t(ODK_Message* message, const uint16_t* value) {
|
||||
assert(value);
|
||||
uint8_t data[2] = {0};
|
||||
data[0] = *value >> 8;
|
||||
data[1] = *value >> 0;
|
||||
PackBytes(message, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Pack_uint32_t(Message* message, const uint32_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_uint32_t(ODK_Message* message, const uint32_t* value) {
|
||||
assert(value);
|
||||
uint8_t data[4] = {0};
|
||||
data[0] = *value >> 24;
|
||||
data[1] = *value >> 16;
|
||||
@@ -85,175 +66,112 @@ void Pack_uint32_t(Message* message, const uint32_t* value) {
|
||||
PackBytes(message, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Pack_uint64_t(Message* message, const uint64_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_uint64_t(ODK_Message* message, const uint64_t* value) {
|
||||
assert(value);
|
||||
uint32_t hi = *value >> 32;
|
||||
uint32_t lo = *value;
|
||||
Pack_uint32_t(message, &hi);
|
||||
Pack_uint32_t(message, &lo);
|
||||
}
|
||||
|
||||
void PackArray(Message* message, const uint8_t* base, size_t size) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void PackArray(ODK_Message* message, const uint8_t* base, size_t size) {
|
||||
PackBytes(message, base, size);
|
||||
}
|
||||
|
||||
void Pack_OEMCrypto_Substring(Message* msg, const OEMCrypto_Substring* obj) {
|
||||
uint32_t offset = obj->offset;
|
||||
uint32_t length = obj->length;
|
||||
Pack_uint32_t(msg, &offset);
|
||||
Pack_uint32_t(msg, &length);
|
||||
void Pack_OEMCrypto_Substring(ODK_Message* message,
|
||||
const OEMCrypto_Substring* obj) {
|
||||
assert(obj);
|
||||
uint32_t offset = (uint32_t)obj->offset;
|
||||
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) {
|
||||
if (count <= message->size - message->read_offset) {
|
||||
memcpy((void*)ptr, (void*)(message->base + message->read_offset), count);
|
||||
message->read_offset += count;
|
||||
static void UnpackBytes(ODK_Message* message, uint8_t* ptr, size_t count) {
|
||||
assert(ptr);
|
||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||
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 {
|
||||
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;
|
||||
Unpack_uint32_t(message, &v32);
|
||||
return v32;
|
||||
}
|
||||
|
||||
void Unpack_bool(Message* message, bool* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_bool(ODK_Message* message, bool* value) {
|
||||
uint8_t data[4] = {0};
|
||||
UnpackBytes(message, data, sizeof(data));
|
||||
assert(value);
|
||||
*value = (0 != data[3]);
|
||||
}
|
||||
|
||||
void Unpack_uint16_t(Message* message, uint16_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_uint16_t(ODK_Message* message, uint16_t* value) {
|
||||
assert(value);
|
||||
uint8_t data[2] = {0};
|
||||
UnpackBytes(message, data, sizeof(data));
|
||||
*value = data[0];
|
||||
*value = *value << 8 | data[1];
|
||||
}
|
||||
|
||||
void Unpack_uint32_t(Message* message, uint32_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_uint32_t(ODK_Message* message, uint32_t* value) {
|
||||
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||
if (!message_impl) return;
|
||||
uint8_t data[4] = {0};
|
||||
UnpackBytes(message, data, sizeof(data));
|
||||
assert(value);
|
||||
*value = data[0];
|
||||
*value = *value << 8 | data[1];
|
||||
*value = *value << 8 | data[2];
|
||||
*value = *value << 8 | data[3];
|
||||
}
|
||||
|
||||
void Unpack_uint64_t(Message* message, uint64_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_uint64_t(ODK_Message* message, uint64_t* value) {
|
||||
uint32_t hi = 0;
|
||||
uint32_t lo = 0;
|
||||
Unpack_uint32_t(message, &hi);
|
||||
Unpack_uint32_t(message, &lo);
|
||||
assert(value);
|
||||
*value = hi;
|
||||
*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;
|
||||
Unpack_uint32_t(msg, &offset);
|
||||
Unpack_uint32_t(msg, &length);
|
||||
if (!ValidMessage(msg)) return;
|
||||
Unpack_uint32_t(message, &offset);
|
||||
Unpack_uint32_t(message, &length);
|
||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||
if (!message_impl) return;
|
||||
|
||||
/* 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
|
||||
* relative to the message body. So we need to verify:
|
||||
* 0 < offset and offset + length < message->capacity - message->size
|
||||
* or offset + length + message->size < message->capacity
|
||||
* 0 < offset and offset + length < message_impl->capacity -
|
||||
* message_impl->size or offset + length + message_impl->size <
|
||||
* message_impl->capacity
|
||||
*/
|
||||
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) ||
|
||||
odk_add_overflow_ux(substring_end, msg->size, &end) ||
|
||||
end > msg->capacity) {
|
||||
msg->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
odk_add_overflow_ux(substring_end, message_impl->size, &end) ||
|
||||
end > message_impl->capacity) {
|
||||
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
return;
|
||||
}
|
||||
assert(obj);
|
||||
obj->offset = offset;
|
||||
obj->length = length;
|
||||
}
|
||||
|
||||
/* copy out */
|
||||
void UnpackArray(Message* message, uint8_t* address, size_t size) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void UnpackArray(ODK_Message* message, uint8_t* address, size_t 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); }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_SERIALIZATION_BASE_H_
|
||||
#define WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
|
||||
@@ -13,84 +13,28 @@ extern "C" {
|
||||
#include <stdint.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);
|
||||
|
||||
/*
|
||||
* Description:
|
||||
* Point |msg| to stack-array |blk|.
|
||||
* |blk| is guaranteed large enough to hold a |Message| struct.
|
||||
* |blk| cannot be used in the same scope as a variable name.
|
||||
* |msg| points to valid memory in the same scope |AllocateMessage| is used.
|
||||
* 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,
|
||||
int Unpack_enum(ODK_Message* message);
|
||||
void Unpack_bool(ODK_Message* message, bool* value);
|
||||
void Unpack_uint16_t(ODK_Message* message, uint16_t* value);
|
||||
void Unpack_uint32_t(ODK_Message* message, uint32_t* value);
|
||||
void Unpack_uint64_t(ODK_Message* message, uint64_t* value);
|
||||
void UnpackArray(ODK_Message* message, uint8_t* address,
|
||||
size_t size); /* copy out */
|
||||
void Unpack_OEMCrypto_Substring(Message* msg, 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();
|
||||
void Unpack_OEMCrypto_Substring(ODK_Message* message, OEMCrypto_Substring* obj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */
|
||||
/* source code may only be used and distributed under the Widevine Master */
|
||||
/* License Agreement. */
|
||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// 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
|
||||
|
||||
#include <dlfcn.h>
|
||||
@@ -21,7 +21,7 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
||||
message, message_length, core_message_length, nonce_values);
|
||||
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);
|
||||
free(file_name);
|
||||
return oem_crypto_result;
|
||||
@@ -50,9 +50,8 @@ OEMCryptoResult ODK_ParseLicense(
|
||||
nonce_values, parsed_license);
|
||||
char* file_name = GetFileName("license_response_corpus");
|
||||
|
||||
/* License Response format expected by fuzzer - [ODK_ParseLicense_Args][Core
|
||||
*/
|
||||
/* License Response] */
|
||||
// License Response format expected by fuzzer - [ODK_ParseLicense_Args][Core
|
||||
// License Response]
|
||||
AppendToFile(file_name, (const char*)&parse_license_args,
|
||||
sizeof(struct ODK_ParseLicense_Args));
|
||||
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);
|
||||
char* file_name = GetFileName("renewal_request_corpus");
|
||||
|
||||
/* License Request format expected by fuzzer - [ODK_ClockValues][Core */
|
||||
/* License Request] */
|
||||
// License Request format expected by fuzzer - [ODK_ClockValues][Core
|
||||
// License Request]
|
||||
AppendToFile(file_name, (const char*)clock_values, sizeof(ODK_ClockValues));
|
||||
AppendToFile(file_name, (const char*)message, *core_message_size);
|
||||
free(file_name);
|
||||
@@ -103,9 +102,8 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
||||
timer_limits, clock_values, timer_value);
|
||||
char* file_name = GetFileName("renewal_response_corpus");
|
||||
|
||||
/* Renewal Response format expected by fuzzer - [ODK_ParseRenewal_Args][Core
|
||||
*/
|
||||
/* Renewal Response] */
|
||||
// Renewal Response format expected by fuzzer - [ODK_ParseRenewal_Args][Core
|
||||
// Renewal Response]
|
||||
AppendToFile(file_name, (const char*)&parse_renewal_args,
|
||||
sizeof(struct ODK_ParseRenewal_Args));
|
||||
AppendToFile(file_name, (const char*)message, core_message_length);
|
||||
@@ -126,8 +124,8 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
||||
nonce_values, device_id, device_id_length);
|
||||
char* file_name = GetFileName("provisioning_request_corpus");
|
||||
|
||||
/* Provisioning Request format expected by fuzzer - [Core Provisioning */
|
||||
/* Request] */
|
||||
// Provisioning Request format expected by fuzzer - [Core Provisioning
|
||||
// Request]
|
||||
AppendToFile(file_name, (const char*)message, *core_message_length);
|
||||
free(file_name);
|
||||
return oem_crypto_result;
|
||||
@@ -150,8 +148,8 @@ OEMCryptoResult ODK_ParseProvisioning(
|
||||
device_id_length, parsed_response);
|
||||
char* file_name = GetFileName("provisioning_response_corpus");
|
||||
|
||||
/* Provisioning Response format expected by fuzzer - */
|
||||
/* [ODK_ParseProvisioning_Args][Core Provisioning Response] */
|
||||
// Provisioning Response format expected by fuzzer -
|
||||
// [ODK_ParseProvisioning_Args][Core Provisioning Response]
|
||||
AppendToFile(file_name, (const char*)&parse_provisioning_args,
|
||||
sizeof(struct ODK_ParseProvisioning_Args));
|
||||
AppendToFile(file_name, (const char*)message, core_message_length);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */
|
||||
/* source code may only be used and distributed under the Widevine Master */
|
||||
/* License Agreement. */
|
||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
#include "fuzzing/corpus_generator/odk_corpus_generator_helper.h"
|
||||
|
||||
void AppendToFile(const char* file_name, const char* message,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */
|
||||
/* source code may only be used and distributed under the Widevine Master */
|
||||
/* License Agreement. */
|
||||
// Copyright 2020 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_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);
|
||||
|
||||
#endif /* WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_ \
|
||||
*/
|
||||
#endif // WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_
|
||||
|
||||
@@ -28,13 +28,13 @@ void ConvertDataToValidBools(ODK_ParsedLicense* t) {
|
||||
&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(
|
||||
const void* in, uint8_t* out, size_t* size,
|
||||
const ODK_LicenseRequest& core_license_request,
|
||||
const void* in UNUSED, uint8_t* out, size_t* size,
|
||||
const ODK_LicenseRequest& core_license_request UNUSED,
|
||||
const ODK_NonceValues* nonce_values) {
|
||||
return ODK_PrepareCoreLicenseRequest(out, SIZE_MAX, size, nonce_values);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ OEMCryptoResult odk_serialize_RenewalRequest(
|
||||
}
|
||||
|
||||
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_NonceValues* nonce_values) {
|
||||
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.
|
||||
// playback_time cannot be captured from publicly exposed API
|
||||
// ODK_ParseRenewal.
|
||||
Message* msg = nullptr;
|
||||
AllocateMessage(&msg, message_block);
|
||||
InitMessage(msg, const_cast<uint8_t*>(buf), len);
|
||||
SetSize(msg, len);
|
||||
Unpack_ODK_PreparedRenewalRequest(msg, renewal_msg);
|
||||
ODK_Message msg = ODK_Message_Create(const_cast<uint8_t*>(buf), len);
|
||||
ODK_Message_SetSize(&msg, len);
|
||||
Unpack_ODK_PreparedRenewalRequest(&msg, renewal_msg);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */
|
||||
/* source code may only be used and distributed under the Widevine Master */
|
||||
/* License Agreement. */
|
||||
// Copyright 2020 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_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 "fuzzing/odk_fuzz_structs.h"
|
||||
#include "odk_attributes.h"
|
||||
#include "odk_serialize.h"
|
||||
|
||||
namespace oemcrypto_core_message {
|
||||
@@ -56,24 +57,23 @@ bool kdo_serialize_ProvisioningResponse(
|
||||
const ODK_ParsedProvisioning& parsed_prov,
|
||||
std::string* oemcrypto_core_message);
|
||||
|
||||
/* Idea behind having three different functions is: */
|
||||
/* Only ODK_ParseLicense structure had fields which needed additional */
|
||||
/* procession. Having a single function with templated parameter T was */
|
||||
/* failing during compile time because other two structures doesn't have */
|
||||
/* fields that need additional processing. Hence to reduce code redundance and
|
||||
*/
|
||||
/* make us of common FuzzerMutateResponse across three response fuzzers, */
|
||||
/* three independent functions were defined and renewal and provisioning */
|
||||
/* functions would be empty as no additional processing is needed for them. */
|
||||
// Idea behind having three different functions is:
|
||||
// Only ODK_ParseLicense structure had fields which needed additional
|
||||
// procession. Having a single function with templated parameter T was
|
||||
// failing during compile time because other two structures doesn't have
|
||||
// fields that need additional processing. Hence to reduce code redundance and
|
||||
// make us of common FuzzerMutateResponse across three response fuzzers,
|
||||
// three independent functions were defined and renewal and provisioning
|
||||
// functions would be empty as no additional processing is needed for them.
|
||||
void ConvertDataToValidBools(ODK_ParsedLicense* t);
|
||||
|
||||
void ConvertDataToValidBools(ODK_PreparedRenewalRequest* t);
|
||||
|
||||
void ConvertDataToValidBools(ODK_ParsedProvisioning* t);
|
||||
|
||||
/* Forward-declare the libFuzzer's mutator callback. Mark it weak so that */
|
||||
/* the program links successfully even outside of --config=asan-fuzzer */
|
||||
/* (apparently the only config in which LLVM uses our custom mutator). */
|
||||
// Forward-declare the libFuzzer's mutator callback. Mark it weak so that
|
||||
// the program links successfully even outside of --config=asan-fuzzer
|
||||
// (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)
|
||||
__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 kTotalResponseSize = kArgsSize + kCoreResponseSize;
|
||||
|
||||
/* Deserializing data in order to make sure it deserializes properly. */
|
||||
/* Input byte array format: [function arguments][data to parse]. */
|
||||
// Deserializing data in order to make sure it deserializes properly.
|
||||
// Input byte array format: [function arguments][data to parse].
|
||||
std::shared_ptr<A> _args(new A());
|
||||
A* args = _args.get();
|
||||
memcpy(args, data, kArgsSize);
|
||||
@@ -97,17 +97,16 @@ size_t FuzzerMutateResponse(uint8_t* data, size_t size, size_t max_size,
|
||||
OEMCryptoResult result =
|
||||
odk_deserialize_fun(buf, size - kArgsSize, args, &nonce_values, &t);
|
||||
|
||||
/* If data doesn't deserialize successfully, We copy random bytes into */
|
||||
/* T and serialize using kdo function */
|
||||
/* which will create a valid oemcrypto core message using */
|
||||
/* nonce and request hash from function args. OEMCrypto core message acts as
|
||||
*/
|
||||
/* input to odk_kdo. */
|
||||
// If data doesn't deserialize successfully, We copy random bytes into
|
||||
// T and serialize using kdo function
|
||||
// which will create a valid oemcrypto core message using
|
||||
// nonce and request hash from function args. OEMCrypto core message acts as
|
||||
// input to odk_kdo.
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
if (max_size < kTotalResponseSize) {
|
||||
return 0;
|
||||
}
|
||||
/* Initialize remaining bytes needed in data to zero. */
|
||||
// Initialize remaining bytes needed in data to zero.
|
||||
if (size < kTotalResponseSize) {
|
||||
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);
|
||||
}
|
||||
|
||||
/* Ask LLVM to run its usual mutations, hopefully giving us interesting */
|
||||
/* inputs. We copy deserialized data into pointer data, run mutations */
|
||||
/* and copy back the mutated data to args and t */
|
||||
// Ask LLVM to run its usual mutations, hopefully giving us interesting
|
||||
// inputs. We copy deserialized data into pointer data, run mutations
|
||||
// and copy back the mutated data to args and t
|
||||
memcpy(data + kArgsSize, &t, kCoreResponseSize);
|
||||
LLVMFuzzerMutate(data, kTotalResponseSize, kTotalResponseSize);
|
||||
memcpy(args, data, kArgsSize);
|
||||
memcpy(&t, data + kArgsSize, kCoreResponseSize);
|
||||
/* Convert boolean flags in parsed message to valid bytes to */
|
||||
/* avoid errors from msan. Only needed for parsed license. */
|
||||
// Convert boolean flags in parsed message to valid bytes to
|
||||
// avoid errors from msan. Only needed for parsed license.
|
||||
ConvertDataToValidBools(&t);
|
||||
/* Serialize the data after mutation. */
|
||||
// Serialize the data after mutation.
|
||||
std::string oemcrypto_core_message;
|
||||
if (!kdo_serialize_fun(args, t, &oemcrypto_core_message)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy mutated and serialized oemcrypto_core_message to data */
|
||||
/* so that it acts as input to odk_kdo function. */
|
||||
// Copy mutated and serialized oemcrypto_core_message to data
|
||||
// so that it acts as input to odk_kdo function.
|
||||
memcpy(data + kArgsSize, oemcrypto_core_message.data(),
|
||||
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>
|
||||
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 = {};
|
||||
/* Input byte array format: [function arguments][data to parse] */
|
||||
// Input byte array format: [function arguments][data to parse]
|
||||
if (size < args_size) {
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
/* Input byte array format: [Clock Values][data to parse]. */
|
||||
/* Only Renewal Request expects clock values to be present. */
|
||||
// Input byte array format: [Clock Values][data to parse].
|
||||
// Only Renewal Request expects clock values to be present.
|
||||
std::string input(reinterpret_cast<const char*>(in) + clock_value_size,
|
||||
size - clock_value_size);
|
||||
T t = {};
|
||||
@@ -202,5 +201,5 @@ static void kdo_odk(const F& kdo_fun, const G& odk_fun, const uint8_t* in,
|
||||
return;
|
||||
}
|
||||
}
|
||||
} /* namespace oemcrypto_core_message */
|
||||
#endif /* WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_ */
|
||||
} // namespace oemcrypto_core_message
|
||||
#endif // WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */
|
||||
/* source code may only be used and distributed under the Widevine Master */
|
||||
/* License Agreement. */
|
||||
// Copyright 2020 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_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;
|
||||
uint8_t device_id[64];
|
||||
};
|
||||
#endif /* WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_ */
|
||||
#endif // WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_
|
||||
|
||||
@@ -12,7 +12,8 @@ namespace oemcrypto_core_message {
|
||||
// The custom mutator: Ensure that each input can be deserialized properly
|
||||
// by ODK function after mutation.
|
||||
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);
|
||||
if (size < kLicenseResponseArgsSize) {
|
||||
return 0;
|
||||
|
||||
@@ -35,6 +35,16 @@ using oemcrypto_core_message::serialize::CreateCoreRenewalResponse;
|
||||
|
||||
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>
|
||||
void ValidateRequest(uint32_t message_type,
|
||||
const std::vector<ODK_Field>& extra_fields,
|
||||
@@ -113,12 +123,13 @@ void ValidateRequest(uint32_t message_type,
|
||||
* G: kdo serializer
|
||||
*/
|
||||
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 F& odk_parse_func, const G& kdo_prepare_func) {
|
||||
T t = {};
|
||||
t.api_minor_version = core_message->nonce_values.api_minor_version;
|
||||
t.api_major_version = core_message->nonce_values.api_major_version;
|
||||
t.api_major_version = versions.request_major_version;
|
||||
t.api_minor_version = versions.request_minor_version;
|
||||
t.nonce = core_message->nonce_values.nonce;
|
||||
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,
|
||||
&bytes_read, extra_fields));
|
||||
|
||||
// parse buf with odk
|
||||
// Parse buf with odk
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, odk_parse_func(buf, buf_size));
|
||||
|
||||
size_t size_out = 0;
|
||||
@@ -209,8 +220,10 @@ TEST(OdkTest, SerializeFieldsStress) {
|
||||
|
||||
TEST(OdkTest, NullRequestTest) {
|
||||
size_t core_message_length = 0;
|
||||
ODK_NonceValues nonce_values{0};
|
||||
ODK_ClockValues clock_values{0};
|
||||
ODK_NonceValues nonce_values;
|
||||
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.
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, ODK_PrepareCoreLicenseRequest(
|
||||
@@ -250,10 +263,12 @@ TEST(OdkTest, NullResponseTest) {
|
||||
uint8_t message[message_size] = {0};
|
||||
size_t core_message_length = message_size;
|
||||
uint8_t request_hash[ODK_SHA256_HASH_SIZE] = {0};
|
||||
ODK_TimerLimits timer_limits{0};
|
||||
ODK_TimerLimits timer_limits;
|
||||
ODK_ParsedLicense parsed_license;
|
||||
ODK_NonceValues nonce_values{0};
|
||||
ODK_ClockValues clock_values{0};
|
||||
ODK_NonceValues nonce_values;
|
||||
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.
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||
@@ -322,7 +337,8 @@ TEST(OdkTest, NullResponseTest) {
|
||||
TEST(OdkTest, PrepareCoreLicenseRequest) {
|
||||
uint8_t license_message[ODK_LICENSE_REQUEST_SIZE] = {0};
|
||||
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(
|
||||
license_message, sizeof(license_message),
|
||||
&core_message_length, &nonce_values));
|
||||
@@ -331,7 +347,8 @@ TEST(OdkTest, PrepareCoreLicenseRequest) {
|
||||
TEST(OdkTest, PrepareCoreLicenseRequestSize) {
|
||||
uint8_t license_message[ODK_LICENSE_REQUEST_SIZE] = {0};
|
||||
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
|
||||
size_t core_message_length_invalid = core_message_length + 1;
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||
@@ -349,8 +366,10 @@ TEST(OdkTest, PrepareCoreLicenseRequestSize) {
|
||||
TEST(OdkTest, PrepareCoreRenewalRequest) {
|
||||
uint8_t renewal_message[ODK_RENEWAL_REQUEST_SIZE] = {0};
|
||||
size_t core_message_length = sizeof(renewal_message);
|
||||
ODK_NonceValues nonce_values{0};
|
||||
ODK_ClockValues clock_values{0};
|
||||
ODK_NonceValues nonce_values;
|
||||
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;
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
ODK_PrepareCoreRenewalRequest(
|
||||
@@ -363,7 +382,8 @@ TEST(OdkTest, PrepareCoreRenewalRequestTimer) {
|
||||
size_t core_message_length = sizeof(renewal_message);
|
||||
ODK_NonceValues nonce_values{2, 16, 0, 0};
|
||||
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
|
||||
clock_values_updated.time_of_first_decrypt = system_time_seconds + 1;
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||
@@ -383,7 +403,8 @@ TEST(OdkTest, PrepareCoreRenewalRequestTimer) {
|
||||
TEST(OdkTest, PrepareCoreProvisioningRequest) {
|
||||
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
|
||||
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};
|
||||
EXPECT_EQ(
|
||||
OEMCrypto_SUCCESS,
|
||||
@@ -395,7 +416,8 @@ TEST(OdkTest, PrepareCoreProvisioningRequest) {
|
||||
TEST(OdkTest, PrepareCoreProvisioningRequestDeviceId) {
|
||||
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
|
||||
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};
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||
ODK_PrepareCoreProvisioningRequest(
|
||||
@@ -423,7 +445,8 @@ TEST(OdkTest, RenewalRequestRoundtrip) {
|
||||
const std::vector<ODK_Field> extra_fields = {
|
||||
{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;
|
||||
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
|
||||
ODK_NonceValues* nonce_values) {
|
||||
@@ -550,10 +573,23 @@ TEST(OdkTest, ParsePrivisioningErrorDeviceId) {
|
||||
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
|
||||
TEST(OdkTest, LicenseResponseRoundtrip) {
|
||||
TEST_P(OdkVersionTest, LicenseResponseRoundtrip) {
|
||||
ODK_LicenseResponseParams params;
|
||||
ODK_SetDefaultLicenseResponseParams(¶ms);
|
||||
SetRequestVersion(¶ms);
|
||||
// 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];
|
||||
memcpy(request_hash_read, params.request_hash, sizeof(request_hash_read));
|
||||
@@ -573,14 +609,15 @@ TEST(OdkTest, LicenseResponseRoundtrip) {
|
||||
request_hash_string,
|
||||
oemcrypto_core_message);
|
||||
};
|
||||
ValidateResponse<ODK_LicenseRequest>(&(params.core_message),
|
||||
ValidateResponse<ODK_LicenseRequest>(GetParam(), &(params.core_message),
|
||||
params.extra_fields, odk_parse_func,
|
||||
kdo_prepare_func);
|
||||
}
|
||||
|
||||
TEST(OdkTest, RenewalResponseRoundtrip) {
|
||||
TEST_P(OdkVersionTest, RenewalResponseRoundtrip) {
|
||||
ODK_RenewalResponseParams params;
|
||||
ODK_SetDefaultRenewalResponseParams(¶ms);
|
||||
SetRequestVersion(¶ms);
|
||||
const uint64_t playback_clock = params.playback_clock;
|
||||
const uint64_t renewal_duration = params.renewal_duration;
|
||||
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
|
||||
@@ -602,14 +639,15 @@ TEST(OdkTest, RenewalResponseRoundtrip) {
|
||||
return CreateCoreRenewalResponse(core_request, renewal_duration,
|
||||
oemcrypto_core_message);
|
||||
};
|
||||
ValidateResponse<ODK_RenewalRequest>(&(params.core_message),
|
||||
ValidateResponse<ODK_RenewalRequest>(GetParam(), &(params.core_message),
|
||||
params.extra_fields, odk_parse_func,
|
||||
kdo_prepare_func);
|
||||
}
|
||||
|
||||
TEST(OdkTest, ProvisionResponseRoundtrip) {
|
||||
TEST_P(OdkVersionTest, ProvisionResponseRoundtrip) {
|
||||
ODK_ProvisioningResponseParams params;
|
||||
ODK_SetDefaultProvisioningResponseParams(¶ms);
|
||||
SetRequestVersion(¶ms);
|
||||
// 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;
|
||||
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||
@@ -628,11 +666,48 @@ TEST(OdkTest, ProvisionResponseRoundtrip) {
|
||||
return CreateCoreProvisioningResponse(params.parsed_provisioning,
|
||||
core_request, oemcrypto_core_message);
|
||||
};
|
||||
ValidateResponse<ODK_ProvisioningRequest>(&(params.core_message),
|
||||
ValidateResponse<ODK_ProvisioningRequest>(GetParam(), &(params.core_message),
|
||||
params.extra_fields, odk_parse_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) {
|
||||
uint8_t* message = nullptr;
|
||||
size_t message_length = 0;
|
||||
|
||||
@@ -409,9 +409,30 @@ OEMCryptoResult ODK_IterFields(ODK_FieldMode mode, uint8_t* buf,
|
||||
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,
|
||||
const std::vector<ODK_Field>& fields) {
|
||||
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};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
char _tmp[] = "/tmp/fileXXXXXX";
|
||||
@@ -430,7 +451,7 @@ void ODK_ExpectEqualBuf(const void* s1, const void* s2, size_t n,
|
||||
size_t bytes_written;
|
||||
uint8_t* buf =
|
||||
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();
|
||||
}
|
||||
@@ -453,24 +474,9 @@ void ODK_BuildMessageBuffer(ODK_CoreMessage* core_message,
|
||||
uint8_t** buf, uint32_t* buf_size) {
|
||||
ASSERT_TRUE(core_message != nullptr);
|
||||
ASSERT_TRUE(buf_size != nullptr);
|
||||
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"},
|
||||
};
|
||||
std::vector<ODK_Field> total_fields =
|
||||
ODK_MakeTotalFields(extra_fields, core_message);
|
||||
|
||||
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) {
|
||||
*buf_size += ODK_FieldLength(field.type);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_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;
|
||||
};
|
||||
|
||||
/* Default values in core_message for testing */
|
||||
// Default values in core_message for testing
|
||||
void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message,
|
||||
uint32_t message_type);
|
||||
void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params);
|
||||
@@ -77,9 +77,9 @@ void ODK_SetDefaultProvisioningResponseParams(
|
||||
size_t ODK_FieldLength(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);
|
||||
/* Load buf to ODK_Field */
|
||||
// Load buf to ODK_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_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);
|
||||
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,
|
||||
const std::vector<ODK_Field>& extra_fields,
|
||||
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_
|
||||
|
||||
@@ -35,6 +35,7 @@ TEST(OdkTimerBasicTest, NullTest) {
|
||||
TEST(OdkTimerBasicTest, Init) {
|
||||
// Verify that basic initialization sets all of the fields.
|
||||
ODK_ClockValues clock_values;
|
||||
memset(&clock_values, 0, sizeof(clock_values));
|
||||
uint64_t time = 42;
|
||||
ODK_InitializeClockValues(&clock_values, 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
|
||||
// for fields that can be saved, and sets others to 0.
|
||||
ODK_ClockValues clock_values;
|
||||
memset(&clock_values, 0, sizeof(clock_values));
|
||||
uint64_t time = 42u;
|
||||
uint64_t lic_signed = 1u;
|
||||
uint64_t first_decrypt = 2u;
|
||||
@@ -1223,6 +1225,7 @@ TEST_F(ODKUseCase_LimitedDurationLicense, Case5) {
|
||||
TEST_F(RenewalTest, V15Test) {
|
||||
const uint32_t key_duration = 25;
|
||||
ODK_NonceValues nonce_values;
|
||||
memset(&nonce_values, 0, sizeof(nonce_values));
|
||||
const uint64_t license_loaded = GetSystemTime(10);
|
||||
EXPECT_EQ(
|
||||
ODK_InitializeV15Values(&timer_limits_, &clock_values_, &nonce_values,
|
||||
|
||||
Reference in New Issue
Block a user