OEMCrypto v16.2

Merge from Widevine repo of http://go/wvgerrit/93404

This is the unit tests, reference code, and documentation for
OEMCrypto v16.2. Backwards compatibility should work for a v15
OEMCrypto.

Some review comments will be addressed in future CLs.

Bug: 141247171
Test: Unit tests
Test: Media GTS tests on bonito
Change-Id: I9d427c07580e180c0a4cfdc4a68f538d351c0ddd
This commit is contained in:
Fred Gylys-Colwell
2020-01-18 10:18:50 -08:00
parent 7665614b2e
commit db2050dff1
62 changed files with 2947 additions and 2286 deletions

View File

@@ -8,63 +8,103 @@
#include <stdint.h>
#include "OEMCryptoCENCCommon.h"
#include "odk_target.h"
#define ODK_MAX_NUM_KEYS 32
/* The version of this library. */
#define ODK_MAJOR_VERSION 16
#define ODK_MINOR_VERSION 2
/* Some useful constants. */
#define ODK_DEVICE_ID_LEN_MAX 64
#define ODK_SHA256_HASH_SIZE 32
/*
* ODK_TimerLimits is filled out by the function ODK_ParseLicense.
* ODK_TimerLimits Structure
*
* The fields in this structure are defined in the core license response
* message. This structure should be kept as part of the session and used
* when calling the ODK timer functions described in the document "License
* Duration and Renewal" distributed as part of the OEMCrypto v16 design.
* Description:
* 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
* fields in this structure are directly related to the fields in the core
* 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
* enforcement of rental duration.
* 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
* 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.
* 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.
* 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.
*
* Version:
* This struct changed in API version 16.2.
*/
typedef struct {
uint32_t /*boolean*/ soft_expiry;
uint64_t earliest_playback_start_seconds; /* since license signed. */
uint64_t latest_playback_start_seconds; /* since license signed. */
uint64_t initial_playback_duration_seconds; /* since playback start. */
uint64_t renewal_playback_duration_seconds; /* since renewal signed. */
uint64_t license_duration_seconds; /* since license signed. */
bool soft_enforce_rental_duration;
bool soft_enforce_playback_duration;
uint64_t earliest_playback_start_seconds;
uint64_t rental_duration_seconds;
uint64_t total_playback_duration_seconds;
uint64_t initial_renewal_duration_seconds;
} ODK_TimerLimits;
/*
* ODK_ParsedLicense holds fields from the core license response.
*/
typedef struct {
OEMCrypto_Substring enc_mac_keys_iv;
OEMCrypto_Substring enc_mac_keys;
OEMCrypto_Substring pst;
OEMCrypto_Substring srm_restriction_data;
uint32_t /* OEMCrypto_LicenseType */ license_type;
uint32_t nonce_required;
ODK_TimerLimits timer_limits;
uint8_t request_hash[ODK_SHA256_HASH_SIZE];
uint32_t key_array_length; /* num_keys */
OEMCrypto_KeyObject key_array[ODK_MAX_NUM_KEYS];
} ODK_ParsedLicense;
/*
* ODK_ParsedProvisioning holds fields from the core provisioning response.
*/
typedef struct {
uint32_t key_type;
OEMCrypto_Substring enc_private_key;
OEMCrypto_Substring enc_private_key_iv;
OEMCrypto_Substring encrypted_message_key; /* Used for Prov 3.0 */
} ODK_ParsedProvisioning;
/*
* ODK_ClockValues keeps information about a session's current clock values
* and timers.
* ODK_ClockValues Structure
*
* Most of the fields in this structure are saved in the usage entry for each
* session. This structure should be initialized when a usage entry is
* created or loaded, and should be used to save a usage entry. It is
* updated using ODK functions listed in the document "License Duration and
* Renewal". The time values are based on OEMCryptos system clock.
* 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
* "Complete ODK API" of the document "Widevine Core Message Serialization"
* for a complete list of all fields in this structure. Most of these values
* shall be saved with the usage entry.
*
* All times are in seconds. Most of the fields in this structure are saved
* in the usage entry. This structure should be initialized when a usage
* entry is created or loaded, and should be used to save a usage entry. It
* is updated using the ODK functions listed below. The time values are based
* 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
* 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.
*
* Version:
* This struct changed in API version 16.2.
*/
typedef struct {
uint64_t time_of_license_signed;
@@ -77,20 +117,99 @@ typedef struct {
} ODK_ClockValues;
/*
* ODK_NonceValues are used to match a license or provisioning request to a
* license or provisioning response. For this reason, the api_version might be
* lower than that supported by OEMCrypto. The api_version matches the version
* of the license. Similarly the nonce and session_id match the session that
* generated the license request. For an offline license, these might not match
* the session that is loading the license. We use the nonce to prevent a
* license from being replayed. By also including a session_id in the license
* request and license response, we prevent an attack using the birthday paradox
* to generate nonce collisions on a single device.
* 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
* be lower than that supported by OEMCrypto. The api_version matches the
* version of the license. Similarly the nonce and session_id match the
* session that generated the license request. For an offline license, these
* might not match the session that is loading the license. We use the nonce
* to prevent a license from being replayed. By also including a session_id
* 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
* provisioning request. It is used to prevent replay attacks from one
* session to another.
*
* Version:
* This struct changed in API version 16.2.
*/
typedef struct {
uint32_t api_version;
uint16_t api_minor_version;
uint16_t api_major_version;
uint32_t nonce;
uint32_t session_id;
} ODK_NonceValues;
/*
* ODK_ParsedLicense Structure
*
* Description:
* 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
* 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.
*
* Version:
* This struct changed in API version 16.2.
*/
typedef struct {
OEMCrypto_Substring enc_mac_keys_iv;
OEMCrypto_Substring enc_mac_keys;
OEMCrypto_Substring pst;
OEMCrypto_Substring srm_restriction_data;
OEMCrypto_LicenseType license_type;
bool nonce_required;
ODK_TimerLimits timer_limits;
uint32_t key_array_length;
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.
*
* Version:
* This struct changed in API version 16.2.
*/
typedef struct {
OEMCrypto_PrivateKeyType key_type;
OEMCrypto_Substring enc_private_key;
OEMCrypto_Substring enc_private_key_iv;
OEMCrypto_Substring encrypted_message_key; /* Used for Prov 3.0 */
} ODK_ParsedProvisioning;
#endif /* WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_ */