[ Merge of http://go/wvgerrit/186825 ] Remove the words ` All rights reserved.` from Widevine's existing copyright headers. For context, see cl/578224540 Bug: 330655176 Test: WVTS PiperOrigin-RevId: 580020267 Change-Id: I43e845b83f438e4ef7f0f542c2f4e427a188ab06
515 lines
21 KiB
C
515 lines
21 KiB
C
// Copyright 2019 Google LLC. This file and proprietary
|
|
// source code may only be used and distributed under the Widevine
|
|
// License Agreement.
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "odk.h"
|
|
#include "odk_attributes.h"
|
|
#include "odk_overflow.h"
|
|
#include "odk_structs_priv.h"
|
|
|
|
/* 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. */
|
|
static OEMCryptoResult ODK_LicenseActive(const ODK_TimerLimits* timer_limits,
|
|
ODK_ClockValues* clock_values) {
|
|
/* Check some basic errors. */
|
|
if (clock_values == NULL || timer_limits == NULL) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
/* Check if the license has not been loaded yet. */
|
|
if (clock_values->timer_status == ODK_CLOCK_TIMER_STATUS_UNDEFINED ||
|
|
clock_values->timer_status == ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED) {
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
}
|
|
if (clock_values->status > kActive) {
|
|
return ODK_TIMER_EXPIRED;
|
|
}
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
/* Private function. Sets the timer_value to be the min(timer_value, new_value),
|
|
* with the convention that 0 means infinite. The convention that 0 means
|
|
* infinite is used for all Widevine license and duration values. */
|
|
static void ComputeMinimum(uint64_t* timer_value, uint64_t new_value) {
|
|
if (timer_value == NULL) return;
|
|
if (new_value > 0) {
|
|
if (*timer_value == 0 || *timer_value > new_value) {
|
|
*timer_value = new_value;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Private function. Check to see if the rental window restricts playback. If
|
|
* the rental enforcement is hard, or if this is the first playback, then we
|
|
* verify that system_time_seconds is within the rental window. If the
|
|
* enforcement is soft and we have already started playback, then there is no
|
|
* restriction.
|
|
* Return ODK_TIMER_EXPIRED if out of the window.
|
|
* Return ODK_TIMER_ACTIVE if within the window, and there is a hard limit.
|
|
* Return ODK_DISABLE_TIMER if no there should be no limit.
|
|
* Return other error on error.
|
|
* Also, if this function does compute a limit, the timer_value is reduced to
|
|
* obey that limit. If the limit is less restrictive than the current
|
|
* timer_value, then timer_value is not changed. */
|
|
static OEMCryptoResult ODK_CheckRentalWindow(
|
|
const ODK_TimerLimits* timer_limits, ODK_ClockValues* clock_values,
|
|
uint64_t system_time_seconds, uint64_t* timer_value) {
|
|
if (clock_values == NULL || timer_limits == NULL || timer_value == NULL) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
/* If playback has already started, and rental duration enforcement is soft,
|
|
* then there is no restriction. */
|
|
if (clock_values->time_of_first_decrypt > 0 &&
|
|
timer_limits->soft_enforce_rental_duration) {
|
|
return ODK_DISABLE_TIMER;
|
|
}
|
|
|
|
/* rental_clock = time since license signed. */
|
|
uint64_t rental_clock = 0;
|
|
if (odk_sub_overflow_u64(system_time_seconds,
|
|
clock_values->time_of_license_request_signed,
|
|
&rental_clock)) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
/* Check if it is before license is valid. This is an unusual case. First
|
|
* playback may still work if it occurs after the rental window opens. */
|
|
if (rental_clock < timer_limits->earliest_playback_start_seconds) {
|
|
return ODK_TIMER_EXPIRED;
|
|
}
|
|
/* If the rental duration is 0, there is no limit. */
|
|
if (timer_limits->rental_duration_seconds == 0) {
|
|
return ODK_DISABLE_TIMER;
|
|
}
|
|
/* End of rental window, based on rental clock (not system time). */
|
|
uint64_t end_of_rental_window = 0;
|
|
if (odk_add_overflow_u64(timer_limits->earliest_playback_start_seconds,
|
|
timer_limits->rental_duration_seconds,
|
|
&end_of_rental_window)) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
if (end_of_rental_window <= rental_clock) {
|
|
return ODK_TIMER_EXPIRED;
|
|
}
|
|
/* At this point system_time is within the rental window. */
|
|
if (timer_limits->soft_enforce_rental_duration) {
|
|
/* For soft enforcement, we allow playback, and do not adjust the timer. */
|
|
return ODK_DISABLE_TIMER;
|
|
}
|
|
uint64_t time_left = 0;
|
|
if (odk_sub_overflow_u64(end_of_rental_window, rental_clock, &time_left)) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
ComputeMinimum(timer_value, time_left);
|
|
return ODK_SET_TIMER;
|
|
}
|
|
|
|
/* Private function. Check to see if the playback window restricts
|
|
* playback. This should only be called if playback has started, so that
|
|
* clock_values->time_of_first_decrypt is nonzero.
|
|
* Return ODK_TIMER_EXPIRED if out of the window.
|
|
* Return ODK_SET_TIMER if within the window, and there is a hard limit.
|
|
* Return ODK_DISABLE_TIMER if no limit.
|
|
* Return other error on error.
|
|
* Also, if this function does compute a limit, the timer_value is reduced to
|
|
* obey that limit. If the limit is less restrictive than the current
|
|
* timer_value, then timer_value is not changed. */
|
|
static OEMCryptoResult ODK_CheckPlaybackWindow(
|
|
const ODK_TimerLimits* timer_limits, ODK_ClockValues* clock_values,
|
|
uint64_t system_time_seconds, uint64_t* timer_value) {
|
|
if (clock_values == NULL || timer_limits == NULL || timer_value == NULL) {
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
}
|
|
/* if the playback duration is 0, there is no limit. */
|
|
if (timer_limits->total_playback_duration_seconds == 0) {
|
|
return ODK_DISABLE_TIMER;
|
|
}
|
|
uint64_t end_of_playback_window = 0;
|
|
if (odk_add_overflow_u64(timer_limits->total_playback_duration_seconds,
|
|
clock_values->time_of_first_decrypt,
|
|
&end_of_playback_window)) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
if (end_of_playback_window <= system_time_seconds) {
|
|
return ODK_TIMER_EXPIRED;
|
|
}
|
|
/* At this point, system_time is within the total playback window. */
|
|
if (timer_limits->soft_enforce_playback_duration) {
|
|
/* For soft enforcement, we allow playback, and do not adjust the timer. */
|
|
return ODK_DISABLE_TIMER;
|
|
}
|
|
uint64_t time_left = 0;
|
|
if (odk_sub_overflow_u64(end_of_playback_window, system_time_seconds,
|
|
&time_left)) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
ComputeMinimum(timer_value, time_left);
|
|
return ODK_SET_TIMER;
|
|
}
|
|
|
|
/* Update the timer status. If playback has already started, we use the given
|
|
* status. However, if playback has not yet started, then we expect a call to
|
|
* ODK_AttemptFirstPlayback in the future, and we need to signal to it that we
|
|
* 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->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;
|
|
} else {
|
|
clock_values->timer_status = new_status;
|
|
}
|
|
}
|
|
|
|
/* Private function, but accessed from odk.c so cannot be static. This checks to
|
|
* see if a renewal message should restart the playback timer and sets the value
|
|
* appropriately. */
|
|
OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
|
ODK_ClockValues* clock_values,
|
|
uint64_t system_time_seconds,
|
|
uint64_t new_renewal_duration,
|
|
uint64_t* timer_value) {
|
|
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_request_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;
|
|
}
|
|
|
|
/* We start with the new renewal duration as the new timer limit. */
|
|
uint64_t new_timer_value = new_renewal_duration;
|
|
|
|
/* Then we factor in the rental window restrictions. This might decrease
|
|
* 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)) {
|
|
return rental_status;
|
|
}
|
|
|
|
/* If playback has already started and it has hard enforcement, then check
|
|
* total playback window. */
|
|
if (clock_values->time_of_first_decrypt > 0 &&
|
|
!timer_limits->soft_enforce_playback_duration) {
|
|
/* This might decrease new_timer_value. */
|
|
const OEMCryptoResult playback_status = ODK_CheckPlaybackWindow(
|
|
timer_limits, clock_values, system_time_seconds, &new_timer_value);
|
|
/* 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)) {
|
|
return playback_status;
|
|
}
|
|
}
|
|
|
|
/* If new_timer_value is infinite (represented by 0), then there are no
|
|
* limits, so we can return now. */
|
|
if (new_timer_value == 0) {
|
|
clock_values->time_when_timer_expires = 0;
|
|
ODK_UpdateTimerStatusForRenewal(clock_values,
|
|
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;
|
|
}
|
|
if (odk_add_overflow_u64(system_time_seconds, new_timer_value,
|
|
&clock_values->time_when_timer_expires)) {
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
}
|
|
ODK_UpdateTimerStatusForRenewal(clock_values, ODK_CLOCK_TIMER_STATUS_ACTIVE);
|
|
return ODK_SET_TIMER;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* Public functions, declared in odk.h. */
|
|
|
|
/* This is called when OEMCrypto opens a new session. */
|
|
OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
|
|
ODK_ClockValues* clock_values,
|
|
ODK_NonceValues* nonce_values,
|
|
uint32_t api_major_version,
|
|
uint32_t session_id) {
|
|
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
timer_limits->soft_enforce_rental_duration = false;
|
|
timer_limits->soft_enforce_playback_duration = false;
|
|
timer_limits->earliest_playback_start_seconds = 0;
|
|
timer_limits->rental_duration_seconds = 0;
|
|
timer_limits->total_playback_duration_seconds = 0;
|
|
timer_limits->initial_renewal_duration_seconds = 0;
|
|
|
|
ODK_InitializeClockValues(clock_values, 0);
|
|
|
|
nonce_values->api_major_version = api_major_version;
|
|
// This needs to be updated with new version releases in the default features
|
|
// of core message features.
|
|
switch (nonce_values->api_major_version) {
|
|
case 16:
|
|
nonce_values->api_minor_version = 5;
|
|
break;
|
|
case 17:
|
|
nonce_values->api_minor_version = 2;
|
|
break;
|
|
case 18:
|
|
nonce_values->api_minor_version = 4;
|
|
break;
|
|
default:
|
|
nonce_values->api_minor_version = 0;
|
|
break;
|
|
}
|
|
nonce_values->nonce = 0;
|
|
nonce_values->session_id = session_id;
|
|
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
/* This is called when OEMCrypto generates a new nonce in
|
|
* OEMCrypto_GenerateNonce. */
|
|
OEMCryptoResult ODK_SetNonceValues(ODK_NonceValues* nonce_values,
|
|
uint32_t nonce) {
|
|
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;
|
|
}
|
|
nonce_values->nonce = nonce;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
clock_values->time_of_license_request_signed = system_time_seconds;
|
|
clock_values->time_of_first_decrypt = 0;
|
|
clock_values->time_of_last_decrypt = 0;
|
|
clock_values->time_of_renewal_request = 0;
|
|
clock_values->time_when_timer_expires = 0;
|
|
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED;
|
|
clock_values->status = kUnused;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
/* This is called when OEMCrypto reloads a usage entry. */
|
|
OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
|
|
uint64_t time_of_license_request_signed,
|
|
uint64_t time_of_first_decrypt,
|
|
uint64_t time_of_last_decrypt,
|
|
enum OEMCrypto_Usage_Entry_Status status,
|
|
uint64_t system_time_seconds UNUSED) {
|
|
if (clock_values == NULL) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
clock_values->time_of_license_request_signed = time_of_license_request_signed;
|
|
clock_values->time_of_first_decrypt = time_of_first_decrypt;
|
|
clock_values->time_of_last_decrypt = time_of_last_decrypt;
|
|
clock_values->time_when_timer_expires = 0;
|
|
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED;
|
|
clock_values->status = status;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
/* This is called on the first playback for a session. */
|
|
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) {
|
|
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,
|
|
clock_values->time_of_license_request_signed,
|
|
&rental_time)) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
if (rental_time < timer_limits->earliest_playback_start_seconds) {
|
|
clock_values->timer_status = ODK_TIMER_EXPIRED;
|
|
return ODK_TIMER_EXPIRED;
|
|
}
|
|
/* 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;
|
|
}
|
|
|
|
/* We start with the initial renewal duration as the timer limit. */
|
|
uint64_t new_timer_value = timer_limits->initial_renewal_duration_seconds;
|
|
/* However, if a renewal was loaded before this first playback, use the
|
|
* previously computed limit. */
|
|
if (clock_values->timer_status == ODK_CLOCK_TIMER_STATUS_RENEWAL_LOADED) {
|
|
if (clock_values->time_when_timer_expires <= system_time_seconds) {
|
|
return ODK_TIMER_EXPIRED;
|
|
}
|
|
if (odk_sub_overflow_u64(clock_values->time_when_timer_expires,
|
|
system_time_seconds, &new_timer_value)) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
}
|
|
|
|
/* Then we factor in the rental window restrictions. This might decrease
|
|
* 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 playback has not already started, then this is the first playback. */
|
|
if (clock_values->time_of_first_decrypt == 0) {
|
|
clock_values->time_of_first_decrypt = system_time_seconds;
|
|
clock_values->status = kActive;
|
|
}
|
|
|
|
/* Similar to the rental window, we check the playback window
|
|
* 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;
|
|
}
|
|
|
|
/* We know we are allowed to decrypt. The rest computes the timer duration. */
|
|
clock_values->time_of_last_decrypt = system_time_seconds;
|
|
|
|
/* If new_timer_value is infinite (represented by 0), then there are no
|
|
* limits, so we can return now. */
|
|
if (new_timer_value == 0) {
|
|
clock_values->time_when_timer_expires = 0;
|
|
clock_values->timer_status = 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) {
|
|
*timer_value = new_timer_value;
|
|
}
|
|
if (odk_add_overflow_u64(system_time_seconds, new_timer_value,
|
|
&clock_values->time_when_timer_expires)) {
|
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
}
|
|
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_ACTIVE;
|
|
return ODK_SET_TIMER;
|
|
}
|
|
|
|
/* This is called regularly during playback if OEMCrypto does not implement its
|
|
* own timer. */
|
|
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;
|
|
}
|
|
switch (clock_values->timer_status) {
|
|
case ODK_CLOCK_TIMER_STATUS_UNLIMITED:
|
|
break;
|
|
case ODK_CLOCK_TIMER_STATUS_ACTIVE:
|
|
/* Note: we allow playback at the time when the timer expires, but not
|
|
* after. This is not important for business cases, but it makes it
|
|
* easier to write tests. */
|
|
if (clock_values->time_when_timer_expires > 0 &&
|
|
system_time_seconds > clock_values->time_when_timer_expires) {
|
|
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_EXPIRED;
|
|
return ODK_TIMER_EXPIRED;
|
|
}
|
|
break;
|
|
default: /* Expired, error state, or never started. */
|
|
return ODK_TIMER_EXPIRED;
|
|
}
|
|
clock_values->time_of_last_decrypt = system_time_seconds;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
/* 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->status == kUnused) {
|
|
clock_values->status = kInactiveUnused;
|
|
} else if (clock_values->status == kActive) {
|
|
clock_values->status = kInactiveUsed;
|
|
}
|
|
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
/* This is called when OEMCrypto loads a legacy v15 license, from
|
|
* OEMCrypto_LoadKeys. */
|
|
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 (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;
|
|
timer_limits->rental_duration_seconds = 0;
|
|
timer_limits->total_playback_duration_seconds = 0;
|
|
timer_limits->initial_renewal_duration_seconds = key_duration;
|
|
|
|
nonce_values->api_major_version = 15;
|
|
nonce_values->api_minor_version = 0;
|
|
if (key_duration > 0) {
|
|
clock_values->time_when_timer_expires = system_time_seconds + key_duration;
|
|
} else {
|
|
clock_values->time_when_timer_expires = 0;
|
|
}
|
|
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED;
|
|
return OEMCrypto_SUCCESS;
|
|
}
|
|
|
|
/* This is called when OEMCrypto loads a legacy license renewal in
|
|
* OEMCrypto_RefreshKeys. */
|
|
OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
|
|
ODK_ClockValues* clock_values,
|
|
const ODK_NonceValues* nonce_values,
|
|
uint64_t system_time_seconds,
|
|
uint32_t new_key_duration,
|
|
uint64_t* timer_value) {
|
|
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL) {
|
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
}
|
|
if (nonce_values->api_major_version != 15) {
|
|
return OEMCrypto_ERROR_INVALID_NONCE;
|
|
}
|
|
if (clock_values->status > kActive) {
|
|
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE;
|
|
return ODK_TIMER_EXPIRED;
|
|
}
|
|
return ODK_ComputeRenewalDuration(timer_limits, clock_values,
|
|
system_time_seconds, new_key_duration,
|
|
timer_value);
|
|
}
|