Merge latest oemcrypto-v17 change

No-Typo-Check: Not related to this change.

Bug: 161477208
Change-Id: I99e4780f6855b7045aa0cd5a49c13d2d0d51ed64
This commit is contained in:
Kyle Zhang
2022-01-21 05:58:12 +00:00
committed by Fred Gylys-Colwell
parent c924960962
commit 642965c678
176 changed files with 301013 additions and 296749 deletions

View File

@@ -91,64 +91,65 @@ static OEMCryptoResult ODK_PrepareRequest(
return OEMCrypto_SUCCESS;
}
static OEMCryptoResult ODK_ParseResponse(
const uint8_t* message, size_t message_length, size_t core_message_length,
ODK_MessageType message_type, const ODK_NonceValues* nonce_values,
void* response_buffer, uint32_t response_buffer_length) {
if (message == NULL || response_buffer == NULL ||
core_message_length > message_length) {
/* Parse the core message and verify that it has the right type. The nonce
* values are updated to hold the response's API version.
*/
static OEMCryptoResult ODK_ParseCoreHeader(const uint8_t* message,
size_t message_length,
size_t core_message_length,
ODK_MessageType message_type,
ODK_NonceValues* nonce_values) {
// The core_message_length is the length of the core message, which is a
// substring of the complete message.
if (message == NULL || core_message_length > message_length) {
return ODK_ERROR_CORE_MESSAGE;
}
ODK_CoreMessage core_message;
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
/* The core message should be at the beginning of the buffer, and with a
* shorter length. The core message is the part we are parsing. */
/* The core message should be at the beginning of the buffer. The core message
* is the part we are parsing. */
ODK_Message_SetSize(&msg, core_message_length);
Unpack_ODK_CoreMessage(&msg, &core_message);
/* Parse message and unpack it into response buffer. */
switch (message_type) {
case ODK_License_Response_Type: {
if (sizeof(ODK_LicenseResponse) > response_buffer_length) {
return ODK_ERROR_CORE_MESSAGE;
}
Unpack_ODK_LicenseResponse(&msg, (ODK_LicenseResponse*)response_buffer);
break;
}
case ODK_Renewal_Response_Type: {
if (sizeof(ODK_RenewalResponse) > response_buffer_length) {
return ODK_ERROR_CORE_MESSAGE;
}
Unpack_ODK_RenewalResponse(&msg, (ODK_RenewalResponse*)response_buffer);
break;
}
case ODK_Provisioning_Response_Type: {
if (sizeof(ODK_ProvisioningResponse) > response_buffer_length) {
return ODK_ERROR_CORE_MESSAGE;
}
Unpack_ODK_ProvisioningResponse(
&msg, (ODK_ProvisioningResponse*)response_buffer);
break;
}
default: {
return ODK_ERROR_CORE_MESSAGE;
}
}
ODK_CoreMessage* core_message = (ODK_CoreMessage*)response_buffer;
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
message_type != core_message->message_type ||
ODK_Message_GetOffset(&msg) != core_message->message_length) {
message_type != core_message.message_type) {
return ODK_ERROR_CORE_MESSAGE;
}
// The current offset should be the end of the header, which is the message
// type, message length, api version, and nonce fields. The header can't be
// larger than the whole core message. Also, the core message specifies its
// length, which should be exactly the length of the core message buffer.
if (ODK_Message_GetOffset(&msg) > core_message.message_length ||
core_message.message_length != core_message_length) {
return ODK_ERROR_CORE_MESSAGE;
}
/* We do not support future API version. Also, this function should not be
* used for legacy licenses without a core message. */
if (core_message.nonce_values.api_major_version > ODK_MAJOR_VERSION ||
core_message.nonce_values.api_major_version < ODK_FIRST_VERSION) {
return ODK_UNSUPPORTED_API;
}
if (nonce_values) {
/* always verify nonce_values for Renewal and Provisioning responses */
if (!ODK_NonceValuesEqual(nonce_values, &(core_message->nonce_values))) {
return OEMCrypto_ERROR_INVALID_NONCE;
/* If the server sent us an older format, record the message's API version.
*/
if (nonce_values->api_major_version >
core_message.nonce_values.api_major_version) {
// If the major version is smaller, use both values from the server.
nonce_values->api_major_version =
core_message.nonce_values.api_major_version;
nonce_values->api_minor_version =
core_message.nonce_values.api_minor_version;
} else if (nonce_values->api_major_version ==
core_message.nonce_values.api_major_version &&
nonce_values->api_minor_version >
core_message.nonce_values.api_minor_version) {
// Otherwise, if the major versions are equal, but the minor is smaller,
// then we should lower the minor version.
nonce_values->api_minor_version =
core_message.nonce_values.api_minor_version;
}
}
return OEMCrypto_SUCCESS;
}
@@ -162,9 +163,7 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
if (core_message_length == NULL || nonce_values == NULL) {
return ODK_ERROR_CORE_MESSAGE;
}
ODK_PreparedLicenseRequest license_request = {
{0, 0, {}},
};
ODK_PreparedLicenseRequest license_request = {0};
return ODK_PrepareRequest(
message, message_length, core_message_length, ODK_License_Request_Type,
nonce_values, &license_request, sizeof(ODK_PreparedLicenseRequest));
@@ -192,7 +191,7 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
return OEMCrypto_SUCCESS;
}
ODK_PreparedRenewalRequest renewal_request = {{0, 0, {}}, 0};
ODK_PreparedRenewalRequest renewal_request = {0};
/* First, we compute the time this request was made relative to the playback
* clock. */
if (clock_values->time_of_first_decrypt == 0) {
@@ -225,11 +224,7 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
if (core_message_length == NULL || nonce_values == NULL) {
return ODK_ERROR_CORE_MESSAGE;
}
ODK_PreparedProvisioningRequest provisioning_request = {
{0, 0, {}},
0,
{0},
};
ODK_PreparedProvisioningRequest provisioning_request = {0};
if (device_id_length > sizeof(provisioning_request.device_id)) {
return ODK_ERROR_CORE_MESSAGE;
}
@@ -248,47 +243,88 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
OEMCryptoResult ODK_ParseLicense(
const uint8_t* message, size_t message_length, size_t core_message_length,
bool initial_license_load, bool usage_entry_present,
const uint8_t* request_hash, ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values, ODK_NonceValues* nonce_values,
ODK_ParsedLicense* parsed_license) {
if (message == NULL || request_hash == NULL || timer_limits == NULL ||
clock_values == NULL || nonce_values == NULL || parsed_license == NULL) {
ODK_TimerLimits* timer_limits, ODK_ClockValues* clock_values,
ODK_NonceValues* nonce_values, ODK_ParsedLicense* parsed_license) {
if (message == NULL || timer_limits == NULL || clock_values == NULL ||
nonce_values == NULL || parsed_license == NULL) {
return ODK_ERROR_CORE_MESSAGE;
}
ODK_LicenseResponse license_response = {{{0, 0, {}}}, NULL, {0}};
license_response.parsed_license = parsed_license;
const OEMCryptoResult err = ODK_ParseResponse(
message, message_length, core_message_length, ODK_License_Response_Type,
NULL, &license_response, sizeof(ODK_LicenseResponse));
const OEMCryptoResult err =
ODK_ParseCoreHeader(message, message_length, core_message_length,
ODK_License_Response_Type, nonce_values);
if (err != OEMCrypto_SUCCESS) {
return err;
}
/* We do not support future API version. Also, this function should not be
* used for legacy licenses. */
if (license_response.request.core_message.nonce_values.api_major_version >
ODK_MAJOR_VERSION ||
license_response.request.core_message.nonce_values.api_major_version <
ODK_FIRST_VERSION) {
return ODK_UNSUPPORTED_API;
ODK_LicenseResponse license_response = {0};
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;
}
// 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 the server sent us an older format, record the license's API version. */
if (nonce_values->api_major_version >
license_response.request.core_message.nonce_values.api_major_version) {
nonce_values->api_major_version =
license_response.request.core_message.nonce_values.api_major_version;
nonce_values->api_minor_version =
license_response.request.core_message.nonce_values.api_minor_version;
} else if (nonce_values->api_minor_version >
license_response.request.core_message.nonce_values
.api_minor_version) {
nonce_values->api_minor_version =
license_response.request.core_message.nonce_values.api_minor_version;
}
/* If the license has a provider session token (pst), then OEMCrypto should
* have a usage entry loaded. The opposite is also an error. */
if ((usage_entry_present && parsed_license->pst.length == 0) ||
@@ -315,15 +351,6 @@ OEMCryptoResult ODK_ParseLicense(
nonce_values->session_id =
license_response.request.core_message.nonce_values.session_id;
}
/* For v16, in order to be backwards compatible with a v15 license server,
* OEMCrypto stores a hash of the core license request and only signs the
* message body. Here, when we process the license response, we verify that
* the server has the same hash of the core request. */
if (initial_license_load && parsed_license->nonce_required &&
crypto_memcmp(request_hash, license_response.request_hash,
ODK_SHA256_HASH_SIZE)) {
return ODK_ERROR_CORE_MESSAGE;
}
*timer_limits = parsed_license->timer_limits;
/* And update the clock values state. */
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED;
@@ -342,17 +369,27 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
return ODK_ERROR_CORE_MESSAGE;
}
ODK_RenewalResponse renewal_response = {
{{0, 0, {}}, 0},
0,
};
const OEMCryptoResult err = ODK_ParseResponse(
message, message_length, core_message_length, ODK_Renewal_Response_Type,
nonce_values, &renewal_response, sizeof(ODK_RenewalResponse));
const OEMCryptoResult err =
ODK_ParseCoreHeader(message, message_length, core_message_length,
ODK_Renewal_Response_Type, NULL);
if (err != OEMCrypto_SUCCESS) {
return err;
}
ODK_RenewalResponse renewal_response = {0};
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
ODK_Message_SetSize(&msg, core_message_length);
Unpack_ODK_RenewalResponse(&msg, &renewal_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,
&(renewal_response.request.core_message.nonce_values))) {
return OEMCrypto_ERROR_INVALID_NONCE;
}
/* Reference:
* Doc: License Duration and Renewal (Changes for OEMCrypto v16)
@@ -381,21 +418,31 @@ OEMCryptoResult ODK_ParseProvisioning(
parsed_response == NULL) {
return ODK_ERROR_CORE_MESSAGE;
}
ODK_ProvisioningResponse provisioning_response = {{{0, 0, {}}, 0, {0}}, NULL};
const OEMCryptoResult err =
ODK_ParseCoreHeader(message, message_length, core_message_length,
ODK_Provisioning_Response_Type, NULL);
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) {
return ODK_ERROR_CORE_MESSAGE;
}
const OEMCryptoResult err = ODK_ParseResponse(
message, message_length, core_message_length,
ODK_Provisioning_Response_Type, nonce_values, &provisioning_response,
sizeof(ODK_ProvisioningResponse));
if (err != OEMCrypto_SUCCESS) {
return err;
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.request.core_message.nonce_values))) {
return OEMCrypto_ERROR_INVALID_NONCE;
}
if (crypto_memcmp(device_id, provisioning_response.request.device_id,
@@ -413,3 +460,10 @@ OEMCryptoResult ODK_ParseProvisioning(
return OEMCrypto_SUCCESS;
}
bool CheckApiVersionAtMost(const ODK_NonceValues* nonce_values,
uint16_t major_version, uint16_t minor_version) {
return nonce_values->api_major_version < major_version ||
(nonce_values->api_major_version == major_version &&
nonce_values->api_minor_version <= minor_version);
}