OEMCrypto v16.1

Merge of http://go/wvgerrit/93404

This CL updates the Widevine CDM to support OEMCrypto v16.1

Test: Tested in 16.2 CL
Bug: 141247171
Change-Id: I69bd993500f6fb63bf6010c8b0250dc7acc3d71b
This commit is contained in:
Fred Gylys-Colwell
2020-01-18 10:11:24 -08:00
parent 7e2619e379
commit 7665614b2e
132 changed files with 12331 additions and 9341 deletions

View File

@@ -0,0 +1,112 @@
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#include "core_message_deserialize.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include "odk_serialize.h"
#include "odk_structs.h"
#include "odk_structs_priv.h"
#include "serialization_base.h"
namespace oemcrypto_core_message {
namespace deserialize {
namespace {
const int EARLIEST_OEMCRYPTO_VERSION_WITH_ODK = 16;
const int LATEST_OEMCRYPTO_VERSION = 16;
/**
* Template for parsing requests
*
* Template arguments:
* S: kdo output struct
* T: struct serialized by odk
* U: auto-generated deserializing function for |T|
*/
template <typename S, typename T, typename U>
bool ParseRequest(uint32_t message_type,
const std::string& oemcrypto_core_message, S* core_request,
T* prepared, const U unpacker) {
if (core_request == nullptr || prepared == nullptr) {
return false;
}
const uint8_t* buf =
reinterpret_cast<const uint8_t*>(oemcrypto_core_message.c_str());
const size_t buf_length = oemcrypto_core_message.size();
Message* msg = nullptr;
AllocateMessage(&msg, message_block);
InitMessage(msg, const_cast<uint8_t*>(buf), buf_length);
SetSize(msg, buf_length);
unpacker(msg, prepared);
if (!ValidMessage(msg)) {
return false;
}
const auto& core_message = prepared->core_message;
core_request->api_version = core_message.nonce_values.api_version;
core_request->nonce = core_message.nonce_values.nonce;
core_request->session_id = core_message.nonce_values.session_id;
return core_message.message_type == message_type &&
core_message.message_length == GetOffset(msg) &&
core_request->api_version >= EARLIEST_OEMCRYPTO_VERSION_WITH_ODK &&
core_request->api_version <= LATEST_OEMCRYPTO_VERSION;
}
} // namespace
bool CoreLicenseRequestFromMessage(const std::string& oemcrypto_core_message,
ODK_LicenseRequest* core_license_request) {
const auto unpacker = Unpack_ODK_PreparedLicense;
ODK_PreparedLicense prepared_license = {};
return ParseRequest(ODK_License_Request_Type, oemcrypto_core_message,
core_license_request, &prepared_license, unpacker);
}
bool CoreRenewalRequestFromMessage(const std::string& oemcrypto_core_message,
ODK_RenewalRequest* core_renewal_request) {
const auto unpacker = Unpack_ODK_RenewalMessage;
ODK_RenewalMessage prepared_renewal = {};
if (!ParseRequest(ODK_Renewal_Request_Type, oemcrypto_core_message,
core_renewal_request, &prepared_renewal, unpacker)) {
return false;
}
core_renewal_request->playback_time_seconds = prepared_renewal.playback_time;
return true;
}
bool CoreProvisioningRequestFromMessage(
const std::string& oemcrypto_core_message,
ODK_ProvisioningRequest* core_provisioning_request) {
const auto unpacker = Unpack_ODK_ProvisioningMessage;
ODK_ProvisioningMessage prepared_provision = {};
if (!ParseRequest(ODK_Provisioning_Request_Type, oemcrypto_core_message,
core_provisioning_request, &prepared_provision, unpacker)) {
return false;
}
const uint8_t* device_id = prepared_provision.device_id;
const uint32_t device_id_length = prepared_provision.device_id_length;
if (device_id_length > ODK_DEVICE_ID_LEN_MAX) {
return false;
}
uint8_t zero[ODK_DEVICE_ID_LEN_MAX] = {};
if (memcmp(zero, device_id + device_id_length,
ODK_DEVICE_ID_LEN_MAX - device_id_length)) {
return false;
}
core_provisioning_request->device_id.assign(
reinterpret_cast<const char*>(device_id), device_id_length);
return true;
}
} // namespace deserialize
} // namespace oemcrypto_core_message

View File

@@ -0,0 +1,114 @@
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#include "core_message_serialize.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>
#include "odk_serialize.h"
#include "odk_structs.h"
#include "odk_structs_priv.h"
#include "serialization_base.h"
namespace oemcrypto_core_message {
namespace serialize {
namespace {
/**
* Template for parsing requests
*
* Template arguments:
* T: struct to be deserialized by odk
* S: kdo input struct
* P: auto-generated serializing function for |T|
*/
template <typename T, typename S, typename P>
bool CreateResponse(uint32_t message_type, const S& core_request,
std::string* oemcrypto_core_message, T& response,
const P& packer) {
if (!oemcrypto_core_message) {
return false;
}
auto* header = reinterpret_cast<ODK_CoreMessage*>(&response);
header->message_type = message_type;
header->nonce_values.api_version = core_request.api_version;
header->nonce_values.nonce = core_request.nonce;
header->nonce_values.session_id = core_request.session_id;
const size_t BUF_CAPACITY = 2048;
std::vector<uint8_t> buf(BUF_CAPACITY, 0);
Message* msg = nullptr;
AllocateMessage(&msg, message_block);
InitMessage(msg, buf.data(), buf.capacity());
packer(msg, &response);
if (!ValidMessage(msg)) {
return false;
}
uint32_t message_length = GetSize(msg);
InitMessage(msg, buf.data() + sizeof(header->message_type),
sizeof(header->message_length));
Pack_uint32_t(msg, &message_length);
oemcrypto_core_message->assign(reinterpret_cast<const char*>(buf.data()),
message_length);
return true;
}
bool CopyDeviceId(const ODK_ProvisioningRequest& src,
ODK_ProvisioningResponse* dest) {
auto& core_provisioning = dest->core_provisioning;
const std::string& device_id = src.device_id;
core_provisioning.device_id_length = device_id.size();
if (core_provisioning.device_id_length >
sizeof(core_provisioning.device_id)) {
return false;
}
memset(core_provisioning.device_id, 0, sizeof(core_provisioning.device_id));
memcpy(core_provisioning.device_id, device_id.data(),
core_provisioning.device_id_length);
return true;
}
} // namespace
bool CreateCoreLicenseResponse(const ODK_ParsedLicense& parsed_lic,
const ODK_LicenseRequest& core_request,
std::string* oemcrypto_core_message) {
ODK_LicenseResponse license_response{
{}, const_cast<ODK_ParsedLicense*>(&parsed_lic)};
return CreateResponse(ODK_License_Response_Type, core_request,
oemcrypto_core_message, license_response,
Pack_ODK_LicenseResponse);
}
bool CreateCoreRenewalResponse(const ODK_RenewalRequest& core_request,
std::string* oemcrypto_core_message) {
ODK_RenewalMessage renewal{{}, core_request.playback_time_seconds};
renewal.playback_time = core_request.playback_time_seconds;
return CreateResponse(ODK_Renewal_Response_Type, core_request,
oemcrypto_core_message, renewal,
Pack_ODK_RenewalMessage);
}
bool CreateCoreProvisioningResponse(const ODK_ParsedProvisioning& parsed_prov,
const ODK_ProvisioningRequest& core_request,
std::string* oemcrypto_core_message) {
ODK_ProvisioningResponse prov_response{
{}, const_cast<ODK_ParsedProvisioning*>(&parsed_prov)};
if (!CopyDeviceId(core_request, &prov_response)) {
return false;
}
return CreateResponse(ODK_Provisioning_Response_Type, core_request,
oemcrypto_core_message, prov_response,
Pack_ODK_ProvisioningResponse);
}
} // namespace serialize
} // namespace oemcrypto_core_message

View File

@@ -0,0 +1,167 @@
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#include "core_message_serialize_proto.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include "core_message_serialize.h"
#include "license_protocol.pb.h"
#include "odk_serialize.h"
#include "odk_structs.h"
#include "odk_structs_priv.h"
#include "serialization_base.h"
namespace oemcrypto_core_message {
namespace serialize {
namespace {
/* @ private functions */
/**
* Extract OEMCrypto_Substring (offset, length) from serialized protobuf
*
* Parameters:
* message: serialized license protobuf
* field: substring value
*/
OEMCrypto_Substring GetOecSubstring(const std::string& message,
const std::string& field) {
OEMCrypto_Substring substring = {};
size_t pos = message.find(field);
if (pos != std::string::npos) {
substring = OEMCrypto_Substring{pos, field.length()};
}
return substring;
}
OEMCrypto_KeyObject KeyContainerToOecKey(
const std::string& proto, const video_widevine::License::KeyContainer& k) {
OEMCrypto_KeyObject obj = {};
obj.key_id = GetOecSubstring(proto, k.id());
obj.key_data_iv = GetOecSubstring(proto, k.iv());
// Strip off PKCS#5 padding - since we know the key is 16 or 32 bytes,
// the padding will always be 16 bytes.
const std::string& key_data = k.key();
const size_t PKCS5_PADDING_SIZE = 16;
obj.key_data = GetOecSubstring(
proto, key_data.substr(0, std::max(PKCS5_PADDING_SIZE, key_data.size()) -
PKCS5_PADDING_SIZE));
if (k.has_key_control()) {
const auto& key_control = k.key_control();
obj.key_control_iv = GetOecSubstring(proto, key_control.iv());
obj.key_control = GetOecSubstring(proto, key_control.key_control_block());
}
return obj;
}
} // namespace
// @ public create response functions
bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
const ODK_LicenseRequest& core_request,
const std::string& core_request_sha256,
std::string* oemcrypto_core_message) {
video_widevine::License lic;
if (!lic.ParseFromString(serialized_license)) {
return false;
}
ODK_ParsedLicense parsed_lic{};
if (core_request_sha256.size() != ODK_SHA256_HASH_SIZE) {
return false;
}
std::memcpy(parsed_lic.request_hash, core_request_sha256.data(),
ODK_SHA256_HASH_SIZE);
for (int i = 0; i < lic.key_size(); ++i) {
const auto& k = lic.key(i);
switch (k.type()) {
case video_widevine::License_KeyContainer::SIGNING: {
parsed_lic.enc_mac_keys_iv =
GetOecSubstring(serialized_license, k.iv());
// Strip off PKCS#5 padding
const size_t MAC_KEY_SIZE = 32;
std::string mac_keys(k.key(), 2 * MAC_KEY_SIZE);
parsed_lic.enc_mac_keys = GetOecSubstring(serialized_license, mac_keys);
break;
}
case video_widevine::License_KeyContainer::CONTENT: {
if (parsed_lic.key_array_length >= ODK_MAX_NUM_KEYS) {
return false;
}
uint32_t& n = parsed_lic.key_array_length;
parsed_lic.key_array[n++] = KeyContainerToOecKey(serialized_license, k);
break;
}
default: {
continue;
}
}
}
const auto& lid = lic.id();
if (lid.has_provider_session_token()) {
parsed_lic.pst =
GetOecSubstring(serialized_license, lid.provider_session_token());
}
if (lic.has_srm_requirement()) {
parsed_lic.srm_restriction_data =
GetOecSubstring(serialized_license, lic.srm_requirement());
}
parsed_lic.license_type = lid.type();
// todo(robertshih): nonce_required
const auto& policy = lic.policy();
ODK_TimerLimits& timer_limits = parsed_lic.timer_limits;
timer_limits.soft_expiry = policy.soft_enforce_playback_duration();
timer_limits.earliest_playback_start_seconds = 0;
timer_limits.latest_playback_start_seconds =
policy.license_duration_seconds();
timer_limits.initial_playback_duration_seconds =
policy.playback_duration_seconds();
timer_limits.renewal_playback_duration_seconds =
policy.playback_duration_seconds();
timer_limits.license_duration_seconds = policy.license_duration_seconds();
return CreateCoreLicenseResponse(parsed_lic, core_request,
oemcrypto_core_message);
}
bool CreateCoreProvisioningResponseFromProto(
const std::string& serialized_provisioning_resp,
const ODK_ProvisioningRequest& core_request,
std::string* oemcrypto_core_message) {
ODK_ParsedProvisioning parsed_prov{};
video_widevine::ProvisioningResponse prov;
if (!prov.ParseFromString(serialized_provisioning_resp)) {
return false;
}
parsed_prov.key_type = 0; // todo(robertshih): ECC or RSA
if (prov.has_device_rsa_key()) {
parsed_prov.enc_private_key =
GetOecSubstring(serialized_provisioning_resp, prov.device_rsa_key());
}
if (prov.has_device_rsa_key_iv()) {
parsed_prov.enc_private_key_iv =
GetOecSubstring(serialized_provisioning_resp, prov.device_rsa_key_iv());
}
if (prov.has_wrapping_key()) {
parsed_prov.encrypted_message_key =
GetOecSubstring(serialized_provisioning_resp, prov.wrapping_key());
}
return CreateCoreProvisioningResponse(parsed_prov, core_request,
oemcrypto_core_message);
}
} // namespace serialize
} // namespace oemcrypto_core_message

View File

@@ -1,14 +1,13 @@
/*
* Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
#include "odk.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "odk.h"
#include "odk_overflow.h"
#include "odk_serialize.h"
#include "odk_structs.h"
@@ -18,6 +17,7 @@
#define ODK_LICENSE_REQUEST_SIZE 20
#define ODK_RENEWAL_REQUEST_SIZE 28
#define ODK_PROVISIONING_REQUEST_SIZE 88
#define OEC_API_VERSION 16
/* @ private odk functions */
@@ -35,7 +35,9 @@ static OEMCryptoResult ODK_PrepareRequest(uint8_t* buffer, size_t buffer_length,
AllocateMessage(&msg, message_block);
InitMessage(msg, buffer, *core_message_length);
*core_message = (ODK_CoreMessage){
message_type, 0, *nonce_values,
message_type,
0,
*nonce_values,
};
switch (message_type) {
@@ -69,13 +71,21 @@ static OEMCryptoResult ODK_PrepareRequest(uint8_t* buffer, size_t buffer_length,
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) {
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);
SetSize(msg, 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);
switch (message_type) {
case ODK_License_Response_Type: {
@@ -121,33 +131,44 @@ 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) {
ODK_PreparedLicense license_request = {0};
ODK_PreparedLicense license_request = {
{0},
};
return ODK_PrepareRequest(message, message_length, core_message_length,
ODK_License_Request_Type, nonce_values,
&license_request.core_message);
}
OEMCryptoResult ODK_PrepareCoreRenewalRequest(
uint8_t* message, size_t message_length, size_t* core_message_length,
const ODK_NonceValues* nonce_values,
const ODK_ClockValues* clock_values, uint64_t system_time_seconds) {
uint8_t* message, size_t message_length, size_t* core_message_size,
const ODK_NonceValues* nonce_values, ODK_ClockValues* clock_values,
uint64_t system_time_seconds) {
ODK_RenewalMessage renewal_request = {
{0},
};
if (odk_sub_overflow_u64(system_time_seconds,
clock_values->time_of_first_decrypt,
&renewal_request.playback_time)) {
return ODK_ERROR_CORE_MESSAGE;
if (clock_values->time_of_first_decrypt == 0) {
/* It is OK to preemptively request a renewal before playback starts.
* We'll treat this as asking for a renewal at playback time 0. */
renewal_request.playback_time = 0;
} else {
/* Otherwise, playback_time is relative to the first decrypt. */
if (odk_sub_overflow_u64(system_time_seconds,
clock_values->time_of_first_decrypt,
&renewal_request.playback_time)) {
return ODK_ERROR_CORE_MESSAGE;
}
}
return ODK_PrepareRequest(message, message_length, core_message_length,
/* Save time for this request so that we can verify the response. */
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);
}
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) {
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
size_t device_id_length) {
ODK_ProvisioningMessage provisioning_request = {
{0},
};
@@ -165,54 +186,60 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
/* @@ parse request functions */
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 (!nonce_values || !parsed_license) {
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 || !request_hash || !timer_limits || !clock_values ||
!nonce_values || !parsed_license) {
return ODK_ERROR_CORE_MESSAGE;
}
ODK_LicenseResponse license_response = {{0}, parsed_license};
OEMCryptoResult err = ODK_ParseResponse(
message, message_length, ODK_License_Response_Type, NULL,
&license_response.core_message);
message, message_length, core_message_length, ODK_License_Response_Type,
NULL, &license_response.core_message);
if (err != OEMCrypto_SUCCESS) {
return err;
}
if (license_response.core_message.nonce_values.api_version != 16) {
/* This function should not be used for legacy licenses. */
if (license_response.core_message.nonce_values.api_version !=
OEC_API_VERSION) {
return ODK_UNSUPPORTED_API;
}
if (parsed_license->nonce_required) {
if (initial_license_load) {
if (nonce_values->nonce != license_response.core_message.nonce_values.nonce ||
nonce_values->session_id != license_response.core_message.nonce_values.session_id) {
if (nonce_values->nonce !=
license_response.core_message.nonce_values.nonce ||
nonce_values->session_id !=
license_response.core_message.nonce_values.session_id) {
return OEMCrypto_ERROR_INVALID_NONCE;
}
} else { /* !initial_license_load */
nonce_values->nonce = license_response.core_message.nonce_values.nonce;
nonce_values->session_id = license_response.core_message.nonce_values.session_id;
nonce_values->session_id =
license_response.core_message.nonce_values.session_id;
}
}
if (initial_license_load &&
memcmp(request_hash, parsed_license->request_hash, ODK_SHA256_HASH_SIZE)) {
/* 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 && memcmp(request_hash, parsed_license->request_hash,
ODK_SHA256_HASH_SIZE)) {
return ODK_ERROR_CORE_MESSAGE;
}
/* If the license has a provider session token (pst), then OEMCrypto should
* have a usage entry loaded. */
if (usage_entry_present && parsed_license->pst.length == 0) {
return ODK_ERROR_CORE_MESSAGE;
}
*timer_limits = parsed_license->timer_limits;
return err;
}
@@ -223,7 +250,7 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
const ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
uint64_t* timer_value) {
if (!nonce_values || !timer_limits || !clock_values || !timer_value) {
if (!message || !nonce_values || !timer_limits || !clock_values) {
return ODK_ERROR_CORE_MESSAGE;
}
@@ -231,8 +258,8 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
{0},
};
OEMCryptoResult err = ODK_ParseResponse(
message, message_length, ODK_Renewal_Response_Type, nonce_values,
&renewal_response.core_message);
message, message_length, core_message_length, ODK_Renewal_Response_Type,
nonce_values, &renewal_response.core_message);
if (err) {
return err;
@@ -243,42 +270,37 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
* Section: Renewal Message
*/
uint64_t playback_timer = 0;
if (odk_sub_overflow_u64(clock_values->time_when_timer_expires, system_time,
&playback_timer)) {
return ODK_TIMER_EXPIRED;
/* If a renewal request is lost in transit, we should throw it out and create
* a new one. We use the timestamp to make sure we have the latest request.
*/
if (clock_values->time_of_renewal_request < renewal_response.playback_time) {
return ODK_STALE_RENEWAL;
}
uint64_t time_since_playback_began = 0;
uint64_t time_since_reset = 0;
uint64_t time_since_message_signed = 0;
/* ... or use clock_values->time_of_license_signed ? */
if (odk_sub_overflow_u64(system_time, clock_values->time_of_first_decrypt,
&time_since_playback_began) ||
odk_sub_overflow_u64(timer_limits->renewal_playback_duration_seconds,
playback_timer, &time_since_reset) ||
odk_sub_overflow_u64(time_since_playback_began,
renewal_response.playback_time,
&time_since_message_signed) ||
time_since_message_signed >= time_since_reset ||
odk_add_overflow_u64(system_time,
/* The timer value should be set to the renewal duration. */
if (timer_value) {
*timer_value = timer_limits->renewal_playback_duration_seconds;
}
if (timer_limits->renewal_playback_duration_seconds == 0) {
clock_values->time_when_timer_expires = 0;
clock_values->timer_status = ODK_DISABLE_TIMER;
return ODK_DISABLE_TIMER;
}
if (odk_add_overflow_u64(system_time,
timer_limits->renewal_playback_duration_seconds,
&clock_values->time_when_timer_expires)) {
return ODK_ERROR_CORE_MESSAGE;
}
/* todo: when to return ODK_DISABLE_TIMER */
*timer_value = timer_limits->renewal_playback_duration_seconds;
clock_values->timer_status = ODK_SET_TIMER;
return ODK_SET_TIMER;
}
OEMCryptoResult ODK_ParseProvisioning(
const uint8_t* message, size_t message_length,
size_t core_message_length,
const ODK_NonceValues* nonce_values,
const uint8_t* device_id,
const 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, ODK_ParsedProvisioning* parsed_response) {
if (!nonce_values || !device_id || !parsed_response) {
if (!message || !nonce_values || !device_id || !parsed_response) {
return ODK_ERROR_CORE_MESSAGE;
}
@@ -290,9 +312,10 @@ OEMCryptoResult ODK_ParseProvisioning(
return ODK_ERROR_CORE_MESSAGE;
}
OEMCryptoResult err = ODK_ParseResponse(
message, message_length, ODK_Provisioning_Response_Type,
nonce_values, &provisioning_response.core_provisioning.core_message);
const OEMCryptoResult err =
ODK_ParseResponse(message, message_length, core_message_length,
ODK_Provisioning_Response_Type, nonce_values,
&provisioning_response.core_provisioning.core_message);
if (err) {
return err;

View File

@@ -0,0 +1,24 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
#ifndef WIDEVINE_ODK_SRC_ODK_ASSERT_H_
#define WIDEVINE_ODK_SRC_ODK_ASSERT_H_
#ifdef __cplusplus
extern "C" {
#endif
#if (__STDC_VERSION__ >= 201112L)
# include <assert.h>
# define odk_static_assert static_assert
#else
# define odk_static_assert(msg, e) \
enum { odk_static_assert = 1 / (!!((msg) && (e))) };
#endif
#ifdef __cplusplus
}
#endif
#endif /* WIDEVINE_ODK_SRC_ODK_ASSERT_H_ */

View File

@@ -0,0 +1,29 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
#ifndef WIDEVINE_ODK_SRC_ODK_ENDIAN_H_
#define WIDEVINE_ODK_SRC_ODK_ENDIAN_H_
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__linux__) || defined(__ANDROID__)
# include <endian.h>
# define oemcrypto_htobe32 htobe32
# define oemcrypto_be32toh be32toh
# define oemcrypto_htobe64 htobe64
# define oemcrypto_be64toh be64toh
#else /* defined(__linux__) || defined(__ANDROID__) */
uint32_t oemcrypto_htobe32(uint32_t u32);
uint32_t oemcrypto_be32toh(uint32_t u32);
uint64_t oemcrypto_htobe64(uint64_t u64);
uint64_t oemcrypto_be64toh(uint64_t u64);
#endif /* defined(__linux__) || defined(__ANDROID__) */
#ifdef __cplusplus
}
#endif
#endif /* WIDEVINE_ODK_SRC_ODK_ENDIAN_H_ */

View File

@@ -1,8 +1,6 @@
/*
* Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
#include <stddef.h>
#include <stdint.h>

View File

@@ -0,0 +1,31 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
#ifndef WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_
#define WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif
#if (defined(__GNUC__) && __GNUC__ >= 5) || \
__has_builtin(__builtin_add_overflow)
# define odk_sub_overflow_u64 __builtin_sub_overflow
# define odk_add_overflow_u64 __builtin_add_overflow
# define odk_add_overflow_ux __builtin_add_overflow
#else
int odk_sub_overflow_u64(uint64_t a, uint64_t b, uint64_t* c);
int odk_add_overflow_u64(uint64_t a, uint64_t b, uint64_t* c);
int odk_add_overflow_ux(size_t a, size_t b, size_t* c);
#endif
#ifdef __cplusplus
}
#endif
#endif /* WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_ */

View File

@@ -1,8 +1,6 @@
/*
* Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
/*
* This code is auto-generated, do not edit
@@ -29,21 +27,20 @@ static void Pack_ODK_CoreMessage(Message* msg, ODK_CoreMessage const* obj) {
static void Pack_OEMCrypto_KeyObject(Message* msg,
OEMCrypto_KeyObject const* obj) {
Pack_OEMCrypto_Substring(msg, (const OEMCrypto_Substring*)&obj->key_id);
Pack_OEMCrypto_Substring(msg, (const OEMCrypto_Substring*)&obj->key_data_iv);
Pack_OEMCrypto_Substring(msg, (const OEMCrypto_Substring*)&obj->key_data);
Pack_OEMCrypto_Substring(msg,
(const OEMCrypto_Substring*)&obj->key_control_iv);
Pack_OEMCrypto_Substring(msg, (const OEMCrypto_Substring*)&obj->key_control);
Pack_OEMCrypto_Substring(msg, &obj->key_id);
Pack_OEMCrypto_Substring(msg, &obj->key_data_iv);
Pack_OEMCrypto_Substring(msg, &obj->key_data);
Pack_OEMCrypto_Substring(msg, &obj->key_control_iv);
Pack_OEMCrypto_Substring(msg, &obj->key_control);
}
static void Pack_ODK_TimerLimits(Message* msg, ODK_TimerLimits const* obj) {
Pack_uint32_t(msg, (const uint32_t*)&obj->soft_expiry);
Pack_uint64_t(msg, (const uint64_t*)&obj->earliest_playback_start_seconds);
Pack_uint64_t(msg, (const uint64_t*)&obj->latest_playback_start_seconds);
Pack_uint64_t(msg, (const uint64_t*)&obj->initial_playback_duration_seconds);
Pack_uint64_t(msg, (const uint64_t*)&obj->renewal_playback_duration_seconds);
Pack_uint64_t(msg, (const uint64_t*)&obj->license_duration_seconds);
Pack_uint32_t(msg, &obj->soft_expiry);
Pack_uint64_t(msg, &obj->earliest_playback_start_seconds);
Pack_uint64_t(msg, &obj->latest_playback_start_seconds);
Pack_uint64_t(msg, &obj->initial_playback_duration_seconds);
Pack_uint64_t(msg, &obj->renewal_playback_duration_seconds);
Pack_uint64_t(msg, &obj->license_duration_seconds);
}
static void Pack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense const* obj) {
@@ -52,62 +49,57 @@ static void Pack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense const* obj) {
SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
return;
}
Pack_OEMCrypto_Substring(msg,
(const OEMCrypto_Substring*)&obj->enc_mac_keys_iv);
Pack_OEMCrypto_Substring(msg, (const OEMCrypto_Substring*)&obj->enc_mac_keys);
Pack_OEMCrypto_Substring(msg, (const OEMCrypto_Substring*)&obj->pst);
Pack_OEMCrypto_Substring(
msg, (const OEMCrypto_Substring*)&obj->srm_restriction_data);
Pack_uint32_t(msg, (const uint32_t*)&obj->license_type);
Pack_uint32_t(msg, (const uint32_t*)&obj->nonce_required);
Pack_ODK_TimerLimits(msg, (const ODK_TimerLimits*)&obj->timer_limits);
PackArray(msg, (const uint8_t*)&obj->request_hash[0], sizeof(obj->request_hash));
Pack_uint32_t(msg, (const uint32_t*)&obj->key_array_length);
for (size_t i = 0; i < (size_t)obj->key_array_length; i++) {
Pack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv);
Pack_OEMCrypto_Substring(msg, &obj->enc_mac_keys);
Pack_OEMCrypto_Substring(msg, &obj->pst);
Pack_OEMCrypto_Substring(msg, &obj->srm_restriction_data);
Pack_uint32_t(msg, &obj->license_type);
Pack_uint32_t(msg, &obj->nonce_required);
Pack_ODK_TimerLimits(msg, &obj->timer_limits);
PackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
Pack_uint32_t(msg, &obj->key_array_length);
size_t i;
for (i = 0; i < (size_t)obj->key_array_length; i++) {
Pack_OEMCrypto_KeyObject(msg, &obj->key_array[i]);
}
}
static void Pack_ODK_ParsedProvisioning(Message* msg,
ODK_ParsedProvisioning const* obj) {
Pack_uint32_t(msg, (const uint32_t*)&obj->key_type);
Pack_OEMCrypto_Substring(msg,
(const OEMCrypto_Substring*)&obj->enc_private_key);
Pack_OEMCrypto_Substring(
msg, (const OEMCrypto_Substring*)&obj->enc_private_key_iv);
Pack_OEMCrypto_Substring(
msg, (const OEMCrypto_Substring*)&obj->encrypted_message_key);
Pack_uint32_t(msg, &obj->key_type);
Pack_OEMCrypto_Substring(msg, &obj->enc_private_key);
Pack_OEMCrypto_Substring(msg, &obj->enc_private_key_iv);
Pack_OEMCrypto_Substring(msg, &obj->encrypted_message_key);
}
/* @@ odk serialize */
void Pack_ODK_PreparedLicense(Message* msg, ODK_PreparedLicense const* obj) {
Pack_ODK_CoreMessage(msg, (const ODK_CoreMessage*)&obj->core_message);
Pack_ODK_CoreMessage(msg, &obj->core_message);
}
void Pack_ODK_RenewalMessage(Message* msg, ODK_RenewalMessage const* obj) {
Pack_ODK_CoreMessage(msg, (const ODK_CoreMessage*)&obj->core_message);
Pack_uint64_t(msg, (const uint64_t*)&obj->playback_time);
Pack_ODK_CoreMessage(msg, &obj->core_message);
Pack_uint64_t(msg, &obj->playback_time);
}
void Pack_ODK_ProvisioningMessage(Message* msg,
ODK_ProvisioningMessage const* obj) {
Pack_ODK_CoreMessage(msg, (const ODK_CoreMessage*)&obj->core_message);
Pack_uint32_t(msg, (const uint32_t*)&obj->device_id_length);
PackArray(msg, (const uint8_t*)&obj->device_id[0], sizeof(obj->device_id));
Pack_ODK_CoreMessage(msg, &obj->core_message);
Pack_uint32_t(msg, &obj->device_id_length);
PackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
}
/* @@ kdo serialize */
void Pack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse const* obj) {
Pack_ODK_CoreMessage(msg, (const ODK_CoreMessage*)&obj->core_message);
Pack_ODK_CoreMessage(msg, &obj->core_message);
Pack_ODK_ParsedLicense(msg, (const ODK_ParsedLicense*)obj->parsed_license);
}
void Pack_ODK_ProvisioningResponse(Message* msg,
ODK_ProvisioningResponse const* obj) {
Pack_ODK_ProvisioningMessage(
msg, (const ODK_ProvisioningMessage*)&obj->core_provisioning);
Pack_ODK_ProvisioningMessage(msg, &obj->core_provisioning);
Pack_ODK_ParsedProvisioning(
msg, (const ODK_ParsedProvisioning*)obj->parsed_provisioning);
}
@@ -129,81 +121,77 @@ static void Unpack_ODK_CoreMessage(Message* msg, ODK_CoreMessage* obj) {
}
static void Unpack_OEMCrypto_KeyObject(Message* msg, OEMCrypto_KeyObject* obj) {
Unpack_OEMCrypto_Substring(msg, (OEMCrypto_Substring*)&obj->key_id);
Unpack_OEMCrypto_Substring(msg, (OEMCrypto_Substring*)&obj->key_data_iv);
Unpack_OEMCrypto_Substring(msg, (OEMCrypto_Substring*)&obj->key_data);
Unpack_OEMCrypto_Substring(msg, (OEMCrypto_Substring*)&obj->key_control_iv);
Unpack_OEMCrypto_Substring(msg, (OEMCrypto_Substring*)&obj->key_control);
Unpack_OEMCrypto_Substring(msg, &obj->key_id);
Unpack_OEMCrypto_Substring(msg, &obj->key_data_iv);
Unpack_OEMCrypto_Substring(msg, &obj->key_data);
Unpack_OEMCrypto_Substring(msg, &obj->key_control_iv);
Unpack_OEMCrypto_Substring(msg, &obj->key_control);
}
static void Unpack_ODK_TimerLimits(Message* msg, ODK_TimerLimits* obj) {
Unpack_uint32_t(msg, (uint32_t*)&obj->soft_expiry);
Unpack_uint64_t(msg, (uint64_t*)&obj->earliest_playback_start_seconds);
Unpack_uint64_t(msg, (uint64_t*)&obj->latest_playback_start_seconds);
Unpack_uint64_t(msg, (uint64_t*)&obj->initial_playback_duration_seconds);
Unpack_uint64_t(msg, (uint64_t*)&obj->renewal_playback_duration_seconds);
Unpack_uint64_t(msg, (uint64_t*)&obj->license_duration_seconds);
Unpack_uint32_t(msg, &obj->soft_expiry);
Unpack_uint64_t(msg, &obj->earliest_playback_start_seconds);
Unpack_uint64_t(msg, &obj->latest_playback_start_seconds);
Unpack_uint64_t(msg, &obj->initial_playback_duration_seconds);
Unpack_uint64_t(msg, &obj->renewal_playback_duration_seconds);
Unpack_uint64_t(msg, &obj->license_duration_seconds);
}
static void Unpack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense* obj) {
Unpack_OEMCrypto_Substring(msg, (OEMCrypto_Substring*)&obj->enc_mac_keys_iv);
Unpack_OEMCrypto_Substring(msg, (OEMCrypto_Substring*)&obj->enc_mac_keys);
Unpack_OEMCrypto_Substring(msg, (OEMCrypto_Substring*)&obj->pst);
Unpack_OEMCrypto_Substring(msg,
(OEMCrypto_Substring*)&obj->srm_restriction_data);
Unpack_uint32_t(msg, (uint32_t*)&obj->license_type);
Unpack_uint32_t(msg, (uint32_t*)&obj->nonce_required);
Unpack_ODK_TimerLimits(msg, (ODK_TimerLimits*)&obj->timer_limits);
UnpackArray(msg, (uint8_t*)&obj->request_hash[0], sizeof(obj->request_hash));
Unpack_uint32_t(msg, (uint32_t*)&obj->key_array_length);
Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv);
Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys);
Unpack_OEMCrypto_Substring(msg, &obj->pst);
Unpack_OEMCrypto_Substring(msg, &obj->srm_restriction_data);
Unpack_uint32_t(msg, &obj->license_type);
Unpack_uint32_t(msg, &obj->nonce_required);
Unpack_ODK_TimerLimits(msg, &obj->timer_limits);
UnpackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
Unpack_uint32_t(msg, &obj->key_array_length);
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
return;
}
for (uint32_t i = 0; i < obj->key_array_length; i++) {
uint32_t i;
for (i = 0; i < obj->key_array_length; i++) {
Unpack_OEMCrypto_KeyObject(msg, &obj->key_array[i]);
}
}
static void Unpack_ODK_ParsedProvisioning(Message* msg,
ODK_ParsedProvisioning* obj) {
Unpack_uint32_t(msg, (uint32_t*)&obj->key_type);
Unpack_OEMCrypto_Substring(msg, (OEMCrypto_Substring*)&obj->enc_private_key);
Unpack_OEMCrypto_Substring(msg,
(OEMCrypto_Substring*)&obj->enc_private_key_iv);
Unpack_OEMCrypto_Substring(msg,
(OEMCrypto_Substring*)&obj->encrypted_message_key);
Unpack_uint32_t(msg, &obj->key_type);
Unpack_OEMCrypto_Substring(msg, &obj->enc_private_key);
Unpack_OEMCrypto_Substring(msg, &obj->enc_private_key_iv);
Unpack_OEMCrypto_Substring(msg, &obj->encrypted_message_key);
}
/* @ kdo deserialize */
void Unpack_ODK_PreparedLicense(Message* msg, ODK_PreparedLicense* obj) {
Unpack_ODK_CoreMessage(msg, (ODK_CoreMessage*)&obj->core_message);
Unpack_ODK_CoreMessage(msg, &obj->core_message);
}
void Unpack_ODK_ProvisioningMessage(Message* msg,
ODK_ProvisioningMessage* obj) {
Unpack_ODK_CoreMessage(msg, (ODK_CoreMessage*)&obj->core_message);
Unpack_uint32_t(msg, (uint32_t*)&obj->device_id_length);
UnpackArray(msg, (uint8_t*)&obj->device_id[0], sizeof(obj->device_id));
Unpack_ODK_CoreMessage(msg, &obj->core_message);
Unpack_uint32_t(msg, &obj->device_id_length);
UnpackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
}
/* @@ odk deserialize */
void Unpack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse* obj) {
Unpack_ODK_CoreMessage(msg, (ODK_CoreMessage*)&obj->core_message);
Unpack_ODK_ParsedLicense(msg, (ODK_ParsedLicense*)obj->parsed_license);
Unpack_ODK_CoreMessage(msg, &obj->core_message);
Unpack_ODK_ParsedLicense(msg, obj->parsed_license);
}
void Unpack_ODK_RenewalMessage(Message* msg, ODK_RenewalMessage* obj) {
Unpack_ODK_CoreMessage(msg, (ODK_CoreMessage*)&obj->core_message);
Unpack_uint64_t(msg, (uint64_t*)&obj->playback_time);
Unpack_ODK_CoreMessage(msg, &obj->core_message);
Unpack_uint64_t(msg, &obj->playback_time);
}
void Unpack_ODK_ProvisioningResponse(Message* msg,
ODK_ProvisioningResponse* obj) {
Unpack_ODK_ProvisioningMessage(
msg, (ODK_ProvisioningMessage*)&obj->core_provisioning);
Unpack_ODK_ParsedProvisioning(
msg, (ODK_ParsedProvisioning*)obj->parsed_provisioning);
Unpack_ODK_ProvisioningMessage(msg, &obj->core_provisioning);
Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning);
}

View File

@@ -0,0 +1,42 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
/*
* This code is auto-generated, do not edit
*/
#ifndef WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_
#define WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_
#include "odk_structs_priv.h"
#include "serialization_base.h"
#ifdef __cplusplus
extern "C" {
#endif
/* odk pack */
void Pack_ODK_PreparedLicense(Message* msg, ODK_PreparedLicense const* obj);
void Pack_ODK_RenewalMessage(Message* msg, ODK_RenewalMessage const* obj);
void Pack_ODK_ProvisioningMessage(Message* msg,
ODK_ProvisioningMessage const* obj);
/* odk unpack */
void Unpack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse* obj);
void Unpack_ODK_RenewalMessage(Message* msg, ODK_RenewalMessage* obj);
void Unpack_ODK_ProvisioningResponse(Message* msg,
ODK_ProvisioningResponse* obj);
/* kdo pack */
void Pack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse const* obj);
void Pack_ODK_ProvisioningResponse(Message* msg,
ODK_ProvisioningResponse const* obj);
/* kdo unpack */
void Unpack_ODK_PreparedLicense(Message* msg, ODK_PreparedLicense* obj);
void Unpack_ODK_ProvisioningMessage(Message* msg, ODK_ProvisioningMessage* obj);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_ */

View File

@@ -0,0 +1,53 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
#ifndef WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_
#define WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_
#include <stdint.h>
#include "OEMCryptoCENCCommon.h"
#include "odk_structs.h"
typedef enum {
ODK_License_Request_Type = 1,
ODK_License_Response_Type = 2,
ODK_Renewal_Request_Type = 3,
ODK_Renewal_Response_Type = 4,
ODK_Provisioning_Request_Type = 5,
ODK_Provisioning_Response_Type = 6,
} ODK_MessageType;
typedef struct {
uint32_t message_type;
uint32_t message_length;
ODK_NonceValues nonce_values;
} ODK_CoreMessage;
typedef struct {
ODK_CoreMessage core_message;
} ODK_PreparedLicense;
typedef struct {
ODK_CoreMessage core_message;
uint64_t playback_time;
} ODK_RenewalMessage;
typedef struct {
ODK_CoreMessage core_message;
uint32_t device_id_length;
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX];
} ODK_ProvisioningMessage;
typedef struct {
ODK_CoreMessage core_message;
ODK_ParsedLicense* parsed_license;
} ODK_LicenseResponse;
typedef struct {
ODK_ProvisioningMessage core_provisioning;
ODK_ParsedProvisioning* parsed_provisioning;
} ODK_ProvisioningResponse;
#endif /* WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_ */

View File

@@ -1,8 +1,6 @@
/*
* Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
#include <stdint.h>
#include <string.h>
@@ -57,11 +55,11 @@ OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
}
OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
uint64_t time_of_license_signed,
uint64_t time_of_first_decrypt,
uint64_t time_of_last_decrypt,
enum OEMCrypto_Usage_Entry_Status status,
uint64_t system_time_seconds) {
uint64_t time_of_license_signed,
uint64_t time_of_first_decrypt,
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;
clock_values->time_of_license_signed = time_of_license_signed;
clock_values->time_of_first_decrypt = time_of_first_decrypt;
@@ -98,7 +96,8 @@ uint32_t ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
* session. */
if (clock_values->status == kUnused) {
/* If the rental clock has expired, the license has expired. */
if (rental_time > timer_limits->latest_playback_start_seconds) {
if (rental_time > timer_limits->latest_playback_start_seconds &&
timer_limits->latest_playback_start_seconds > 0) {
clock_values->timer_status = ODK_TIMER_EXPIRED;
return ODK_TIMER_EXPIRED;
}
@@ -187,6 +186,13 @@ OEMCryptoResult ODK_UpdateLastPlaybackTime(uint64_t system_time_seconds,
if (clock_values->timer_status == ODK_TIMER_EXPIRED) {
return ODK_TIMER_EXPIRED;
}
/* If the clock status is already marked as inactive, then playback is
* not allowed. */
/* TODO(b/142415188): add helper function. */
if (clock_values->status > kActive) {
clock_values->timer_status = ODK_TIMER_EXPIRED;
return ODK_TIMER_EXPIRED;
}
if (clock_values->time_when_timer_expires > 0 &&
system_time_seconds > clock_values->time_when_timer_expires) {
clock_values->timer_status = ODK_TIMER_EXPIRED;
@@ -200,7 +206,7 @@ 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 {
} else if (clock_values->status == kActive) {
clock_values->status = kInactiveUsed;
}
return OEMCrypto_SUCCESS;
@@ -227,3 +233,53 @@ OEMCryptoResult ODK_InitializeV15Values(ODK_TimerLimits* timer_limits,
}
return OEMCrypto_SUCCESS;
}
OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
const ODK_NonceValues* nonce_values,
uint64_t system_time_seconds,
uint64_t* timer_value) {
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL)
return OEMCrypto_ERROR_INVALID_CONTEXT;
if (nonce_values->api_version != 15) return OEMCrypto_ERROR_INVALID_NONCE;
if (clock_values->status > kActive) {
clock_values->timer_status = ODK_TIMER_EXPIRED;
return ODK_TIMER_EXPIRED;
}
/* If this is before the license was signed, something is odd. Return an
* error. */
if (system_time_seconds < clock_values->time_of_license_signed)
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
/* All times are relative to when the license was signed. */
const uint64_t rental_time =
system_time_seconds - clock_values->time_of_license_signed;
/* The timer should be limited by the renewal playback duration. This is
* similar to code in AttemptFirstPlayback, above, except we use the
* renewal_playback_duration here, and we do not change clock_values->status.
*/
uint64_t time_left = timer_limits->renewal_playback_duration_seconds;
/* If there is a license duration, it also limits the timer. Remember, a
* limit of 0 means no limit, or infinite. */
if (timer_limits->license_duration_seconds > 0) {
if (timer_limits->license_duration_seconds < rental_time) {
clock_values->timer_status = ODK_TIMER_EXPIRED;
return ODK_TIMER_EXPIRED;
}
if (timer_limits->license_duration_seconds - rental_time < time_left ||
time_left == 0) {
time_left = timer_limits->license_duration_seconds - rental_time;
}
}
if (time_left == 0 || timer_limits->soft_expiry) { /* Unlimited. */
clock_values->time_when_timer_expires = 0;
clock_values->timer_status = ODK_DISABLE_TIMER;
return ODK_DISABLE_TIMER;
}
/* Set timer to limit playback. */
if (timer_value) *timer_value = time_left;
clock_values->time_when_timer_expires = system_time_seconds + time_left;
clock_values->timer_status = ODK_SET_TIMER;
return ODK_SET_TIMER;
}

View File

@@ -1,8 +1,6 @@
/*
* Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
#include "serialization_base.h"
@@ -117,8 +115,16 @@ void Unpack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring* obj) {
Unpack_uint32_t(msg, &offset);
Unpack_uint32_t(msg, &length);
if (!ValidMessage(msg)) return;
size_t end = 0;
if (offset > msg->capacity || odk_add_overflow_ux(offset, length, &end) ||
/* Each substring should be contained within the message body, which is in the
* total message, just after the core message. The offset of a substring is
* relative to the message body. So we need to verify:
* 0 < offset and offset + length < message->capacity - message->size
* or offset + length + message->size < message->capacity
*/
size_t substring_end = 0; /* = offset + length; */
size_t end = 0; /* = substring_end + message->size; */
if (odk_add_overflow_ux(offset, length, &substring_end) ||
odk_add_overflow_ux(substring_end, msg->size, &end) ||
end > msg->capacity) {
msg->status = MESSAGE_STATUS_OVERFLOW_ERROR;
return;
@@ -188,6 +194,7 @@ 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;
message->size = size;
}

View File

@@ -0,0 +1,90 @@
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary */
/* source code may only be used and distributed under the Widevine Master */
/* License Agreement. */
#ifndef WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
#define WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
#include "OEMCryptoCENCCommon.h"
#define SIZE_OF_MESSAGE_STRUCT 64
/*
* Description:
* Point |msg| to stack-array |blk|.
* |blk| is guaranteed large enough to hold a |Message| struct.
* |blk| cannot be used in the same scope as a variable name.
* |msg| points to valid memory in the same scope |AllocateMessage| is used.
* Parameters:
* msg: pointer to pointer to |Message| struct
* blk: variable name for stack-array
*/
#define AllocateMessage(msg, blk) \
uint8_t blk[SIZE_OF_MESSAGE_STRUCT]; \
*(msg) = (Message*)(blk);
typedef struct _Message Message;
bool ValidMessage(Message* message);
void Pack_uint32_t(Message* message, const uint32_t* value);
void Pack_uint64_t(Message* message, const uint64_t* value);
void PackArray(Message* message, const uint8_t* base, size_t size);
void Pack_OEMCrypto_Substring(Message* msg, const OEMCrypto_Substring* obj);
void Unpack_uint32_t(Message* message, uint32_t* value);
void Unpack_uint64_t(Message* message, uint64_t* value);
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
* that the buffer remains allocated for the lifetime of the message.
*/
Message* CreateMessage(uint8_t* buffer, size_t buffer_size);
/*
* Initialize a message structure to reference a separate buffer. The caller
* is responsible for ensuring that the buffer remains allocated for the
* lifetime of the message.
*/
void InitMessage(Message* message, uint8_t* buffer, size_t capacity);
/*
* Reset an existing the message to an empty state
*/
void ResetMessage(Message* message);
uint8_t* GetBase(Message* message);
size_t GetCapacity(Message* message);
size_t GetSize(Message* message);
void SetSize(Message* message, size_t size);
MessageStatus GetStatus(Message* message);
void SetStatus(Message* message, MessageStatus status);
size_t GetOffset(Message* message);
size_t SizeOfMessageStruct();
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_ */