Source release 18.1.0
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "odk_overflow.h"
|
||||
@@ -13,7 +14,6 @@
|
||||
#include "odk_structs.h"
|
||||
#include "odk_structs_priv.h"
|
||||
#include "odk_util.h"
|
||||
#include "serialization_base.h"
|
||||
|
||||
/* @ private odk functions */
|
||||
|
||||
@@ -31,7 +31,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
|
||||
/* The core message should be at the beginning of the buffer, and with a
|
||||
* shorter length. */
|
||||
if (sizeof(ODK_CoreMessage) > prepared_request_buffer_length) {
|
||||
if (ODK_CORE_MESSAGE_SIZE > prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_CoreMessage* core_message = (ODK_CoreMessage*)prepared_request_buffer;
|
||||
@@ -72,6 +72,16 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
&msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Provisioning40_Request_Type: {
|
||||
core_message->message_length = ODK_PROVISIONING40_REQUEST_SIZE;
|
||||
if (sizeof(ODK_PreparedProvisioning40Request) >
|
||||
prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedProvisioning40Request(
|
||||
&msg, (ODK_PreparedProvisioning40Request*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Renewed_Provisioning_Request_Type: {
|
||||
core_message->message_length = ODK_RENEWED_PROVISIONING_REQUEST_SIZE;
|
||||
if (sizeof(ODK_PreparedRenewedProvisioningRequest) >
|
||||
@@ -169,14 +179,18 @@ static OEMCryptoResult ODK_ParseCoreHeader(const uint8_t* message,
|
||||
/* @@ prepare request functions */
|
||||
|
||||
OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
||||
uint8_t* message, size_t message_length, size_t* core_message_length,
|
||||
const ODK_NonceValues* nonce_values) {
|
||||
if (core_message_length == NULL || nonce_values == NULL) {
|
||||
uint8_t* message, size_t message_length, size_t* core_message_size,
|
||||
const ODK_NonceValues* nonce_values,
|
||||
const ODK_MessageCounterInfo* counter_info) {
|
||||
if (core_message_size == NULL || nonce_values == NULL ||
|
||||
counter_info == NULL) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedLicenseRequest license_request = {0};
|
||||
memcpy(&license_request.counter_info, counter_info,
|
||||
sizeof(license_request.counter_info));
|
||||
return ODK_PrepareRequest(
|
||||
message, message_length, core_message_length, ODK_License_Request_Type,
|
||||
message, message_length, core_message_size, ODK_License_Request_Type,
|
||||
nonce_values, &license_request, sizeof(ODK_PreparedLicenseRequest));
|
||||
}
|
||||
|
||||
@@ -230,25 +244,47 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
||||
|
||||
OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
||||
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) {
|
||||
if (core_message_length == NULL || nonce_values == NULL) {
|
||||
const ODK_NonceValues* nonce_values,
|
||||
const ODK_MessageCounterInfo* counter_info) {
|
||||
if (core_message_length == NULL || nonce_values == NULL ||
|
||||
counter_info == NULL) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedProvisioningRequest provisioning_request = {0};
|
||||
if (device_id_length > sizeof(provisioning_request.device_id)) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
provisioning_request.device_id_length = (uint32_t)device_id_length;
|
||||
if (device_id) {
|
||||
memcpy(provisioning_request.device_id, device_id, device_id_length);
|
||||
}
|
||||
memcpy(&provisioning_request.counter_info, counter_info,
|
||||
sizeof(ODK_MessageCounterInfo));
|
||||
|
||||
return ODK_PrepareRequest(message, message_length, core_message_length,
|
||||
ODK_Provisioning_Request_Type, nonce_values,
|
||||
&provisioning_request,
|
||||
sizeof(ODK_PreparedProvisioningRequest));
|
||||
}
|
||||
|
||||
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) {
|
||||
if (core_message_length == NULL || nonce_values == NULL ||
|
||||
counter_info == NULL) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedProvisioning40Request provisioning_request = {0};
|
||||
if (device_info_length > sizeof(provisioning_request.device_info)) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
provisioning_request.device_info_length = (uint32_t)device_info_length;
|
||||
if (device_info) {
|
||||
memcpy(provisioning_request.device_info, device_info, device_info_length);
|
||||
}
|
||||
memcpy(&provisioning_request.counter_info, counter_info,
|
||||
sizeof(provisioning_request.counter_info));
|
||||
|
||||
return ODK_PrepareRequest(message, message_length, core_message_length,
|
||||
ODK_Provisioning40_Request_Type, nonce_values,
|
||||
&provisioning_request,
|
||||
sizeof(provisioning_request));
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -285,14 +321,15 @@ OEMCryptoResult ODK_PrepareCoreRenewedProvisioningRequest(
|
||||
OEMCryptoResult ODK_ParseLicense(
|
||||
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||
bool initial_license_load, bool usage_entry_present,
|
||||
ODK_TimerLimits* timer_limits, ODK_ClockValues* clock_values,
|
||||
ODK_NonceValues* nonce_values, ODK_ParsedLicense* parsed_license) {
|
||||
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) {
|
||||
if (message == NULL || timer_limits == NULL || clock_values == NULL ||
|
||||
nonce_values == NULL || parsed_license == NULL) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
const OEMCryptoResult err =
|
||||
OEMCryptoResult err =
|
||||
ODK_ParseCoreHeader(message, message_length, core_message_length,
|
||||
ODK_License_Response_Type, nonce_values);
|
||||
if (err != OEMCrypto_SUCCESS) {
|
||||
@@ -303,68 +340,14 @@ OEMCryptoResult ODK_ParseLicense(
|
||||
license_response.parsed_license = parsed_license;
|
||||
|
||||
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||
|
||||
ODK_Message_SetSize(&msg, core_message_length);
|
||||
if (nonce_values->api_major_version == 16) {
|
||||
ODK_LicenseResponseV16 license_response_v16 = {0};
|
||||
Unpack_ODK_LicenseResponseV16(&msg, &license_response_v16);
|
||||
|
||||
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Unpack_ODK_LicenseResponse(&msg, &license_response);
|
||||
|
||||
// Need to manually set parsed_license fields to
|
||||
// license_response_v16.parsed_license field values since
|
||||
// license_response_v16 is no longer a pointer so parsed_license doesn't get
|
||||
// updated during the unpacking.
|
||||
parsed_license->enc_mac_keys_iv =
|
||||
license_response_v16.parsed_license.enc_mac_keys_iv;
|
||||
parsed_license->enc_mac_keys =
|
||||
license_response_v16.parsed_license.enc_mac_keys;
|
||||
parsed_license->pst = license_response_v16.parsed_license.pst;
|
||||
parsed_license->srm_restriction_data =
|
||||
license_response_v16.parsed_license.srm_restriction_data;
|
||||
parsed_license->license_type =
|
||||
license_response_v16.parsed_license.license_type;
|
||||
parsed_license->nonce_required =
|
||||
license_response_v16.parsed_license.nonce_required;
|
||||
parsed_license->timer_limits =
|
||||
license_response_v16.parsed_license.timer_limits;
|
||||
parsed_license->key_array_length =
|
||||
license_response_v16.parsed_license.key_array_length;
|
||||
uint32_t i;
|
||||
for (i = 0; i < parsed_license->key_array_length; i++) {
|
||||
parsed_license->key_array[i] =
|
||||
license_response_v16.parsed_license.key_array[i];
|
||||
}
|
||||
// Set fields not used in V16 to default values.
|
||||
parsed_license->watermarking = 0;
|
||||
// Set fields not used in V16 to default values.
|
||||
parsed_license->dtcp2_required.dtcp2_required = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_0.id = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_0.extension = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_0.length = 1;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_0.data = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_1.id = 1;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_1.extension = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_1.length = 3;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_1.data[0] = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_1.data[1] = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_1.data[2] = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_2.id = 2;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_2.extension = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_2.length = 3;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_2.data[0] = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_2.data[1] = 0;
|
||||
parsed_license->dtcp2_required.cmi_descriptor_2.data[2] = 0;
|
||||
license_response.request = license_response_v16.request;
|
||||
} else {
|
||||
Unpack_ODK_LicenseResponse(&msg, &license_response);
|
||||
|
||||
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
/* If the license has a provider session token (pst), then OEMCrypto should
|
||||
@@ -382,26 +365,38 @@ OEMCryptoResult ODK_ParseLicense(
|
||||
*/
|
||||
if (parsed_license->nonce_required && initial_license_load) {
|
||||
if (nonce_values->nonce !=
|
||||
license_response.request.core_message.nonce_values.nonce ||
|
||||
license_response.core_message.nonce_values.nonce ||
|
||||
nonce_values->session_id !=
|
||||
license_response.request.core_message.nonce_values.session_id) {
|
||||
license_response.core_message.nonce_values.session_id) {
|
||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
} else { /* !initial_license_load, or can't tell if initial. */
|
||||
nonce_values->nonce =
|
||||
license_response.request.core_message.nonce_values.nonce;
|
||||
nonce_values->nonce = license_response.core_message.nonce_values.nonce;
|
||||
nonce_values->session_id =
|
||||
license_response.request.core_message.nonce_values.session_id;
|
||||
license_response.core_message.nonce_values.session_id;
|
||||
/* Start the rental clock if not already started for reloading an offline
|
||||
* license without a nonce. */
|
||||
if (!parsed_license->nonce_required &&
|
||||
clock_values->time_of_license_request_signed == 0) {
|
||||
clock_values->time_of_license_request_signed = system_time_seconds;
|
||||
}
|
||||
}
|
||||
bool license_load =
|
||||
(parsed_license->renewal_delay_base == OEMCrypto_License_Load);
|
||||
*timer_limits = parsed_license->timer_limits;
|
||||
/* And update the clock values state. */
|
||||
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED;
|
||||
if (nonce_values->api_major_version == 18 && license_load) {
|
||||
err = ODK_AttemptFirstPlayback(system_time_seconds, timer_limits,
|
||||
clock_values, timer_value);
|
||||
return err;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
||||
size_t core_message_length,
|
||||
const ODK_NonceValues* nonce_values,
|
||||
ODK_NonceValues* nonce_values,
|
||||
uint64_t system_time,
|
||||
const ODK_TimerLimits* timer_limits,
|
||||
ODK_ClockValues* clock_values,
|
||||
@@ -413,7 +408,7 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
||||
|
||||
const OEMCryptoResult err =
|
||||
ODK_ParseCoreHeader(message, message_length, core_message_length,
|
||||
ODK_Renewal_Response_Type, NULL);
|
||||
ODK_Renewal_Response_Type, nonce_values);
|
||||
if (err != OEMCrypto_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
@@ -454,7 +449,7 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
||||
|
||||
OEMCryptoResult ODK_ParseProvisioning(
|
||||
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
||||
ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
||||
size_t device_id_length, ODK_ParsedProvisioning* parsed_response) {
|
||||
if (message == NULL || nonce_values == NULL || device_id == NULL ||
|
||||
parsed_response == NULL) {
|
||||
@@ -462,44 +457,96 @@ OEMCryptoResult ODK_ParseProvisioning(
|
||||
}
|
||||
const OEMCryptoResult err =
|
||||
ODK_ParseCoreHeader(message, message_length, core_message_length,
|
||||
ODK_Provisioning_Response_Type, NULL);
|
||||
ODK_Provisioning_Response_Type, nonce_values);
|
||||
if (err != OEMCrypto_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
ODK_ProvisioningResponse provisioning_response = {0};
|
||||
provisioning_response.parsed_provisioning = parsed_response;
|
||||
|
||||
if (device_id_length > ODK_DEVICE_ID_LEN_MAX) {
|
||||
if (nonce_values->api_major_version <= 17) {
|
||||
// Do v16/v17
|
||||
ODK_ProvisioningResponseV16 provisioning_response = {0};
|
||||
provisioning_response.parsed_provisioning = parsed_response;
|
||||
|
||||
if (device_id_length > ODK_DEVICE_ID_LEN_MAX) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||
ODK_Message_SetSize(&msg, core_message_length);
|
||||
Unpack_ODK_ProvisioningResponseV16(&msg, &provisioning_response);
|
||||
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
/* always verify nonce_values for Renewal and Provisioning responses */
|
||||
if (!ODK_NonceValuesEqualExcludingVersion(
|
||||
nonce_values,
|
||||
&(provisioning_response.request.core_message.nonce_values))) {
|
||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
|
||||
if (crypto_memcmp(device_id, provisioning_response.request.device_id,
|
||||
device_id_length) != 0) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
const uint8_t zero[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||
/* check bytes beyond device_id_length are 0 */
|
||||
if (crypto_memcmp(
|
||||
zero, provisioning_response.request.device_id + device_id_length,
|
||||
ODK_DEVICE_ID_LEN_MAX - device_id_length) != 0) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
} else {
|
||||
// v18
|
||||
ODK_ProvisioningResponse provisioning_response = {0};
|
||||
provisioning_response.parsed_provisioning = parsed_response;
|
||||
|
||||
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||
ODK_Message_SetSize(&msg, core_message_length);
|
||||
Unpack_ODK_ProvisioningResponse(&msg, &provisioning_response);
|
||||
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
/* always verify nonce_values for Renewal and Provisioning responses */
|
||||
if (!ODK_NonceValuesEqualExcludingVersion(
|
||||
nonce_values, &(provisioning_response.core_message.nonce_values))) {
|
||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
}
|
||||
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_ParseProvisioning40(const uint8_t* message,
|
||||
size_t message_length,
|
||||
size_t core_message_length,
|
||||
ODK_NonceValues* nonce_values) {
|
||||
if (message == NULL || nonce_values == NULL) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
const OEMCryptoResult err =
|
||||
ODK_ParseCoreHeader(message, message_length, core_message_length,
|
||||
ODK_Provisioning_Response_Type, nonce_values);
|
||||
if (err != OEMCrypto_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
ODK_Provisioning40Response provisioning_response = {0};
|
||||
|
||||
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||
ODK_Message_SetSize(&msg, core_message_length);
|
||||
Unpack_ODK_ProvisioningResponse(&msg, &provisioning_response);
|
||||
Unpack_ODK_Provisioning40Response(&msg, &provisioning_response);
|
||||
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
/* always verify nonce_values for Renewal and Provisioning responses */
|
||||
if (!ODK_NonceValuesEqualExcludingVersion(
|
||||
nonce_values,
|
||||
&(provisioning_response.request.core_message.nonce_values))) {
|
||||
nonce_values, &(provisioning_response.core_message.nonce_values))) {
|
||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
|
||||
if (crypto_memcmp(device_id, provisioning_response.request.device_id,
|
||||
device_id_length) != 0) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
const uint8_t zero[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||
/* check bytes beyond device_id_length are 0 */
|
||||
if (crypto_memcmp(zero,
|
||||
provisioning_response.request.device_id + device_id_length,
|
||||
ODK_DEVICE_ID_LEN_MAX - device_id_length) != 0) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user