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:
Fred Gylys-Colwell
2020-02-28 12:03:28 -08:00
committed by Jeff Tinker
parent 0947bd185b
commit c5b7a01ab5
17 changed files with 1528 additions and 866 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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. */

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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