Update to v16.1 documentation and ODK library
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
156
oemcrypto/odk/include/OEMCryptoCENCCommon.h
Normal file
156
oemcrypto/odk/include/OEMCryptoCENCCommon.h
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// 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
|
||||||
|
*
|
||||||
|
* Common structures and error codes between WV servers and OEMCrypto.
|
||||||
|
*
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
#ifndef OEMCRYPTO_CENC_COMMON_H_
|
||||||
|
#define OEMCRYPTO_CENC_COMMON_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef uint32_t OEMCrypto_SESSION;
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
typedef enum OEMCryptoResult {
|
||||||
|
OEMCrypto_SUCCESS = 0,
|
||||||
|
OEMCrypto_ERROR_INIT_FAILED = 1,
|
||||||
|
OEMCrypto_ERROR_TERMINATE_FAILED = 2,
|
||||||
|
OEMCrypto_ERROR_OPEN_FAILURE = 3,
|
||||||
|
OEMCrypto_ERROR_CLOSE_FAILURE = 4,
|
||||||
|
OEMCrypto_ERROR_ENTER_SECURE_PLAYBACK_FAILED = 5, // deprecated
|
||||||
|
OEMCrypto_ERROR_EXIT_SECURE_PLAYBACK_FAILED = 6, // deprecated
|
||||||
|
OEMCrypto_ERROR_SHORT_BUFFER = 7,
|
||||||
|
OEMCrypto_ERROR_NO_DEVICE_KEY = 8, // no keybox device key.
|
||||||
|
OEMCrypto_ERROR_NO_ASSET_KEY = 9,
|
||||||
|
OEMCrypto_ERROR_KEYBOX_INVALID = 10,
|
||||||
|
OEMCrypto_ERROR_NO_KEYDATA = 11,
|
||||||
|
OEMCrypto_ERROR_NO_CW = 12,
|
||||||
|
OEMCrypto_ERROR_DECRYPT_FAILED = 13,
|
||||||
|
OEMCrypto_ERROR_WRITE_KEYBOX = 14,
|
||||||
|
OEMCrypto_ERROR_WRAP_KEYBOX = 15,
|
||||||
|
OEMCrypto_ERROR_BAD_MAGIC = 16,
|
||||||
|
OEMCrypto_ERROR_BAD_CRC = 17,
|
||||||
|
OEMCrypto_ERROR_NO_DEVICEID = 18,
|
||||||
|
OEMCrypto_ERROR_RNG_FAILED = 19,
|
||||||
|
OEMCrypto_ERROR_RNG_NOT_SUPPORTED = 20,
|
||||||
|
OEMCrypto_ERROR_SETUP = 21,
|
||||||
|
OEMCrypto_ERROR_OPEN_SESSION_FAILED = 22,
|
||||||
|
OEMCrypto_ERROR_CLOSE_SESSION_FAILED = 23,
|
||||||
|
OEMCrypto_ERROR_INVALID_SESSION = 24,
|
||||||
|
OEMCrypto_ERROR_NOT_IMPLEMENTED = 25,
|
||||||
|
OEMCrypto_ERROR_NO_CONTENT_KEY = 26,
|
||||||
|
OEMCrypto_ERROR_CONTROL_INVALID = 27,
|
||||||
|
OEMCrypto_ERROR_UNKNOWN_FAILURE = 28,
|
||||||
|
OEMCrypto_ERROR_INVALID_CONTEXT = 29,
|
||||||
|
OEMCrypto_ERROR_SIGNATURE_FAILURE = 30,
|
||||||
|
OEMCrypto_ERROR_TOO_MANY_SESSIONS = 31,
|
||||||
|
OEMCrypto_ERROR_INVALID_NONCE = 32,
|
||||||
|
OEMCrypto_ERROR_TOO_MANY_KEYS = 33,
|
||||||
|
OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED = 34,
|
||||||
|
OEMCrypto_ERROR_INVALID_RSA_KEY = 35,
|
||||||
|
OEMCrypto_ERROR_KEY_EXPIRED = 36,
|
||||||
|
OEMCrypto_ERROR_INSUFFICIENT_RESOURCES = 37,
|
||||||
|
OEMCrypto_ERROR_INSUFFICIENT_HDCP = 38,
|
||||||
|
OEMCrypto_ERROR_BUFFER_TOO_LARGE = 39,
|
||||||
|
OEMCrypto_WARNING_GENERATION_SKEW = 40, // Warning, not an error.
|
||||||
|
OEMCrypto_ERROR_GENERATION_SKEW = 41,
|
||||||
|
OEMCrypto_LOCAL_DISPLAY_ONLY = 42, // Info, not an error.
|
||||||
|
OEMCrypto_ERROR_ANALOG_OUTPUT = 43,
|
||||||
|
OEMCrypto_ERROR_WRONG_PST = 44,
|
||||||
|
OEMCrypto_ERROR_WRONG_KEYS = 45,
|
||||||
|
OEMCrypto_ERROR_MISSING_MASTER = 46,
|
||||||
|
OEMCrypto_ERROR_LICENSE_INACTIVE = 47,
|
||||||
|
OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE = 48,
|
||||||
|
OEMCrypto_ERROR_ENTRY_IN_USE = 49,
|
||||||
|
OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE = 50, // Reserved. Do not use.
|
||||||
|
OEMCrypto_KEY_NOT_LOADED = 51, // obsolete. use error 26.
|
||||||
|
OEMCrypto_KEY_NOT_ENTITLED = 52,
|
||||||
|
OEMCrypto_ERROR_BAD_HASH = 53,
|
||||||
|
OEMCrypto_ERROR_OUTPUT_TOO_LARGE = 54,
|
||||||
|
OEMCrypto_ERROR_SESSION_LOST_STATE = 55,
|
||||||
|
OEMCrypto_ERROR_SYSTEM_INVALIDATED = 56,
|
||||||
|
OEMCrypto_ERROR_LICENSE_RELOAD = 57,
|
||||||
|
OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES = 58,
|
||||||
|
OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION = 59,
|
||||||
|
/* ODK return values */
|
||||||
|
ODK_ERROR_BASE = 1000,
|
||||||
|
ODK_ERROR_CORE_MESSAGE = ODK_ERROR_BASE,
|
||||||
|
ODK_SET_TIMER = ODK_ERROR_BASE + 1,
|
||||||
|
ODK_DISABLE_TIMER = ODK_ERROR_BASE + 2,
|
||||||
|
ODK_TIMER_EXPIRED = ODK_ERROR_BASE + 3,
|
||||||
|
ODK_UNSUPPORTED_API = ODK_ERROR_BASE + 4,
|
||||||
|
ODK_STALE_RENEWAL = ODK_ERROR_BASE + 5,
|
||||||
|
} OEMCryptoResult;
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OEMCrypto_Usage_Entry_Status.
|
||||||
|
* Valid values for status in the usage table.
|
||||||
|
*/
|
||||||
|
typedef enum OEMCrypto_Usage_Entry_Status {
|
||||||
|
kUnused = 0,
|
||||||
|
kActive = 1,
|
||||||
|
kInactive = 2, // Deprecated. Used kInactiveUsed or kInactiveUnused.
|
||||||
|
kInactiveUsed = 3,
|
||||||
|
kInactiveUnused = 4,
|
||||||
|
} OEMCrypto_Usage_Entry_Status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
size_t offset;
|
||||||
|
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
|
||||||
|
* 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
|
||||||
|
* key_data field.
|
||||||
|
* 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
|
||||||
|
* key_control field.
|
||||||
|
* 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
|
||||||
|
* by the caller of OEMCrypto_LoadKeys().
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
OEMCrypto_Substring key_id;
|
||||||
|
OEMCrypto_Substring key_data_iv;
|
||||||
|
OEMCrypto_Substring key_data;
|
||||||
|
OEMCrypto_Substring key_control_iv;
|
||||||
|
OEMCrypto_Substring key_control;
|
||||||
|
} OEMCrypto_KeyObject;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // OEMCRYPTO_CENC_COMMON_H_
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
#define ODK_H_
|
#define ODK_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
#include "odk_structs.h"
|
#include "odk_structs.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -400,6 +400,41 @@ OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
|
|||||||
uint32_t key_duration,
|
uint32_t key_duration,
|
||||||
uint64_t system_time_seconds);
|
uint64_t system_time_seconds);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ODK_RefreshV15Values
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function updates the clock_values as needed if the renewal is
|
||||||
|
* accepted. The field nonce_values.api_level is verified to be 15.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* described in the document "License Duration and Renewal".
|
||||||
|
* [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
|
||||||
|
* allowed.
|
||||||
|
* 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,
|
||||||
|
uint64_t* timer_value);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ODK_ParseLicense
|
* ODK_ParseLicense
|
||||||
*
|
*
|
||||||
@@ -514,6 +549,8 @@ OEMCryptoResult ODK_ParseLicense(
|
|||||||
* allowed.
|
* allowed.
|
||||||
* ODK_TIMER_EXPIRED: Set timer as diabled. Playback is not allowed.
|
* ODK_TIMER_EXPIRED: Set timer as diabled. Playback is not allowed.
|
||||||
* ODK_UNSUPPORTED_API
|
* ODK_UNSUPPORTED_API
|
||||||
|
* ODK_STALE_RENEWAL: This renewal is not the most recently signed. It is
|
||||||
|
* rejected.
|
||||||
* OEMCrypto_ERROR_INVALID_NONCE
|
* OEMCrypto_ERROR_INVALID_NONCE
|
||||||
*
|
*
|
||||||
* Version:
|
* Version:
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#define ODK_STRUCTS_H_
|
#define ODK_STRUCTS_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
|
|
||||||
#define ODK_MAX_NUM_KEYS 32
|
#define ODK_MAX_NUM_KEYS 32
|
||||||
#define ODK_DEVICE_ID_LEN_MAX 64
|
#define ODK_DEVICE_ID_LEN_MAX 64
|
||||||
@@ -71,6 +71,7 @@ typedef struct {
|
|||||||
uint64_t time_of_license_signed;
|
uint64_t time_of_license_signed;
|
||||||
uint64_t time_of_first_decrypt;
|
uint64_t time_of_first_decrypt;
|
||||||
uint64_t time_of_last_decrypt;
|
uint64_t time_of_last_decrypt;
|
||||||
|
uint64_t time_of_renewal_request;
|
||||||
uint64_t time_when_timer_expires;
|
uint64_t time_when_timer_expires;
|
||||||
uint32_t timer_status;
|
uint32_t timer_status;
|
||||||
enum OEMCrypto_Usage_Entry_Status status;
|
enum OEMCrypto_Usage_Entry_Status status;
|
||||||
|
|||||||
@@ -103,10 +103,11 @@ static OEMCryptoResult ODK_ParseResponse(const uint8_t* buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nonce_values) {
|
if (nonce_values) {
|
||||||
|
/* always verify nonce_values for Renewal and Provisioning responses */
|
||||||
if (nonce_values->api_version != core_message->nonce_values.api_version ||
|
if (nonce_values->api_version != core_message->nonce_values.api_version ||
|
||||||
nonce_values->nonce != core_message->nonce_values.nonce ||
|
nonce_values->nonce != core_message->nonce_values.nonce ||
|
||||||
nonce_values->session_id != core_message->nonce_values.session_id) {
|
nonce_values->session_id != core_message->nonce_values.session_id) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +169,7 @@ OEMCryptoResult ODK_ParseLicense(const uint8_t* message, size_t message_length,
|
|||||||
size_t core_message_length,
|
size_t core_message_length,
|
||||||
bool initial_license_load,
|
bool initial_license_load,
|
||||||
bool usage_entry_present,
|
bool usage_entry_present,
|
||||||
const uint8_t request_hash[ODK_SHA256_HASH_SIZE],
|
const uint8_t* request_hash,
|
||||||
ODK_TimerLimits* timer_limits,
|
ODK_TimerLimits* timer_limits,
|
||||||
ODK_ClockValues* clock_values,
|
ODK_ClockValues* clock_values,
|
||||||
ODK_NonceValues* nonce_values,
|
ODK_NonceValues* nonce_values,
|
||||||
@@ -183,7 +184,7 @@ OEMCryptoResult ODK_ParseLicense(const uint8_t* message, size_t message_length,
|
|||||||
message, message_length, ODK_License_Response_Type, NULL,
|
message, message_length, ODK_License_Response_Type, NULL,
|
||||||
&license_response.core_message);
|
&license_response.core_message);
|
||||||
|
|
||||||
if (err) {
|
if (err != OEMCrypto_SUCCESS) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,10 +209,8 @@ OEMCryptoResult ODK_ParseLicense(const uint8_t* message, size_t message_length,
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usage_entry_present) {
|
if (usage_entry_present && parsed_license->pst.length == 0) {
|
||||||
nonce_values->nonce = license_response.core_message.nonce_values.nonce;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
nonce_values->session_id = license_response.core_message.nonce_values.session_id;
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#define ODK_STRUCTS_PRIV_H_
|
#define ODK_STRUCTS_PRIV_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
#include "odk_structs.h"
|
#include "odk_structs.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -9,8 +9,42 @@
|
|||||||
|
|
||||||
#include "odk.h"
|
#include "odk.h"
|
||||||
|
|
||||||
|
OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
|
||||||
|
ODK_ClockValues* clock_values,
|
||||||
|
ODK_NonceValues* nonce_values,
|
||||||
|
uint32_t api_version,
|
||||||
|
uint32_t session_id) {
|
||||||
|
if (clock_values == NULL || clock_values == NULL || nonce_values == NULL)
|
||||||
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
|
timer_limits->soft_expiry = false;
|
||||||
|
timer_limits->earliest_playback_start_seconds = 0;
|
||||||
|
timer_limits->latest_playback_start_seconds = 0;
|
||||||
|
timer_limits->initial_playback_duration_seconds = 0;
|
||||||
|
timer_limits->renewal_playback_duration_seconds = 0;
|
||||||
|
timer_limits->license_duration_seconds = 0;
|
||||||
|
|
||||||
|
clock_values->time_of_license_signed = 0;
|
||||||
|
clock_values->time_of_first_decrypt = 0;
|
||||||
|
clock_values->time_of_last_decrypt = 0;
|
||||||
|
clock_values->time_when_timer_expires = 0;
|
||||||
|
clock_values->timer_status = 0;
|
||||||
|
clock_values->status = kUnused;
|
||||||
|
|
||||||
|
nonce_values->api_version = api_version;
|
||||||
|
nonce_values->nonce = 0;
|
||||||
|
nonce_values->session_id = session_id;
|
||||||
|
|
||||||
|
return OEMCrypto_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult ODK_SetNonceValues(ODK_NonceValues* nonce_values,
|
||||||
|
uint32_t nonce) {
|
||||||
|
nonce_values->nonce = nonce;
|
||||||
|
return OEMCrypto_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
|
OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
|
||||||
uint64_t system_time_seconds) {
|
uint64_t system_time_seconds) {
|
||||||
if (clock_values == NULL) return OEMCrypto_ERROR_INVALID_CONTEXT;
|
if (clock_values == NULL) return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
clock_values->time_of_license_signed = system_time_seconds;
|
clock_values->time_of_license_signed = system_time_seconds;
|
||||||
clock_values->time_of_first_decrypt = 0;
|
clock_values->time_of_first_decrypt = 0;
|
||||||
@@ -64,7 +98,8 @@ uint32_t ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
|
|||||||
* session. */
|
* session. */
|
||||||
if (clock_values->status == kUnused) {
|
if (clock_values->status == kUnused) {
|
||||||
/* If the rental clock has expired, the license has expired. */
|
/* If the rental clock has expired, the license has expired. */
|
||||||
if (rental_time > timer_limits->latest_playback_start_seconds) {
|
if (rental_time > timer_limits->latest_playback_start_seconds &&
|
||||||
|
timer_limits->latest_playback_start_seconds > 0) {
|
||||||
clock_values->timer_status = ODK_TIMER_EXPIRED;
|
clock_values->timer_status = ODK_TIMER_EXPIRED;
|
||||||
return ODK_TIMER_EXPIRED;
|
return ODK_TIMER_EXPIRED;
|
||||||
}
|
}
|
||||||
@@ -161,3 +196,85 @@ OEMCryptoResult ODK_UpdateLastPlaybackTime(uint64_t system_time_seconds,
|
|||||||
clock_values->time_of_last_decrypt = system_time_seconds;
|
clock_values->time_of_last_decrypt = system_time_seconds;
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values) {
|
||||||
|
if (clock_values == NULL) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
if (clock_values->status == kUnused) {
|
||||||
|
clock_values->status = kInactiveUnused;
|
||||||
|
} else if (clock_values->status == kActive) {
|
||||||
|
clock_values->status = kInactiveUsed;
|
||||||
|
}
|
||||||
|
return OEMCrypto_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
|
||||||
|
ODK_ClockValues* clock_values,
|
||||||
|
ODK_NonceValues* nonce_values,
|
||||||
|
uint32_t key_duration,
|
||||||
|
uint64_t system_time_seconds) {
|
||||||
|
if (clock_values == NULL || clock_values == NULL || nonce_values == NULL)
|
||||||
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
|
timer_limits->soft_expiry = false;
|
||||||
|
timer_limits->earliest_playback_start_seconds = 0;
|
||||||
|
timer_limits->latest_playback_start_seconds = 0;
|
||||||
|
timer_limits->initial_playback_duration_seconds = key_duration;
|
||||||
|
timer_limits->renewal_playback_duration_seconds = key_duration;
|
||||||
|
timer_limits->license_duration_seconds = 0;
|
||||||
|
nonce_values->api_version = 15;
|
||||||
|
if (key_duration > 0) {
|
||||||
|
clock_values->time_when_timer_expires = system_time_seconds + key_duration;
|
||||||
|
} else {
|
||||||
|
clock_values->time_when_timer_expires = 0;
|
||||||
|
}
|
||||||
|
return OEMCrypto_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
|
||||||
|
ODK_ClockValues* clock_values,
|
||||||
|
const ODK_NonceValues* nonce_values,
|
||||||
|
uint64_t system_time_seconds,
|
||||||
|
uint64_t* timer_value) {
|
||||||
|
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL)
|
||||||
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
|
if (nonce_values->api_version != 15) return OEMCrypto_ERROR_INVALID_NONCE;
|
||||||
|
if (clock_values->status > kActive) {
|
||||||
|
clock_values->timer_status = ODK_TIMER_EXPIRED;
|
||||||
|
return ODK_TIMER_EXPIRED;
|
||||||
|
}
|
||||||
|
/* If this is before the license was signed, something is odd. Return an
|
||||||
|
* error. */
|
||||||
|
if (system_time_seconds < clock_values->time_of_license_signed)
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
|
||||||
|
/* All times are relative to when the license was signed. */
|
||||||
|
const uint64_t rental_time =
|
||||||
|
system_time_seconds - clock_values->time_of_license_signed;
|
||||||
|
|
||||||
|
/* The timer should be limited by the renewal playback duration. This is
|
||||||
|
* similar to code in AttemptFirstPlayback, above, except we use the
|
||||||
|
* renewal_playback_duration here, and we do not change clock_values->status.
|
||||||
|
*/
|
||||||
|
uint64_t time_left = timer_limits->renewal_playback_duration_seconds;
|
||||||
|
/* If there is a license duration, it also limits the timer. Remember, a
|
||||||
|
* limit of 0 means no limit, or infinite. */
|
||||||
|
if (timer_limits->license_duration_seconds > 0) {
|
||||||
|
if (timer_limits->license_duration_seconds < rental_time) {
|
||||||
|
clock_values->timer_status = ODK_TIMER_EXPIRED;
|
||||||
|
return ODK_TIMER_EXPIRED;
|
||||||
|
}
|
||||||
|
if (timer_limits->license_duration_seconds - rental_time < time_left ||
|
||||||
|
time_left == 0) {
|
||||||
|
time_left = timer_limits->license_duration_seconds - rental_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (time_left == 0 || timer_limits->soft_expiry) { /* Unlimited. */
|
||||||
|
clock_values->time_when_timer_expires = 0;
|
||||||
|
clock_values->timer_status = ODK_DISABLE_TIMER;
|
||||||
|
return ODK_DISABLE_TIMER;
|
||||||
|
}
|
||||||
|
/* Set timer to limit playback. */
|
||||||
|
if (timer_value) *timer_value = time_left;
|
||||||
|
clock_values->time_when_timer_expires = system_time_seconds + time_left;
|
||||||
|
clock_values->timer_status = ODK_SET_TIMER;
|
||||||
|
return ODK_SET_TIMER;
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
#include "odk_assert.h"
|
#include "odk_assert.h"
|
||||||
#include "odk_overflow.h"
|
#include "odk_overflow.h"
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ extern "C" {
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
|
|
||||||
#define SIZE_OF_MESSAGE_STRUCT 64
|
#define SIZE_OF_MESSAGE_STRUCT 64
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
#include "odk.h"
|
#include "odk.h"
|
||||||
#include "odk_serialize.h"
|
#include "odk_serialize.h"
|
||||||
#include "oec_util.h"
|
#include "oec_util.h"
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ size_t ODK_FieldLength(ODK_FieldType type) {
|
|||||||
case ODK_SUBSTRING:
|
case ODK_SUBSTRING:
|
||||||
return sizeof(uint32_t) + sizeof(uint32_t);
|
return sizeof(uint32_t) + sizeof(uint32_t);
|
||||||
case ODK_DEVICEID:
|
case ODK_DEVICEID:
|
||||||
return DEVICE_ID_MAX;
|
return ODK_DEVICE_ID_LEN_MAX;
|
||||||
|
case ODK_HASH:
|
||||||
|
return ODK_SHA256_HASH_SIZE;
|
||||||
default:
|
default:
|
||||||
return SIZE_MAX;
|
return SIZE_MAX;
|
||||||
}
|
}
|
||||||
@@ -51,7 +53,7 @@ size_t ODK_AllocSize(ODK_FieldType type) {
|
|||||||
|
|
||||||
OEMCryptoResult ODK_WriteSingleField(uint8_t* const buf,
|
OEMCryptoResult ODK_WriteSingleField(uint8_t* const buf,
|
||||||
const ODK_Field* const field) {
|
const ODK_Field* const field) {
|
||||||
if (!field || !field->value) {
|
if (!buf || !field || !field->value) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
@@ -73,9 +75,12 @@ OEMCryptoResult ODK_WriteSingleField(uint8_t* const buf,
|
|||||||
memcpy(buf + sizeof(off), &len, sizeof(len));
|
memcpy(buf + sizeof(off), &len, sizeof(len));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_DEVICEID: {
|
case ODK_DEVICEID:
|
||||||
|
case ODK_HASH: {
|
||||||
|
const size_t field_len = ODK_FieldLength(field->type);
|
||||||
const uint8_t* const id = static_cast<uint8_t*>(field->value);
|
const uint8_t* const id = static_cast<uint8_t*>(field->value);
|
||||||
memcpy(buf, id, DEVICE_ID_MAX);
|
memcpy(buf, id, field_len);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -112,9 +117,11 @@ OEMCryptoResult ODK_ReadSingleField(const uint8_t* const buf,
|
|||||||
s->length = be32toh(len);
|
s->length = be32toh(len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_DEVICEID: {
|
case ODK_DEVICEID:
|
||||||
|
case ODK_HASH: {
|
||||||
|
const size_t field_len = ODK_FieldLength(field->type);
|
||||||
uint8_t* const id = static_cast<uint8_t*>(field->value);
|
uint8_t* const id = static_cast<uint8_t*>(field->value);
|
||||||
memcpy(id, buf, DEVICE_ID_MAX);
|
memcpy(id, buf, field_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -174,29 +181,6 @@ OEMCryptoResult ODK_WriteFields(uint8_t* const buf, const size_t size_in,
|
|||||||
return ODK_IterFields(ODK_WRITE, buf, size_in, size_out, fields);
|
return ODK_IterFields(ODK_WRITE, buf, size_in, size_out, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
OEMCryptoResult ODK_ValidateSubstrings(const size_t size, const size_t n,
|
|
||||||
const ODK_Field* const fields) {
|
|
||||||
if (!fields) {
|
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
|
||||||
}
|
|
||||||
size_t off = 0;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
if (fields[i].type != ODK_SUBSTRING) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!fields[i].value) {
|
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
|
||||||
}
|
|
||||||
size_t end = 0;
|
|
||||||
OEMCrypto_Substring* s = static_cast<OEMCrypto_Substring*>(fields[i].value);
|
|
||||||
if (s->offset > size ||
|
|
||||||
__builtin_add_overflow(s->offset, s->length, &end) || end > size) {
|
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return OEMCrypto_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void expect_eq_buf(const void* s1, const void* s2, size_t n) {
|
void expect_eq_buf(const void* s1, const void* s2, size_t n) {
|
||||||
if (memcmp(s1, s2, n)) {
|
if (memcmp(s1, s2, n)) {
|
||||||
const void* buffers[] = {s1, s2};
|
const void* buffers[] = {s1, s2};
|
||||||
@@ -222,6 +206,7 @@ void ValidateRequest(uint32_t message_type,
|
|||||||
uint32_t api_version = 16;
|
uint32_t api_version = 16;
|
||||||
uint32_t nonce = 0xdeadbeef;
|
uint32_t nonce = 0xdeadbeef;
|
||||||
uint32_t session_id = 0xcafebabe;
|
uint32_t session_id = 0xcafebabe;
|
||||||
|
ODK_NonceValues nonce_values{api_version, nonce, session_id};
|
||||||
std::vector<ODK_Field> total_fields = {
|
std::vector<ODK_Field> total_fields = {
|
||||||
{ODK_UINT32, &message_type}, {ODK_UINT32, &message_size},
|
{ODK_UINT32, &message_type}, {ODK_UINT32, &message_size},
|
||||||
{ODK_UINT32, &api_version}, {ODK_UINT32, &nonce},
|
{ODK_UINT32, &api_version}, {ODK_UINT32, &nonce},
|
||||||
@@ -238,9 +223,8 @@ void ValidateRequest(uint32_t message_type,
|
|||||||
uint8_t* buf2 = new uint8_t[message_size]();
|
uint8_t* buf2 = new uint8_t[message_size]();
|
||||||
size_t bytes_written = message_size;
|
size_t bytes_written = message_size;
|
||||||
|
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_SUCCESS,
|
odk_prepare_func(buf, &bytes_written, &nonce_values));
|
||||||
odk_prepare_func(buf, &bytes_written, api_version, nonce, session_id));
|
|
||||||
EXPECT_EQ(bytes_written, message_size);
|
EXPECT_EQ(bytes_written, message_size);
|
||||||
|
|
||||||
EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_WRITE, buf2, SIZE_MAX,
|
EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_WRITE, buf2, SIZE_MAX,
|
||||||
@@ -254,9 +238,11 @@ void ValidateRequest(uint32_t message_type,
|
|||||||
std::string oemcrypto_core_message(reinterpret_cast<char*>(buf),
|
std::string oemcrypto_core_message(reinterpret_cast<char*>(buf),
|
||||||
message_size);
|
message_size);
|
||||||
EXPECT_TRUE(kdo_parse_func(oemcrypto_core_message, &t));
|
EXPECT_TRUE(kdo_parse_func(oemcrypto_core_message, &t));
|
||||||
|
nonce_values.api_version = t.api_version;
|
||||||
|
nonce_values.nonce = t.nonce;
|
||||||
|
nonce_values.session_id = t.session_id;
|
||||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||||
odk_prepare_func(buf2, &bytes_written, t.api_version, t.nonce,
|
odk_prepare_func(buf2, &bytes_written, &nonce_values));
|
||||||
t.session_id));
|
|
||||||
EXPECT_EQ(bytes_written, message_size);
|
EXPECT_EQ(bytes_written, message_size);
|
||||||
expect_eq_buf(buf, buf2, message_size);
|
expect_eq_buf(buf, buf2, message_size);
|
||||||
|
|
||||||
@@ -264,6 +250,12 @@ void ValidateRequest(uint32_t message_type,
|
|||||||
delete[] buf2;
|
delete[] buf2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template arguments:
|
||||||
|
* T: kdo input struct
|
||||||
|
* F: odk deserializer
|
||||||
|
* G: kdo serializer
|
||||||
|
*/
|
||||||
template <typename T, typename F, typename G>
|
template <typename T, typename F, typename G>
|
||||||
void ValidateResponse(uint32_t message_type,
|
void ValidateResponse(uint32_t message_type,
|
||||||
std::vector<ODK_Field>& extra_fields,
|
std::vector<ODK_Field>& extra_fields,
|
||||||
@@ -310,8 +302,9 @@ void ValidateResponse(uint32_t message_type,
|
|||||||
bytes_written - bytes_read == header_size);
|
bytes_written - bytes_read == header_size);
|
||||||
|
|
||||||
// parse buf with odk
|
// parse buf with odk
|
||||||
|
ODK_NonceValues nonce_values{api_version, nonce, session_id};
|
||||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||||
odk_parse_func(buf, bytes_written, api_version, nonce, session_id));
|
odk_parse_func(buf, bytes_written, &nonce_values));
|
||||||
|
|
||||||
// serialize odk output to oemcrypto_core_message
|
// serialize odk output to oemcrypto_core_message
|
||||||
std::string oemcrypto_core_message;
|
std::string oemcrypto_core_message;
|
||||||
@@ -377,14 +370,11 @@ TEST(OdkTest, SerializeFieldsStress) {
|
|||||||
delete[] buf2;
|
delete[] buf2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // TODO(b/144233698): fix this.
|
|
||||||
TEST(OdkTest, LicenseRequest) {
|
TEST(OdkTest, LicenseRequest) {
|
||||||
std::vector<ODK_Field> empty;
|
std::vector<ODK_Field> empty;
|
||||||
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
|
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
|
||||||
uint32_t api_version, uint32_t nonce,
|
ODK_NonceValues* nonce_values) {
|
||||||
uint32_t session_id) {
|
return ODK_PrepareCoreLicenseRequest(buf, SIZE_MAX, size, nonce_values);
|
||||||
return ODK_PrepareCoreLicenseRequest(buf, SIZE_MAX, size, api_version,
|
|
||||||
nonce, session_id);
|
|
||||||
};
|
};
|
||||||
auto kdo_parse_func = ParseLicenseRequest;
|
auto kdo_parse_func = ParseLicenseRequest;
|
||||||
ValidateRequest<ODK_LicenseRequest>(ODK_License_Request_Type, empty,
|
ValidateRequest<ODK_LicenseRequest>(ODK_License_Request_Type, empty,
|
||||||
@@ -398,11 +388,9 @@ TEST(OdkTest, RenewalRequest) {
|
|||||||
};
|
};
|
||||||
ODK_ClockValues clock_values = {0};
|
ODK_ClockValues clock_values = {0};
|
||||||
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
|
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
|
||||||
uint32_t api_version, uint32_t nonce,
|
const ODK_NonceValues* nonce_values) {
|
||||||
uint32_t session_id) {
|
return ODK_PrepareCoreRenewalRequest(buf, SIZE_MAX, size, nonce_values,
|
||||||
return ODK_PrepareCoreRenewalRequest(buf, SIZE_MAX, size, api_version,
|
&clock_values, system_time_seconds);
|
||||||
nonce, session_id, &clock_values,
|
|
||||||
system_time_seconds);
|
|
||||||
};
|
};
|
||||||
auto kdo_parse_func = [&](const std::string& oemcrypto_core_message,
|
auto kdo_parse_func = [&](const std::string& oemcrypto_core_message,
|
||||||
ODK_RenewalRequest* core_renewal_request) {
|
ODK_RenewalRequest* core_renewal_request) {
|
||||||
@@ -425,11 +413,9 @@ TEST(OdkTest, ProvisionRequest) {
|
|||||||
{ODK_DEVICEID, device_id},
|
{ODK_DEVICEID, device_id},
|
||||||
};
|
};
|
||||||
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
|
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
|
||||||
uint32_t api_version, uint32_t nonce,
|
const ODK_NonceValues* nonce_values) {
|
||||||
uint32_t session_id) {
|
return ODK_PrepareCoreProvisioningRequest(buf, SIZE_MAX, size, nonce_values,
|
||||||
return ODK_PrepareCoreProvisioningRequest(buf, SIZE_MAX, size, api_version,
|
device_id, device_id_length);
|
||||||
nonce, session_id, device_id,
|
|
||||||
device_id_length);
|
|
||||||
};
|
};
|
||||||
auto kdo_parse_func =
|
auto kdo_parse_func =
|
||||||
[&](const std::string& oemcrypto_core_message,
|
[&](const std::string& oemcrypto_core_message,
|
||||||
@@ -466,6 +452,9 @@ TEST(OdkTest, LicenseResponse) {
|
|||||||
.renewal_playback_duration_seconds = 13,
|
.renewal_playback_duration_seconds = 13,
|
||||||
.license_duration_seconds = 14,
|
.license_duration_seconds = 14,
|
||||||
},
|
},
|
||||||
|
.request_hash = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||||
|
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||||
|
22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
|
||||||
.key_array_length = 3,
|
.key_array_length = 3,
|
||||||
.key_array =
|
.key_array =
|
||||||
{
|
{
|
||||||
@@ -510,6 +499,7 @@ TEST(OdkTest, LicenseResponse) {
|
|||||||
{ODK_UINT64,
|
{ODK_UINT64,
|
||||||
&parsed_license.timer_limits.renewal_playback_duration_seconds},
|
&parsed_license.timer_limits.renewal_playback_duration_seconds},
|
||||||
{ODK_UINT64, &parsed_license.timer_limits.license_duration_seconds},
|
{ODK_UINT64, &parsed_license.timer_limits.license_duration_seconds},
|
||||||
|
{ODK_HASH, &parsed_license.request_hash},
|
||||||
{ODK_UINT32, &parsed_license.key_array_length},
|
{ODK_UINT32, &parsed_license.key_array_length},
|
||||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_id},
|
{ODK_SUBSTRING, &parsed_license.key_array[0].key_id},
|
||||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_data_iv},
|
{ODK_SUBSTRING, &parsed_license.key_array[0].key_data_iv},
|
||||||
@@ -528,11 +518,12 @@ TEST(OdkTest, LicenseResponse) {
|
|||||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_control},
|
{ODK_SUBSTRING, &parsed_license.key_array[2].key_control},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint8_t request_hash[ODK_SHA256_HASH_SIZE] = {};
|
||||||
|
memcpy(request_hash, parsed_license.request_hash, ODK_SHA256_HASH_SIZE);
|
||||||
auto odk_parse_func = [&](const uint8_t* buf, size_t size,
|
auto odk_parse_func = [&](const uint8_t* buf, size_t size,
|
||||||
uint32_t api_version, uint32_t nonce,
|
ODK_NonceValues* nonce_values) {
|
||||||
uint32_t session_id) {
|
return ODK_ParseLicense(buf, size + 128, size, 1, 0, request_hash, nullptr,
|
||||||
return ODK_ParseLicense(buf, size + 128, api_version, nonce, session_id, 0,
|
nullptr, nonce_values, &parsed_license);
|
||||||
0, &parsed_license);
|
|
||||||
};
|
};
|
||||||
auto kdo_prepare_func = [&](const ODK_LicenseRequest& core_request,
|
auto kdo_prepare_func = [&](const ODK_LicenseRequest& core_request,
|
||||||
std::string* oemcrypto_core_message) {
|
std::string* oemcrypto_core_message) {
|
||||||
@@ -571,10 +562,9 @@ TEST(OdkTest, RenewalResponse) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto odk_parse_func = [&](const uint8_t* buf, size_t size,
|
auto odk_parse_func = [&](const uint8_t* buf, size_t size,
|
||||||
uint32_t api_version, uint32_t nonce,
|
ODK_NonceValues* nonce_values) {
|
||||||
uint32_t session_id) {
|
|
||||||
OEMCryptoResult err =
|
OEMCryptoResult err =
|
||||||
ODK_ParseRenewal(buf, size, api_version, nonce, session_id, system_time,
|
ODK_ParseRenewal(buf, size, size, nonce_values, system_time,
|
||||||
&timer_limits, &clock_values, &playback_timer);
|
&timer_limits, &clock_values, &playback_timer);
|
||||||
|
|
||||||
EXPECT_EQ(ODK_SET_TIMER, err);
|
EXPECT_EQ(ODK_SET_TIMER, err);
|
||||||
@@ -617,14 +607,13 @@ TEST(OdkTest, ProvisionResponse) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto odk_parse_func = [&](const uint8_t* buf, size_t size,
|
auto odk_parse_func = [&](const uint8_t* buf, size_t size,
|
||||||
uint32_t api_version, uint32_t nonce,
|
ODK_NonceValues* nonce_values) {
|
||||||
uint32_t session_id) {
|
|
||||||
// restore device id because it is not part of parsed_response
|
// restore device id because it is not part of parsed_response
|
||||||
device_id_length = DEVICE_ID_MAX / 2;
|
device_id_length = DEVICE_ID_MAX / 2;
|
||||||
memset(device_id, 0xff, device_id_length);
|
memset(device_id, 0xff, device_id_length);
|
||||||
OEMCryptoResult err =
|
OEMCryptoResult err =
|
||||||
ODK_ParseProvisioning(buf, size + 16, api_version, nonce, session_id,
|
ODK_ParseProvisioning(buf, size + 16, size, nonce_values, device_id,
|
||||||
device_id, device_id_length, &parsed_response);
|
device_id_length, &parsed_response);
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
auto kdo_prepare_func = [&](ODK_ProvisioningRequest& core_request,
|
auto kdo_prepare_func = [&](ODK_ProvisioningRequest& core_request,
|
||||||
@@ -646,10 +635,10 @@ TEST(OdkSizeTest, LicenseRequest) {
|
|||||||
uint32_t api_version = 0;
|
uint32_t api_version = 0;
|
||||||
uint32_t nonce = 0;
|
uint32_t nonce = 0;
|
||||||
uint32_t session_id = 0;
|
uint32_t session_id = 0;
|
||||||
|
ODK_NonceValues nonce_values{api_version, nonce, session_id};
|
||||||
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||||
ODK_PrepareCoreLicenseRequest(message, message_length,
|
ODK_PrepareCoreLicenseRequest(message, message_length,
|
||||||
&core_message_length, api_version,
|
&core_message_length, &nonce_values));
|
||||||
nonce, session_id));
|
|
||||||
// All messages have at least a five 4-byte fields.
|
// All messages have at least a five 4-byte fields.
|
||||||
size_t minimum_message_size = 5 * 4;
|
size_t minimum_message_size = 5 * 4;
|
||||||
EXPECT_GE(core_message_length, minimum_message_size);
|
EXPECT_GE(core_message_length, minimum_message_size);
|
||||||
@@ -665,10 +654,11 @@ TEST(OdkSizeTest, RenewalRequest) {
|
|||||||
ODK_ClockValues clock_values = {};
|
ODK_ClockValues clock_values = {};
|
||||||
clock_values.time_of_first_decrypt = 10;
|
clock_values.time_of_first_decrypt = 10;
|
||||||
uint64_t system_time_seconds = 15;
|
uint64_t system_time_seconds = 15;
|
||||||
|
ODK_NonceValues nonce_values{api_version, nonce, session_id};
|
||||||
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||||
ODK_PrepareCoreRenewalRequest(
|
ODK_PrepareCoreRenewalRequest(message, message_length,
|
||||||
message, message_length, &core_message_length, api_version,
|
&core_message_length, &nonce_values,
|
||||||
nonce, session_id, &clock_values, system_time_seconds));
|
&clock_values, system_time_seconds));
|
||||||
// All messages have at least a five 4-byte fields.
|
// All messages have at least a five 4-byte fields.
|
||||||
size_t minimum_message_size = 5 * 4;
|
size_t minimum_message_size = 5 * 4;
|
||||||
EXPECT_GE(core_message_length, minimum_message_size);
|
EXPECT_GE(core_message_length, minimum_message_size);
|
||||||
@@ -683,12 +673,12 @@ TEST(OdkSizeTest, ProvisioningRequest) {
|
|||||||
uint32_t session_id = 0;
|
uint32_t session_id = 0;
|
||||||
uint8_t* device_id = nullptr;
|
uint8_t* device_id = nullptr;
|
||||||
uint32_t device_id_length = 0;
|
uint32_t device_id_length = 0;
|
||||||
|
ODK_NonceValues nonce_values{api_version, nonce, session_id};
|
||||||
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||||
ODK_PrepareCoreProvisioningRequest(
|
ODK_PrepareCoreProvisioningRequest(
|
||||||
message, message_length, &core_message_length, api_version,
|
message, message_length, &core_message_length, &nonce_values,
|
||||||
nonce, session_id, nullptr, device_id_length));
|
nullptr, device_id_length));
|
||||||
// All messages have at least a five 4-byte fields.
|
// All messages have at least a five 4-byte fields.
|
||||||
size_t minimum_message_size = 5 * 4;
|
size_t minimum_message_size = 5 * 4;
|
||||||
EXPECT_GE(core_message_length, minimum_message_size);
|
EXPECT_GE(core_message_length, minimum_message_size);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#ifndef ODK_TEST_H_
|
#ifndef ODK_TEST_H_
|
||||||
#define ODK_TEST_H_
|
#define ODK_TEST_H_
|
||||||
|
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ODK_License_Request_Type = 1,
|
ODK_License_Request_Type = 1,
|
||||||
@@ -23,6 +23,7 @@ typedef enum {
|
|||||||
ODK_UINT64,
|
ODK_UINT64,
|
||||||
ODK_SUBSTRING,
|
ODK_SUBSTRING,
|
||||||
ODK_DEVICEID,
|
ODK_DEVICEID,
|
||||||
|
ODK_HASH,
|
||||||
ODK_NUMTYPES,
|
ODK_NUMTYPES,
|
||||||
} ODK_FieldType;
|
} ODK_FieldType;
|
||||||
|
|
||||||
|
|||||||
@@ -87,10 +87,12 @@ std::string a2bs_hex(const std::string& byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string b2a_hex(const std::vector<uint8_t>& byte) {
|
std::string b2a_hex(const std::vector<uint8_t>& byte) {
|
||||||
return HexEncode(&byte[0], byte.size());
|
if (byte.empty()) return "";
|
||||||
|
return HexEncode(byte.data(), byte.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string b2a_hex(const std::string& byte) {
|
std::string b2a_hex(const std::string& byte) {
|
||||||
|
if (byte.empty()) return "";
|
||||||
return HexEncode(reinterpret_cast<const uint8_t*>(byte.data()),
|
return HexEncode(reinterpret_cast<const uint8_t*>(byte.data()),
|
||||||
byte.length());
|
byte.length());
|
||||||
}
|
}
|
||||||
@@ -251,7 +253,7 @@ std::vector<uint8_t> Base64SafeDecode(const std::string& b64_input) {
|
|||||||
|
|
||||||
std::string HexEncode(const uint8_t* in_buffer, unsigned int size) {
|
std::string HexEncode(const uint8_t* in_buffer, unsigned int size) {
|
||||||
static const char kHexChars[] = "0123456789ABCDEF";
|
static const char kHexChars[] = "0123456789ABCDEF";
|
||||||
|
if (size == 0) return "";
|
||||||
// Each input byte creates two output hex characters.
|
// Each input byte creates two output hex characters.
|
||||||
std::string out_buffer(size * 2, '\0');
|
std::string out_buffer(size * 2, '\0');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user