Update ODK Library and add license release unit test
Merge from Widevine repo of two CLs. Merge from Widevine repo of http://go/wvgerrit/94743 A license release should not have a core message. This CL adjusts the existing unit tests to verify this. There is also a new unit test called SecureStop that explicitly tests sending a secure stop in a new session without first loading the license. Merge from Widevine repo of http://go/wvgerrit/94865 This CL has the following changes copied from google3: http://cr/298871728 Remove odk_static_assert for Message size temporarily http://cr/298755935 Fix a compiling error during macro expansion http://cr/298481745 Add missing header for android http://cr/298448142 Fix odk_test gyp file http://cr/298419641 Remove header from Android.bp http://cr/298402053 Separate sizeOf(args) bytes in fuzz tests http://cr/297730316 No core messages for license release http://cr/297714346 Add copybara_test and piper_sot_to_gerrit http://cr/297636713 Adding some comments around boolean conversion code http://cr/297420679 Autofuzzer when ran with address sanitizer ... http://cr/296513584 Minor fix with fuzzing odk clock values http://cr/296322024 Fixing errors in code with how request ... http://cr/296313159 Fuzzing ODK clock values by setting aside ... http://cr/295763207 Add more odk tests and move helper functions to test helper http://cr/294524098 Adding a Build Rule for ODK_KDO_Fuzzer and updating http://cr/294492213 Address a few review comments of ODK http://cr/293674368 odk_fuzz: add TODOs & comments http://cr/293492806 Fix spelling Bug: 150243585 Bug: 150020278 Bug: 150095506 Bug: 147297226 Bug: 148290294 Bug: 148907684 Bug: 150608451 Test: unit tests Change-Id: I25fd406f29f4eba40f5cb27e9a1317dce4ffc2f5
This commit is contained in:
committed by
Jeff Tinker
parent
0947bd185b
commit
c5b7a01ab5
@@ -138,10 +138,8 @@ bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
|
||||
parsed_lic.nonce_required = nonce_required;
|
||||
const auto& policy = lic.policy();
|
||||
ODK_TimerLimits& timer_limits = parsed_lic.timer_limits;
|
||||
// TODO(b/148241181): add field to protobuf.
|
||||
// timer_limits.soft_enforce_rental_duration =
|
||||
// policy.soft_enforce_rental_duration();
|
||||
timer_limits.soft_enforce_rental_duration = true;
|
||||
timer_limits.soft_enforce_rental_duration =
|
||||
policy.soft_enforce_rental_duration();
|
||||
timer_limits.soft_enforce_playback_duration =
|
||||
policy.soft_enforce_playback_duration();
|
||||
timer_limits.earliest_playback_start_seconds = 0;
|
||||
|
||||
@@ -15,48 +15,63 @@
|
||||
#include "odk_util.h"
|
||||
#include "serialization_base.h"
|
||||
|
||||
#define ODK_LICENSE_REQUEST_SIZE 20
|
||||
#define ODK_RENEWAL_REQUEST_SIZE 28
|
||||
#define ODK_PROVISIONING_REQUEST_SIZE 88
|
||||
|
||||
/* @ private odk functions */
|
||||
|
||||
static OEMCryptoResult ODK_PrepareRequest(uint8_t* buffer, size_t buffer_length,
|
||||
size_t* core_message_length,
|
||||
uint32_t message_type,
|
||||
const ODK_NonceValues* nonce_values,
|
||||
ODK_CoreMessage* core_message) {
|
||||
static OEMCryptoResult ODK_PrepareRequest(
|
||||
uint8_t* message, size_t message_length, size_t* core_message_length,
|
||||
uint32_t message_type, const ODK_NonceValues* nonce_values,
|
||||
void* prepared_request_buffer, size_t prepared_request_buffer_length) {
|
||||
if (nonce_values == NULL || core_message_length == NULL ||
|
||||
core_message == NULL || *core_message_length > buffer_length) {
|
||||
prepared_request_buffer == NULL ||
|
||||
*core_message_length > message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
Message* msg = NULL;
|
||||
AllocateMessage(&msg, message_block);
|
||||
InitMessage(msg, buffer, *core_message_length);
|
||||
InitMessage(msg, message, *core_message_length);
|
||||
|
||||
/* The core message should be at the beginning of the buffer, and with a
|
||||
* shorter length. */
|
||||
if (sizeof(ODK_CoreMessage) > prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_CoreMessage* core_message = (ODK_CoreMessage*)prepared_request_buffer;
|
||||
*core_message = (ODK_CoreMessage){
|
||||
message_type,
|
||||
0,
|
||||
*nonce_values,
|
||||
};
|
||||
|
||||
/* Set core message length, and pack prepared request into message if the
|
||||
* message buffer has been correctly initialized by the caller. */
|
||||
switch (message_type) {
|
||||
case ODK_License_Request_Type: {
|
||||
core_message->message_length = ODK_LICENSE_REQUEST_SIZE;
|
||||
if (sizeof(ODK_PreparedLicenseRequest) > prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedLicenseRequest(
|
||||
msg, (ODK_PreparedLicenseRequest*)core_message);
|
||||
msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Renewal_Request_Type: {
|
||||
core_message->message_length = ODK_RENEWAL_REQUEST_SIZE;
|
||||
if (sizeof(ODK_PreparedRenewalRequest) > prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedRenewalRequest(
|
||||
msg, (ODK_PreparedRenewalRequest*)core_message);
|
||||
msg, (ODK_PreparedRenewalRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Provisioning_Request_Type: {
|
||||
core_message->message_length = ODK_PROVISIONING_REQUEST_SIZE;
|
||||
if (sizeof(ODK_PreparedProvisioningRequest) >
|
||||
prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedProvisioningRequest(
|
||||
msg, (ODK_PreparedProvisioningRequest*)core_message);
|
||||
msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -65,43 +80,59 @@ static OEMCryptoResult ODK_PrepareRequest(uint8_t* buffer, size_t buffer_length,
|
||||
}
|
||||
|
||||
*core_message_length = core_message->message_length;
|
||||
if (GetStatus(msg) != MESSAGE_STATUS_OK ||
|
||||
GetSize(msg) != *core_message_length) {
|
||||
if (GetStatus(msg) != MESSAGE_STATUS_OK) {
|
||||
/* This is to indicate the caller that the core_message_length has been
|
||||
* appropriately set, but the message buffer is either empty or too small,
|
||||
* which needs to be initialized and filled in the subsequent call. */
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
if (GetSize(msg) != *core_message_length) {
|
||||
/* This should not happen. Something is wrong. */
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
static OEMCryptoResult ODK_ParseResponse(const uint8_t* buf,
|
||||
size_t message_length,
|
||||
size_t core_message_length,
|
||||
uint32_t message_type,
|
||||
const ODK_NonceValues* nonce_values,
|
||||
ODK_CoreMessage* const core_message) {
|
||||
if (core_message_length > message_length) {
|
||||
static OEMCryptoResult ODK_ParseResponse(
|
||||
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||
uint32_t 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) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
Message* msg = NULL;
|
||||
AllocateMessage(&msg, message_block);
|
||||
/* We initialize the message buffer with a size of the entire message
|
||||
* length. */
|
||||
InitMessage(msg, (uint8_t*)buf, message_length);
|
||||
InitMessage(msg, (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. */
|
||||
SetSize(msg, core_message_length);
|
||||
|
||||
/* Parse message and unpack it into response buffer. */
|
||||
switch (message_type) {
|
||||
case ODK_License_Response_Type: {
|
||||
Unpack_ODK_LicenseResponse(msg, (ODK_LicenseResponse*)core_message);
|
||||
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: {
|
||||
Unpack_ODK_RenewalResponse(msg, (ODK_RenewalResponse*)core_message);
|
||||
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: {
|
||||
Unpack_ODK_ProvisioningResponse(msg,
|
||||
(ODK_ProvisioningResponse*)core_message);
|
||||
if (sizeof(ODK_ProvisioningResponse) > response_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Unpack_ODK_ProvisioningResponse(
|
||||
msg, (ODK_ProvisioningResponse*)response_buffer);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -109,6 +140,7 @@ static OEMCryptoResult ODK_ParseResponse(const uint8_t* buf,
|
||||
}
|
||||
}
|
||||
|
||||
ODK_CoreMessage* core_message = (ODK_CoreMessage*)response_buffer;
|
||||
if (GetStatus(msg) != MESSAGE_STATUS_OK ||
|
||||
message_type != core_message->message_type ||
|
||||
GetOffset(msg) != core_message->message_length) {
|
||||
@@ -117,12 +149,7 @@ static OEMCryptoResult ODK_ParseResponse(const uint8_t* buf,
|
||||
|
||||
if (nonce_values) {
|
||||
/* always verify nonce_values for Renewal and Provisioning responses */
|
||||
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 ||
|
||||
nonce_values->nonce != core_message->nonce_values.nonce ||
|
||||
nonce_values->session_id != core_message->nonce_values.session_id) {
|
||||
if (!ODK_NonceValuesEqual(nonce_values, &(core_message->nonce_values))) {
|
||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
}
|
||||
@@ -137,12 +164,15 @@ static OEMCryptoResult ODK_ParseResponse(const uint8_t* buf,
|
||||
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) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedLicenseRequest license_request = {
|
||||
{0},
|
||||
};
|
||||
return ODK_PrepareRequest(message, message_length, core_message_length,
|
||||
ODK_License_Request_Type, nonce_values,
|
||||
&license_request.core_message);
|
||||
return ODK_PrepareRequest(
|
||||
message, message_length, core_message_length, ODK_License_Request_Type,
|
||||
nonce_values, &license_request, sizeof(ODK_PreparedLicenseRequest));
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
||||
@@ -151,8 +181,22 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
||||
ODK_NonceValues* nonce_values,
|
||||
ODK_ClockValues* clock_values,
|
||||
uint64_t system_time_seconds) {
|
||||
if (nonce_values == NULL || clock_values == NULL)
|
||||
if (core_message_size == NULL || nonce_values == NULL ||
|
||||
clock_values == NULL) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
/* If the license has not been loaded, then this is release instead of a
|
||||
* renewal. All releases use v15. */
|
||||
if (clock_values->timer_status == ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED ||
|
||||
clock_values->timer_status == ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE) {
|
||||
nonce_values->api_major_version = 15;
|
||||
}
|
||||
if (nonce_values->api_major_version < 16) {
|
||||
*core_message_size = 0;
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
ODK_PreparedRenewalRequest renewal_request = {{0}, 0};
|
||||
/* First, we compute the time this request was made relative to the playback
|
||||
* clock. */
|
||||
@@ -168,19 +212,24 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save time for this request so that we can verify the response. This makes
|
||||
* all earlier requests invalid. If preparing this request fails, then all
|
||||
* requests will be bad. */
|
||||
clock_values->time_of_renewal_request = renewal_request.playback_time;
|
||||
return ODK_PrepareRequest(message, message_length, core_message_size,
|
||||
ODK_Renewal_Request_Type, nonce_values,
|
||||
&renewal_request.core_message);
|
||||
|
||||
return ODK_PrepareRequest(
|
||||
message, message_length, core_message_size, ODK_Renewal_Request_Type,
|
||||
nonce_values, &renewal_request, sizeof(ODK_PreparedRenewalRequest));
|
||||
}
|
||||
|
||||
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) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedProvisioningRequest provisioning_request = {
|
||||
{0},
|
||||
0,
|
||||
@@ -195,7 +244,8 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
||||
}
|
||||
return ODK_PrepareRequest(message, message_length, core_message_length,
|
||||
ODK_Provisioning_Request_Type, nonce_values,
|
||||
&provisioning_request.core_message);
|
||||
&provisioning_request,
|
||||
sizeof(ODK_PreparedProvisioningRequest));
|
||||
}
|
||||
|
||||
/* @@ parse request functions */
|
||||
@@ -214,7 +264,7 @@ OEMCryptoResult ODK_ParseLicense(
|
||||
ODK_LicenseResponse license_response = {{{0}}, parsed_license, {0}};
|
||||
const OEMCryptoResult err = ODK_ParseResponse(
|
||||
message, message_length, core_message_length, ODK_License_Response_Type,
|
||||
NULL, &license_response.request.core_message);
|
||||
NULL, &license_response, sizeof(ODK_LicenseResponse));
|
||||
|
||||
if (err != OEMCrypto_SUCCESS) {
|
||||
return err;
|
||||
@@ -279,11 +329,11 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
||||
{{0}, 0},
|
||||
0,
|
||||
};
|
||||
OEMCryptoResult err = ODK_ParseResponse(
|
||||
const OEMCryptoResult err = ODK_ParseResponse(
|
||||
message, message_length, core_message_length, ODK_Renewal_Response_Type,
|
||||
nonce_values, &renewal_response.request.core_message);
|
||||
nonce_values, &renewal_response, sizeof(ODK_RenewalResponse));
|
||||
|
||||
if (err) {
|
||||
if (err != OEMCrypto_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -318,24 +368,24 @@ OEMCryptoResult ODK_ParseProvisioning(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
OEMCryptoResult err =
|
||||
ODK_ParseResponse(message, message_length, core_message_length,
|
||||
ODK_Provisioning_Response_Type, nonce_values,
|
||||
&provisioning_response.request.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) {
|
||||
if (err != OEMCrypto_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (memcmp(device_id, provisioning_response.request.device_id,
|
||||
device_id_length)) {
|
||||
if (crypto_memcmp(device_id, provisioning_response.request.device_id,
|
||||
device_id_length) != 0) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
uint8_t zero[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||
const uint8_t zero[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||
/* check bytes beyond device_id_length are 0 */
|
||||
if (memcmp(zero, provisioning_response.request.device_id + device_id_length,
|
||||
ODK_DEVICE_ID_LEN_MAX - device_id_length)) {
|
||||
ODK_DEVICE_ID_LEN_MAX - device_id_length) != 0) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,10 @@ typedef struct {
|
||||
ODK_ParsedProvisioning* parsed_provisioning;
|
||||
} ODK_ProvisioningResponse;
|
||||
|
||||
#define ODK_LICENSE_REQUEST_SIZE 20
|
||||
#define ODK_RENEWAL_REQUEST_SIZE 28
|
||||
#define ODK_PROVISIONING_REQUEST_SIZE 88
|
||||
|
||||
/* These are the possible timer status values. */
|
||||
#define ODK_CLOCK_TIMER_STATUS_UNDEFINED 0 /* Should not happen. */
|
||||
/* When the structure has been initialized, but no license is loaded. */
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "odk.h"
|
||||
#include "odk_overflow.h"
|
||||
#include "odk_structs_priv.h"
|
||||
@@ -12,8 +11,7 @@
|
||||
/* Private function. Checks to see if the license is active. Returns
|
||||
* ODK_TIMER_EXPIRED if the license is valid but inactive. Returns
|
||||
* OEMCrypto_SUCCESS if the license is active. Returns
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE on other errors. This also updates the
|
||||
* timer_status if appropriate. */
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE on other errors. */
|
||||
static OEMCryptoResult ODK_LicenseActive(const ODK_TimerLimits* timer_limits,
|
||||
ODK_ClockValues* clock_values) {
|
||||
/* Check some basic errors. */
|
||||
@@ -26,7 +24,6 @@ static OEMCryptoResult ODK_LicenseActive(const ODK_TimerLimits* timer_limits,
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (clock_values->status > kActive) {
|
||||
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE;
|
||||
return ODK_TIMER_EXPIRED;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
@@ -157,7 +154,9 @@ static OEMCryptoResult ODK_CheckPlaybackWindow(
|
||||
* have already computed the timer limit. */
|
||||
static void ODK_UpdateTimerStatusForRenewal(ODK_ClockValues* clock_values,
|
||||
uint32_t new_status) {
|
||||
if (clock_values == NULL) return; /* should not happen. */
|
||||
if (clock_values == NULL) {
|
||||
return; /* should not happen. */
|
||||
}
|
||||
if (clock_values->timer_status == ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED) {
|
||||
/* Signal that the timer is already set. */
|
||||
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_RENEWAL_LOADED;
|
||||
@@ -174,17 +173,21 @@ OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
||||
uint64_t system_time_seconds,
|
||||
uint64_t new_renewal_duration,
|
||||
uint64_t* timer_value) {
|
||||
if (timer_limits == NULL || clock_values == NULL)
|
||||
if (timer_limits == NULL || clock_values == NULL) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT; /* should not happen. */
|
||||
}
|
||||
/* If this is before the license was signed, something is odd. Return an
|
||||
* error. */
|
||||
if (system_time_seconds < clock_values->time_of_license_signed)
|
||||
if (system_time_seconds < clock_values->time_of_license_signed) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
|
||||
const OEMCryptoResult license_status =
|
||||
ODK_LicenseActive(timer_limits, clock_values);
|
||||
/* If the license is not active, then we cannot renew the license. */
|
||||
if (license_status != OEMCrypto_SUCCESS) return license_status;
|
||||
if (license_status != OEMCrypto_SUCCESS) {
|
||||
return license_status;
|
||||
}
|
||||
|
||||
/* We start with the new renewal duration as the new timer limit. */
|
||||
uint64_t new_timer_value = new_renewal_duration;
|
||||
@@ -193,9 +196,12 @@ OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
||||
* new_timer_value. */
|
||||
const OEMCryptoResult rental_status = ODK_CheckRentalWindow(
|
||||
timer_limits, clock_values, system_time_seconds, &new_timer_value);
|
||||
|
||||
/* If the rental status forbids playback, then we're done. */
|
||||
if ((rental_status != ODK_DISABLE_TIMER) && (rental_status != ODK_SET_TIMER))
|
||||
if ((rental_status != ODK_DISABLE_TIMER) &&
|
||||
(rental_status != ODK_SET_TIMER)) {
|
||||
return rental_status;
|
||||
}
|
||||
|
||||
/* If playback has already started and it has hard enforcement, then check
|
||||
* total playback window. */
|
||||
@@ -207,8 +213,9 @@ OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
||||
/* If the timer limits forbid playback in the playback window, then we're
|
||||
* done. */
|
||||
if ((playback_status != ODK_DISABLE_TIMER) &&
|
||||
(playback_status != ODK_SET_TIMER))
|
||||
(playback_status != ODK_SET_TIMER)) {
|
||||
return playback_status;
|
||||
}
|
||||
}
|
||||
|
||||
/* If new_timer_value is infinite (represented by 0), then there are no
|
||||
@@ -219,6 +226,7 @@ OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
||||
ODK_CLOCK_TIMER_STATUS_UNLIMITED);
|
||||
return ODK_DISABLE_TIMER;
|
||||
}
|
||||
|
||||
/* If the caller gave us a pointer to store the new timer value. Fill it. */
|
||||
if (timer_value != NULL) {
|
||||
*timer_value = new_timer_value;
|
||||
@@ -241,8 +249,9 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
|
||||
ODK_NonceValues* nonce_values,
|
||||
uint32_t api_major_version,
|
||||
uint32_t session_id) {
|
||||
if (clock_values == NULL || clock_values == NULL || nonce_values == NULL)
|
||||
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
/* Check that the API version passed in from OEMCrypto matches the version of
|
||||
* this ODK library. */
|
||||
if (api_major_version != ODK_MAJOR_VERSION) {
|
||||
@@ -269,7 +278,9 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
|
||||
* OEMCrypto_GenerateNonce. */
|
||||
OEMCryptoResult ODK_SetNonceValues(ODK_NonceValues* nonce_values,
|
||||
uint32_t nonce) {
|
||||
if (nonce_values == NULL) return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
if (nonce_values == NULL) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
/* Setting the nonce should only happen once per session. */
|
||||
if (nonce_values->nonce != 0) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
@@ -281,7 +292,9 @@ OEMCryptoResult ODK_SetNonceValues(ODK_NonceValues* nonce_values,
|
||||
/* This is called when OEMCrypto signs a license. */
|
||||
OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
|
||||
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_first_decrypt = 0;
|
||||
clock_values->time_of_last_decrypt = 0;
|
||||
@@ -298,7 +311,9 @@ OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
|
||||
uint64_t time_of_last_decrypt,
|
||||
enum OEMCrypto_Usage_Entry_Status status,
|
||||
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 = time_of_license_signed;
|
||||
clock_values->time_of_first_decrypt = time_of_first_decrypt;
|
||||
clock_values->time_of_last_decrypt = time_of_last_decrypt;
|
||||
@@ -313,8 +328,9 @@ OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
|
||||
const ODK_TimerLimits* timer_limits,
|
||||
ODK_ClockValues* clock_values,
|
||||
uint64_t* timer_value) {
|
||||
if (clock_values == NULL || timer_limits == NULL)
|
||||
if (clock_values == NULL || timer_limits == NULL) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
/* All times are relative to when the license was signed. */
|
||||
uint64_t rental_time = 0;
|
||||
if (odk_sub_overflow_u64(system_time_seconds,
|
||||
@@ -328,7 +344,9 @@ OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
|
||||
}
|
||||
/* If the license is inactive or not loaded, then playback is not allowed. */
|
||||
OEMCryptoResult status = ODK_LicenseActive(timer_limits, clock_values);
|
||||
if (status != OEMCrypto_SUCCESS) return status;
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* We start with the initial renewal duration as the timer limit. */
|
||||
uint64_t new_timer_value = timer_limits->initial_renewal_duration_seconds;
|
||||
@@ -348,7 +366,9 @@ OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
|
||||
* new_timer_value. */
|
||||
status = ODK_CheckRentalWindow(timer_limits, clock_values,
|
||||
system_time_seconds, &new_timer_value);
|
||||
if ((status != ODK_DISABLE_TIMER) && (status != ODK_SET_TIMER)) return status;
|
||||
if ((status != ODK_DISABLE_TIMER) && (status != ODK_SET_TIMER)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* If playback has not already started, then this is the first playback. */
|
||||
if (clock_values->time_of_first_decrypt == 0) {
|
||||
@@ -360,7 +380,9 @@ OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
|
||||
* restrictions. This might decrease new_timer_value. */
|
||||
status = ODK_CheckPlaybackWindow(timer_limits, clock_values,
|
||||
system_time_seconds, &new_timer_value);
|
||||
if ((status != ODK_DISABLE_TIMER) && (status != ODK_SET_TIMER)) return status;
|
||||
if ((status != ODK_DISABLE_TIMER) && (status != ODK_SET_TIMER)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* We know we are allowed to decrypt. The rest computes the timer duration. */
|
||||
clock_values->time_of_last_decrypt = system_time_seconds;
|
||||
@@ -390,7 +412,9 @@ OEMCryptoResult ODK_UpdateLastPlaybackTime(uint64_t system_time_seconds,
|
||||
const ODK_TimerLimits* timer_limits,
|
||||
ODK_ClockValues* clock_values) {
|
||||
OEMCryptoResult status = ODK_LicenseActive(timer_limits, clock_values);
|
||||
if (status != OEMCrypto_SUCCESS) return status;
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
switch (clock_values->timer_status) {
|
||||
case ODK_CLOCK_TIMER_STATUS_UNLIMITED:
|
||||
break;
|
||||
@@ -413,7 +437,9 @@ OEMCryptoResult ODK_UpdateLastPlaybackTime(uint64_t system_time_seconds,
|
||||
|
||||
/* This is called from OEMCrypto_DeactivateUsageEntry. */
|
||||
OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values) {
|
||||
if (clock_values == NULL) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
if (clock_values == NULL) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (clock_values->status == kUnused) {
|
||||
clock_values->status = kInactiveUnused;
|
||||
} else if (clock_values->status == kActive) {
|
||||
@@ -430,8 +456,9 @@ OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
|
||||
ODK_NonceValues* nonce_values,
|
||||
uint32_t key_duration,
|
||||
uint64_t system_time_seconds) {
|
||||
if (clock_values == NULL || clock_values == NULL || nonce_values == NULL)
|
||||
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
timer_limits->soft_enforce_playback_duration = false;
|
||||
timer_limits->soft_enforce_rental_duration = false;
|
||||
timer_limits->earliest_playback_start_seconds = 0;
|
||||
@@ -458,12 +485,14 @@ OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
|
||||
uint64_t system_time_seconds,
|
||||
uint32_t new_key_duration,
|
||||
uint64_t* timer_value) {
|
||||
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL)
|
||||
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
if (nonce_values->api_major_version != 15)
|
||||
}
|
||||
if (nonce_values->api_major_version != 15) {
|
||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
if (clock_values->status > kActive) {
|
||||
clock_values->timer_status = ODK_TIMER_EXPIRED;
|
||||
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE;
|
||||
return ODK_TIMER_EXPIRED;
|
||||
}
|
||||
return ODK_ComputeRenewalDuration(timer_limits, clock_values,
|
||||
|
||||
@@ -23,3 +23,12 @@ int crypto_memcmp(const void* in_a, const void* in_b, size_t len) {
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
bool ODK_NonceValuesEqual(const ODK_NonceValues* a, const ODK_NonceValues* b) {
|
||||
if (a == NULL || b == NULL) {
|
||||
return (a == b);
|
||||
}
|
||||
return (a->api_major_version == b->api_major_version &&
|
||||
a->api_minor_version == b->api_minor_version &&
|
||||
a->nonce == b->nonce && a->session_id == b->session_id);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "odk_structs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -18,6 +20,8 @@ extern "C" {
|
||||
* return value when a != b is undefined, other than being non-zero. */
|
||||
int crypto_memcmp(const void* a, const void* b, size_t len);
|
||||
|
||||
bool ODK_NonceValuesEqual(const ODK_NonceValues* a, const ODK_NonceValues* b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
@@ -20,8 +20,12 @@ struct _Message {
|
||||
MessageStatus status;
|
||||
};
|
||||
|
||||
odk_static_assert(SIZE_OF_MESSAGE_STRUCT >= sizeof(Message),
|
||||
"SIZE_OF_MESSAGE_STRUCT too small");
|
||||
/* TODO(b/150776214): this can be removed once AllocateMessage gets cleaned up
|
||||
*/
|
||||
/*
|
||||
* odk_static_assert(SIZE_OF_MESSAGE_STRUCT >= sizeof(struct _Message),
|
||||
* "SIZE_OF_MESSAGE_STRUCT too small");
|
||||
*/
|
||||
|
||||
bool ValidMessage(Message* message) {
|
||||
if (message == NULL) {
|
||||
@@ -235,7 +239,8 @@ size_t GetSize(Message* message) {
|
||||
|
||||
void SetSize(Message* message, size_t size) {
|
||||
if (message == NULL) return;
|
||||
if (size > message->capacity) message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
if (size > message->capacity)
|
||||
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
else
|
||||
message->size = size;
|
||||
}
|
||||
|
||||
@@ -28,10 +28,20 @@ extern "C" {
|
||||
*/
|
||||
#define AllocateMessage(msg, blk) \
|
||||
uint8_t blk[SIZE_OF_MESSAGE_STRUCT]; \
|
||||
*(msg) = (Message*)(blk);
|
||||
*(msg) = (Message*)(blk)
|
||||
|
||||
typedef struct _Message Message;
|
||||
|
||||
typedef enum {
|
||||
MESSAGE_STATUS_OK,
|
||||
MESSAGE_STATUS_UNKNOWN_ERROR,
|
||||
MESSAGE_STATUS_OVERFLOW_ERROR,
|
||||
MESSAGE_STATUS_UNDERFLOW_ERROR,
|
||||
MESSAGE_STATUS_PARSE_ERROR,
|
||||
MESSAGE_STATUS_NULL_POINTER_ERROR,
|
||||
MESSAGE_STATUS_API_VALUE_ERROR
|
||||
} MessageStatus;
|
||||
|
||||
bool ValidMessage(Message* message);
|
||||
|
||||
void Pack_enum(Message* message, int value);
|
||||
@@ -51,16 +61,6 @@ void UnpackArray(Message* message, uint8_t* address,
|
||||
size_t size); /* copy out */
|
||||
void Unpack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring* obj);
|
||||
|
||||
typedef enum {
|
||||
MESSAGE_STATUS_OK,
|
||||
MESSAGE_STATUS_UNKNOWN_ERROR,
|
||||
MESSAGE_STATUS_OVERFLOW_ERROR,
|
||||
MESSAGE_STATUS_UNDERFLOW_ERROR,
|
||||
MESSAGE_STATUS_PARSE_ERROR,
|
||||
MESSAGE_STATUS_NULL_POINTER_ERROR,
|
||||
MESSAGE_STATUS_API_VALUE_ERROR
|
||||
} MessageStatus;
|
||||
|
||||
/*
|
||||
* Create a message from a buffer. The message structure consumes the first
|
||||
* sizeof(Message) bytes of the buffer. The caller is responsible for ensuring
|
||||
|
||||
Reference in New Issue
Block a user