// 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 * Widevine Core Message Serialization * and * License Duration and Renewal * 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 #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_