Files
oemcrypto_core_message/oemcrypto/odk/include/odk.h
2024-07-08 22:56:53 +00:00

901 lines
38 KiB
C

// Copyright 2019 Google LLC. This file and proprietary
// source code may only be used and distributed under the Widevine
// License Agreement.
/**
* @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
* response, and renewal request and response.
*
* In OEMCrypto v15 and earlier, messages from the server were parsed by the
* CDM layer above OEMCrypto; the CDM in turn gave OEMCrypto a collection of
* pointers to protected data within the message. However, the pointers
* themselves were not signed by the server.
*
* Starting from OEMCrypto v16, all fields used by OEMCrypto in each of these
* messages have been identified in the document "Widevine Core Message
* Serialization". These fields are called the core of the message. Core
* message fields are (de)serialized using the ODK, a C library provided by
* Widevine. OEMCrypto will parse and verify the core of the message with
* help from the ODK.
*
* The ODK functions that parse code will fill out structs that have similar
* formats to the function parameters of the OEMCrypto v15 functions being
* replaced. The ODK will be provided in source code and it is Widevine's
* intention that partners can build and link ODK with their implementation
* of OEMCrypto with no or few code changes.
*
* OEMCrypto implementers shall build the ODK library as part of the Trusted
* Application (TA) running in the TEE. All memory and buffers used by the
* ODK library shall be sanitized by the OEMCrypto implementer to prevent
* modification by any process running the REE.
*
* 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
*
* @defgroup odk_derivation Key Derivation Utils
* Utilities and constants relating to key derivation.
* functions.
*********************************************************************/
#ifndef WIDEVINE_ODK_INCLUDE_ODK_H_
#define WIDEVINE_ODK_INCLUDE_ODK_H_
#include <stdint.h>
#include "OEMCryptoCENCCommon.h"
#include "odk_structs.h"
#ifdef __cplusplus
extern "C" {
#endif
/// @addtogroup odk_timer
/// @{
/**
* This function initializes the session's data structures. It shall be
* called from OEMCrypto_OpenSession.
*
* @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.
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 16 of the API.
*/
OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
ODK_NonceValues* nonce_values,
uint32_t api_major_version,
uint32_t session_id);
/**
* This function sets the nonce value in the session's nonce structure. It
* shall be called from OEMCrypto_GenerateNonce.
*
* @param[in,out] nonce_values: the session's nonce data.
* @param[in] nonce: the new nonce that was just generated.
*
* @retval true on success
*
* @version
* This method is new in version 16 of the API.
*/
OEMCryptoResult ODK_SetNonceValues(ODK_NonceValues* nonce_values,
uint32_t nonce);
/**
* This function initializes the clock values in the session clock_values
* structure. It shall be called from OEMCrypto_PrepAndSignLicenseRequest.
*
* Parameters:
* @param[in,out] clock_values: the session's clock data.
* @param[in] system_time_seconds: the current time on OEMCrypto's monotonic
* clock.
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 16 of the API.
*/
OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
uint64_t system_time_seconds);
/**
* 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_request_signed.
*
* @param[in,out] clock_values: the session's clock data.
* @param[in] time_of_license_request_signed: the value time_license_received
* from the loaded usage entry.
* @param[in] time_of_first_decrypt: the value time_of_first_decrypt from the
* loaded usage entry.
* @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.
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 16 of the API.
*/
OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
uint64_t time_of_license_request_signed,
uint64_t time_of_first_decrypt,
uint64_t time_of_last_decrypt,
enum OEMCrypto_Usage_Entry_Status status,
uint64_t system_time_seconds);
/**
* 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
* just this session.
*
* This shall be called from the first call in a session to any of
* OEMCrypto_DecryptCENC or any of the OEMCrypto_Generic* functions.
*
* If OEMCrypto uses a hardware timer, and this function returns
* ODK_SET_TIMER, then the timer should be set to the value pointed to by
* timer_value.
*
* @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.
*
* @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.
* @retval ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
*
* @version
* This method is new in version 16 of the API.
*/
OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
const ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
uint64_t* timer_value);
/**
* 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
* system time. This shall be called from any of OEMCrypto_DecryptCENC or any
* of the OEMCrypto_Generic* functions.
*
* All Vendors (i.e. those that do or do not implement their own timer) shall
* call ODK_UpdateLastPlaybackTime from the function
* OEMCrypto_UpdateUsageEntry before updating the usage entry so that the
* clock values are accurate.
*
* @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.
*
* @retval OEMCrypto_SUCCESS: Success. Playback is allowed.
* @retval ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
*
* @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);
/**
* This function modifies the session's clock values to indicate that the
* license has been deactivated. It shall be called from
* OEMCrypto_DeactivateUsageEntry
*
* Parameters:
* @param[in,out] clock_values: the sessions clock values.
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 16 of the API.
*/
OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values);
/// @}
/// @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.
*
* This shall be called by OEMCrypto from OEMCrypto_PrepAndSignLicenseRequest.
*
* NOTE: if the message pointer is null and/or input core_message_size is
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
* core_message_size to the size needed.
*
* @param[in,out] message: Pointer to memory for the entire message. Modified by
* the ODK library.
* @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.
* @param[in] nonce_values: pointer to the session's nonce data.
* @param[in] message_count_info: information used for server-side anomaly
* detection
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @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,
const ODK_MessageCounterInfo* counter_info);
/**
* Modifies the message to include a core license release at the beginning of
* the message buffer. The values in nonce_values are used to populate the
* message.
*
* This shall be called by OEMCrypto from OEMCrypto_PrepAndSignLicenseRelease.
*
* NOTE: if the message pointer is null and/or input core_message_size is
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
* core_message_size to the size needed.
*
* @param[in,out] message: Pointer to memory for the entire message. Modified by
* the ODK library.
* @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.
* @param[in] nonce_values: pointer to the session's nonce data.
* @param[in] status: the enumeration of OEMCrypto_Usage_Entry_Status
* @param[in] clock_security_level: the enumeration of
* OEMCryto_Clock_Security_Level
* @param[in] seconds_since_license_requested: the time between the license
* being requested and the release being generated in seconds
* @param[in] seconds_since_first_decrypt: The time since playback has started
* in seconds
* @param[in,out] clock_values: the session's clock values.
* @param[in] system_time_seconds: the current time on OEMCrypto's clock, in
* seconds.
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 19 of the API.
*/
OEMCryptoResult ODK_PrepareCoreReleaseRequest(
uint8_t* message, size_t message_length, size_t* core_message_size,
ODK_NonceValues* nonce_values, uint32_t status,
uint32_t clock_security_level, int64_t seconds_since_license_requested,
int64_t seconds_since_first_decrypt, ODK_ClockValues* clock_values,
uint64_t system_time_seconds);
/**
* 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
* should match those from the license.
*
* This shall be called by OEMCrypto from OEMCrypto_PrepAndSignRenewalRequest.
*
* If status in clock_values indicates that a license has not been loaded,
* then this is a license release. The ODK library will change the value of
* nonce_values.api_major_version to 15. This will make
* OEMCrypto_PrepAndSignRenewalRequest sign just the message body, as it does
* for all legacy licenses.
*
* NOTE: if the message pointer is null and/or input core_message_size is
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
* core_message_size to the size needed.
*
* @param[in,out] message: Pointer to memory for the entire message. Modified by
* the ODK library.
* @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.
* @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.
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 16 of the API.
*/
OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
size_t message_length,
size_t* core_message_size,
ODK_NonceValues* nonce_values,
ODK_ClockValues* clock_values,
uint64_t system_time_seconds);
/**
* 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.
*
* This shall be called by OEMCrypto from
* OEMCrypto_PrepAndSignProvisioningRequest.
*
* The buffer device_id shall be the same string returned by
* OEMCrypto_GetDeviceID. The device ID shall be unique to the device, and
* stable across reboots and factory resets for an L1 device.
*
* NOTE: if the message pointer is null and/or input core_message_length is
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
* core_message_size to the size needed.
*
* @param[in,out] message: Pointer to memory for the entire message. Modified by
* the ODK library.
* @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.
* @param[in] nonce_values: pointer to the session's nonce data.
* @param[in] counter_info: information used for server-side anomaly
* detection
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 16 of the API.
*/
OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
uint8_t* message, size_t message_length, size_t* core_message_length,
const ODK_NonceValues* nonce_values,
const ODK_MessageCounterInfo* counter_info);
/**
* Modifies the message to include a core provisioning 4.0 request at the
* beginning of the message buffer. The values in nonce_values are used to
* populate the message.
*
* This shall be called by OEMCrypto from
* OEMCrypto_PrepAndSignProvisioningRequest.
*
* NOTE: if the message pointer is null and/or input core_message_length is
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
* core_message_size to the size needed.
*
* @param[in,out] message: Pointer to memory for the entire message. Modified by
* the ODK library.
* @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.
* @param[in] nonce_values: pointer to the session's nonce data.
* @param[in] device_info: Encoded device hardware info in CBOR format.
* @param[in] device_info_length: length of device_info.
* @param[in] message_count_info: information used for server-side anomaly
* detection
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 18 of the API.
*/
OEMCryptoResult ODK_PrepareCoreProvisioning40Request(
uint8_t* message, size_t message_length, size_t* core_message_length,
const ODK_NonceValues* nonce_values, const uint8_t* device_info,
size_t device_info_length, const ODK_MessageCounterInfo* counter_info);
/**
* Modifies the message to include a core renewal provisioning request at the
* beginning of the message buffer. The values in nonce_values are used to
* populate the message.
*
* This shall be called by OEMCrypto from
* OEMCrypto_PrepAndSignProvisioningRequest.
*
* The buffer device_id shall be the same string returned by
* OEMCrypto_GetDeviceID. The device ID shall be unique to the device, and
* stable across reboots and factory resets for an L1 device.
*
* NOTE: if the message pointer is null and/or input core_message_length is
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
* core_message_size to the size needed.
*
* @param[in,out] message: pointer to memory for the entire message. Modified by
* the ODK library.
* @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.
* @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.
* @param[in] renewal_type: type of renewal used
* @param[in] renewal_data: renewal data used. For renewal_type = 1,
* renewal_data is the Android attestation batch certificate.
* @param[in] renewal_data_length: length of renewal_data
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 17 of the API.
*/
OEMCryptoResult ODK_PrepareCoreRenewedProvisioningRequest(
uint8_t* message, size_t message_length, size_t* core_message_length,
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
size_t device_id_length, uint16_t renewal_type, const uint8_t* renewal_data,
size_t renewal_data_length);
/// @}
/// @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.
*
* @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".
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 16 of the API.
*/
OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
ODK_NonceValues* nonce_values,
uint32_t key_duration,
uint64_t system_time_seconds);
/**
* 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.
*
* This is called from OEMCrypto_RefreshKeys for a valid license renewal.
* OEMCrypto shall pass in the current system time, and the key duration from
* the first object in the OEMCrypto_KeyRefreshObject.
*
* @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".
* @param[in] new_key_duration: The duration from the first
* OEMCrypto_KeyRefreshObject in key_array.
* @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.
*
* @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.
* @retval ODK_TIMER_EXPIRED: Set timer as disabled. Playback is not allowed.
*
* @version
* This method is new in version 16 of the API.
*/
OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
const ODK_NonceValues* nonce_values,
uint64_t system_time_seconds,
uint32_t new_key_duration,
uint64_t* timer_value);
/// @}
/// @addtogroup odk_parser
/// @{
/**
* The function ODK_ParseLicense will parse the message and verify fields in
* the message.
*
* If the message does not parse correctly, ODK_VerifyAndParseLicense will
* return ODK_ERROR_CORE_MESSAGE that OEMCrypto should return to the CDM
* layer above.
*
* If the API in the message is not 16, then ODK_UNSUPPORTED_API is returned.
*
* If initial_license_load is true, and nonce_required in the license is
* true, then the ODK library shall verify that nonce_values->nonce and
* nonce_values->session_id are the same as those in the message. If
* verification fails, then it shall return OEMCrypto_ERROR_INVALID_NONCE.
*
* If initial_license_load is false, and nonce_required is true, then
* ODK_ParseLicense will set the values in nonce_values from those in the
* message.
*
* The function ODK_ParseLicense will verify that each substring points to a
* location in the message body. The message body is the buffer starting at
* message + core_message_length with size message_length -
* core_message_length.
*
* If initial_license_load is true, then ODK_ParseLicense shall verify that
* the parameter request_hash matches request_hash in the parsed license. If
* verification fails, then it shall return ODK_ERROR_CORE_MESSAGE. This was
* computed by OEMCrypto when the license was requested.
*
* If usage_entry_present is true, then ODK_ParseLicense shall verify that
* the pst in the license has a nonzero length.
*
* @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.
* @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.
* @param[in] system_time_seconds: The current system's time in seconds.
* @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.
* @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.
*
* @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 ODK_SET_TIMER: Success. The timer should be reset to the specified
* timer value.
* @retval ODK_DISABLE_TIMER: if the playtime timer has been started
* successfully then is disabled.
* @retval ODK_TIMER_EXPIRED: if the license is attempted to be loaded after the
* rental duration expires.
* @retval OEMCrypto_ERROR_INVALåID_NONCE
*
* @version
* This method changed in version 18 of the API.
*/
OEMCryptoResult ODK_ParseLicense(
const uint8_t* message, size_t message_length, size_t core_message_length,
bool initial_license_load, bool usage_entry_present,
uint64_t system_time_seconds, ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values, ODK_NonceValues* nonce_values,
ODK_ParsedLicense* parsed_license, uint64_t* timer_value);
/**
* 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.
*
* ODK_ParseRenewal shall verify that all fields in nonce_values match those
* in the license. Otherwise it shall return OEMCrypto_ERROR_INVALID_NONCE.
*
* After parsing the message, this function updates the clock_values based on
* the timer_limits and the current system time. If playback may not
* continue, then ODK_TIMER_EXPIRED is returned.
*
* If playback may continue, a return value of ODK_SET_TIMER or
* ODK_TIMER_EXPIRED is returned. If the return value is ODK_SET_TIMER, then
* playback may continue until the timer expires. If the return value is
* ODK_DISABLE_TIMER, then playback time is not limited.
*
* If OEMCrypto uses a hardware timer, and this function returns
* ODK_SET_TIMER, then OEMCrypto shall set the timer to the value pointed to
* by timer_value.
*
* @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.
* @param[in,out] nonce_values: pointer to the session's nonce data. These might
* be updated if the server returns a lower API version.
* @param[in] system_time_seconds: the current time on OEMCrypto's 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.
*
* @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_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.
* @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
* This method changed in version 18 of the API.
*/
OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
size_t core_message_length,
ODK_NonceValues* nonce_values,
uint64_t system_time_seconds,
const ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
uint64_t* timer_value);
/**
* The function ODK_ParseRelease will parse the message and verify its
* header contents. If the message does not parse correctly, an error of
* ODK_ERROR_CORE_MESSAGE is returned. This function is mostly a placeholder
* function since there is no information needed in the release response.
*
* @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.
* @param[in,out] nonce_values: pointer to the session's nonce data. These might
* be updated if the server returns a lower API version.
*
* @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
* This method is new in version 19 of the API.
*/
OEMCryptoResult ODK_ParseRelease(const uint8_t* message, size_t message_length,
size_t core_message_length,
ODK_NonceValues* nonce_values);
/**
* The function ODK_ParseProvisioning will parse the message and verify the
* nonce values match those in the license.
*
* If the message does not parse correctly, ODK_ParseProvisioning will return
* an error that OEMCrypto should return to the CDM layer above.
*
* If the API in the message is larger than ODK_MAJOR_VERSION, then
* ODK_UNSUPPORTED_API is returned.
*
* ODK_ParseProvisioning shall verify that nonce_values->nonce and
* nonce_values->session_id are the same as those in the message. Otherwise
* it shall return OEMCrypto_ERROR_INVALID_NONCE.
*
* The function ODK_ParseProvisioning will verify that each substring points
* to a location in the message body. The message body is the buffer starting
* at message + core_message_length with size message_length -
* core_message_length.
*
* @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.
* @param[in/out] nonce_values: pointer to the session's nonce data. These might
* be updated if the server returns a lower API version.
* @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.
* @param[in] device_id_length: the length of the device ID.
* @param[out] parsed_response: destination for response portion of parse data.
*
* @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
* This method changed in version 18 of the API.
*/
OEMCryptoResult ODK_ParseProvisioning(
const uint8_t* message, size_t message_length, size_t core_message_length,
ODK_NonceValues* nonce_values, const uint8_t* device_id,
size_t device_id_length, ODK_ParsedProvisioning* parsed_response);
/**
* The function ODK_ParseProvisioning40 will parse the message and verify the
* nonce values match those in the request.
*
* If the message does not parse correctly, ODK_ParseProvisioning40 will return
* an error that OEMCrypto should return to the CDM layer above.
*
* If the API in the message is larger than ODK_MAJOR_VERSION, then
* ODK_UNSUPPORTED_API is returned.
*
* ODK_ParseProvisioning40 shall verify that nonce_values->nonce and
* nonce_values->session_id are the same as those in the message. Otherwise
* it shall return OEMCrypto_ERROR_INVALID_NONCE.
*
* @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.
* @param[in,out] nonce_values: pointer to the session's nonce data. These might
* be updated if the server returns a lower API version.
*
* @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
* This method is new in version 18 of the API.
*/
OEMCryptoResult ODK_ParseProvisioning40(const uint8_t* message,
size_t message_length,
size_t core_message_length,
ODK_NonceValues* nonce_values);
/**
* The function ODK_ParseProvisioning will parse the message and verify the
* API version is at most the version passed in.
*
* @param[in] nonce_values: pointer to the session's nonce data.
* @param[in] major_versioh: current API major version.
* @param[in] minor_version: current API minor version.
*
* @version
* This method is new in version 17 of the API.
*/
bool CheckApiVersionAtMost(const ODK_NonceValues* nonce_values,
uint16_t major_version, uint16_t minor_version);
/// @}
/// @addtogroup odk_derivation
/// @{
/**
* Contains the key label for the Mac key derivation. This contains
* |ODK_MacKeyLabelWithZeroLength| number of bytes.
*/
extern const uint8_t ODK_MacKeyLabelWithZero[];
/** Contains the number of bytes in |ODK_MacKeyLabelWithZero|. */
extern const size_t ODK_MacKeyLabelWithZeroLength;
/**
* Contains the key label for the Encryption key derivation. This contains
* |ODK_EncKeyLabelWithZeroLength| number of bytes.
*/
extern const uint8_t ODK_EncKeyLabelWithZero[];
/** Contains the number of bytes in |ODK_EncKeyLabelWithZero|. */
extern const size_t ODK_EncKeyLabelWithZeroLength;
/**
* Contains the suffix bytes (NIST 800-108 key length) for Mac key derivation.
* This value is appended after the context string. This contains
* ODK_MacKeySuffixLength number of bytes.
*/
extern const uint8_t ODK_MacKeySuffix[];
/** Contains the number of bytes in |ODK_MacKeySuffix|. */
extern const size_t ODK_MacKeySuffixLength;
/**
* Contains the suffix bytes (NIST 800-108 key length) for Encryption key
* derivation. This value is appended after the context string. This contains
* ODK_EncKeySuffixLength number of bytes.
*/
extern const uint8_t ODK_EncKeySuffix[];
/** Contains the number of bytes in |ODK_EncKeySuffix|. */
extern const size_t ODK_EncKeySuffixLength;
/**
* Generates the key-derivation contexts for the license exchange based on the
* given context value.
*
* NOTE: if the mac_key_context/enc_key_context pointer are null and/or input
* mac_key_context_length/enc_key_context_length is zero, this function returns
* OEMCrypto_ERROR_SHORT_BUFFER and sets output
* mac_key_context_length/enc_key_context_length to the size needed.
*
* @param[in] context: pointer to the context buffer.
* @param[in] context_length: the length of the context buffer.
* @param[out] mac_key_context: an output buffer to contain the MAC key context.
* @param[in,out] mac_key_context_length: on input, contains the number of bytes
* in |mac_key_context|; on return, will contain the context length.
* @param[out] enc_key_context: an output buffer to contain the encryption key
* context.
* @param[in,out] enc_key_context_length: on input, contains the number of bytes
* in |enc_key_context|; on return, will contain the context length.
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_SHORT_BUFFER: mac_key_context_length or
* enc_key_context_length is too small
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 19 of the API.
*/
OEMCryptoResult ODK_GenerateKeyContexts(const uint8_t* context,
size_t context_length,
uint8_t* mac_key_context,
size_t* mac_key_context_length,
uint8_t* enc_key_context,
size_t* enc_key_context_length);
/// @}
#ifdef __cplusplus
}
#endif
#endif // WIDEVINE_ODK_INCLUDE_ODK_H_