Update ODK Library and add license release unit test
Merge from Widevine repo of two CLs. Merge from Widevine repo of http://go/wvgerrit/94743 A license release should not have a core message. This CL adjusts the existing unit tests to verify this. There is also a new unit test called SecureStop that explicitly tests sending a secure stop in a new session without first loading the license. Merge from Widevine repo of http://go/wvgerrit/94865 This CL has the following changes copied from google3: http://cr/298871728 Remove odk_static_assert for Message size temporarily http://cr/298755935 Fix a compiling error during macro expansion http://cr/298481745 Add missing header for android http://cr/298448142 Fix odk_test gyp file http://cr/298419641 Remove header from Android.bp http://cr/298402053 Separate sizeOf(args) bytes in fuzz tests http://cr/297730316 No core messages for license release http://cr/297714346 Add copybara_test and piper_sot_to_gerrit http://cr/297636713 Adding some comments around boolean conversion code http://cr/297420679 Autofuzzer when ran with address sanitizer ... http://cr/296513584 Minor fix with fuzzing odk clock values http://cr/296322024 Fixing errors in code with how request ... http://cr/296313159 Fuzzing ODK clock values by setting aside ... http://cr/295763207 Add more odk tests and move helper functions to test helper http://cr/294524098 Adding a Build Rule for ODK_KDO_Fuzzer and updating http://cr/294492213 Address a few review comments of ODK http://cr/293674368 odk_fuzz: add TODOs & comments http://cr/293492806 Fix spelling Bug: 150243585 Bug: 150020278 Bug: 150095506 Bug: 147297226 Bug: 148290294 Bug: 148907684 Bug: 150608451 Test: unit tests Change-Id: I25fd406f29f4eba40f5cb27e9a1317dce4ffc2f5
This commit is contained in:
committed by
Jeff Tinker
parent
0947bd185b
commit
c5b7a01ab5
@@ -9,7 +9,7 @@
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "OEMCryptoCENCCommon.h"
|
||||
#include "core_message_deserialize.h"
|
||||
@@ -20,48 +20,74 @@
|
||||
#include "odk_structs.h"
|
||||
#include "odk_structs_priv.h"
|
||||
|
||||
// TODO(b/147297226): remove this: using namespace std;
|
||||
// TODO(b/147297226): remove this: using namespace oec_util;
|
||||
typedef std::function<size_t(const uint8_t*, uint8_t*, size_t, size_t)>
|
||||
roundtrip_fun;
|
||||
|
||||
typedef std::function<size_t(const uint8_t*, uint8_t*, size_t)> roundtrip_fun;
|
||||
using oemcrypto_core_message::ODK_LicenseRequest;
|
||||
using oemcrypto_core_message::ODK_ProvisioningRequest;
|
||||
using oemcrypto_core_message::ODK_RenewalRequest;
|
||||
|
||||
// @ kdo deserialize; odk derialize
|
||||
static OEMCryptoResult odk_fun_LicenseRequest(
|
||||
uint8_t* out, size_t* size, uint32_t api_version, uint32_t nonce,
|
||||
uint32_t session_id, const ODK_LicenseRequest& /*core_license_request*/) {
|
||||
return ODK_PrepareCoreLicenseRequest(out, SIZE_MAX, size, api_version, nonce,
|
||||
session_id);
|
||||
using oemcrypto_core_message::deserialize::CoreLicenseRequestFromMessage;
|
||||
using oemcrypto_core_message::deserialize::CoreProvisioningRequestFromMessage;
|
||||
using oemcrypto_core_message::deserialize::CoreRenewalRequestFromMessage;
|
||||
|
||||
using oemcrypto_core_message::serialize::CreateCoreLicenseResponse;
|
||||
using oemcrypto_core_message::serialize::CreateCoreProvisioningResponse;
|
||||
using oemcrypto_core_message::serialize::CreateCoreRenewalResponse;
|
||||
|
||||
// @ kdo deserialize; odk serialize
|
||||
static OEMCryptoResult odk_serialize_LicenseRequest(
|
||||
const void* in, uint8_t* out, size_t* size,
|
||||
const ODK_LicenseRequest& core_license_request,
|
||||
const ODK_NonceValues* nonce_values) {
|
||||
return ODK_PrepareCoreLicenseRequest(out, SIZE_MAX, size, nonce_values);
|
||||
}
|
||||
|
||||
static OEMCryptoResult odk_fun_RenewalRequest(
|
||||
uint8_t* out, size_t* size, uint32_t api_version, uint32_t nonce,
|
||||
uint32_t session_id, const ODK_RenewalRequest& core_renewal) {
|
||||
// todo: fuzz ODK_ClockValues
|
||||
ODK_ClockValues clock = {};
|
||||
uint64_t system_time_seconds = core_renewal.playback_time;
|
||||
return ODK_PrepareCoreRenewalRequest(out, SIZE_MAX, size, api_version, nonce,
|
||||
session_id, &clock, system_time_seconds);
|
||||
static OEMCryptoResult odk_serialize_RenewalRequest(
|
||||
const void* in, uint8_t* out, size_t* size,
|
||||
const ODK_RenewalRequest& core_renewal, ODK_NonceValues* nonce_values) {
|
||||
ODK_ClockValues clock{};
|
||||
memcpy(&clock, in, sizeof(ODK_ClockValues));
|
||||
uint64_t system_time_seconds = core_renewal.playback_time_seconds;
|
||||
return ODK_PrepareCoreRenewalRequest(out, SIZE_MAX, size, nonce_values,
|
||||
&clock, system_time_seconds);
|
||||
}
|
||||
|
||||
static OEMCryptoResult odk_fun_ProvisioningRequest(
|
||||
uint8_t* out, size_t* size, uint32_t api_version, uint32_t nonce,
|
||||
uint32_t session_id, const ODK_ProvisioningRequest& core_provisioning) {
|
||||
static OEMCryptoResult odk_serialize_ProvisioningRequest(
|
||||
const void* in, uint8_t* out, size_t* size,
|
||||
const ODK_ProvisioningRequest& core_provisioning,
|
||||
const ODK_NonceValues* nonce_values) {
|
||||
const std::string& device_id = core_provisioning.device_id;
|
||||
return ODK_PrepareCoreProvisioningRequest(
|
||||
out, SIZE_MAX, size, api_version, nonce, session_id,
|
||||
out, SIZE_MAX, size, nonce_values,
|
||||
reinterpret_cast<const uint8_t*>(device_id.data()), device_id.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Template arguments:
|
||||
* T: kdo deserialize output/odk serialize input structure
|
||||
* F: kdo deserialize function
|
||||
* G: odk serialize function
|
||||
*
|
||||
* raw bytes -> F deserialize -> struct T -> G serialize -> raw bytes
|
||||
*/
|
||||
template <typename T, typename F, typename G>
|
||||
static roundtrip_fun kdo_odk(const F& kdo_fun, const G& odk_fun) {
|
||||
auto roundtrip = [&](const uint8_t* in, uint8_t* out, size_t size) -> size_t {
|
||||
std::string input(reinterpret_cast<const char*>(in), size);
|
||||
auto roundtrip = [&](const uint8_t* in, uint8_t* out, size_t size,
|
||||
size_t clock_value_size) -> size_t {
|
||||
if (size <= clock_value_size) {
|
||||
return 0;
|
||||
}
|
||||
// Input byte array format: [Clock Values][data to parse]
|
||||
std::string input(reinterpret_cast<const char*>(in) + clock_value_size,
|
||||
size - clock_value_size);
|
||||
T t = {};
|
||||
if (!kdo_fun(input, &t)) {
|
||||
return 0;
|
||||
}
|
||||
OEMCryptoResult err =
|
||||
odk_fun(out, &size, t.api_version, t.nonce, t.session_id, t);
|
||||
ODK_NonceValues nonce_values = {t.api_minor_version, t.api_major_version,
|
||||
t.nonce, t.session_id};
|
||||
OEMCryptoResult err = odk_fun(in, out, &size, t, &nonce_values);
|
||||
return OEMCrypto_SUCCESS == err ? size : 0;
|
||||
};
|
||||
return roundtrip;
|
||||
@@ -70,7 +96,8 @@ static roundtrip_fun kdo_odk(const F& kdo_fun, const G& odk_fun) {
|
||||
// @ odk deserialize; kdo serialize
|
||||
namespace {
|
||||
struct ODK_Common_Args {
|
||||
uint32_t api_version;
|
||||
uint16_t api_minor_version;
|
||||
uint16_t api_major_version;
|
||||
uint32_t nonce;
|
||||
uint32_t session_id;
|
||||
};
|
||||
@@ -78,6 +105,9 @@ struct ODK_ParseLicense_Args {
|
||||
ODK_Common_Args common;
|
||||
uint8_t initial_license_load;
|
||||
uint8_t usage_entry_present;
|
||||
uint8_t request_hash[32];
|
||||
ODK_TimerLimits timer_limits;
|
||||
ODK_ClockValues clock_values;
|
||||
};
|
||||
struct ODK_ParseRenewal_Args {
|
||||
ODK_Common_Args common;
|
||||
@@ -92,93 +122,128 @@ struct ODK_ParseProvisioning_Args {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static OEMCryptoResult odk_fun_LicenseResponse(
|
||||
const uint8_t* message, size_t message_length, uint32_t api_version,
|
||||
uint32_t nonce, uint32_t session_id, const ODK_ParseLicense_Args* a,
|
||||
ODK_ParsedLicense& parsed_lic) {
|
||||
return ODK_ParseLicense(
|
||||
message, message_length, api_version, nonce, session_id,
|
||||
static_cast<bool>(a->initial_license_load),
|
||||
static_cast<bool>(a->usage_entry_present), &parsed_lic);
|
||||
uint8_t convert_byte_to_valid_boolean(const bool* in) {
|
||||
uint8_t boolean_value;
|
||||
memcpy(&boolean_value, in, 1);
|
||||
return boolean_value % 2;
|
||||
}
|
||||
|
||||
static bool kdo_fun_LicenseResponse(const ODK_ParseLicense_Args* args,
|
||||
const ODK_ParsedLicense& parsed_lic,
|
||||
std::string* oemcrypto_core_message) {
|
||||
static OEMCryptoResult odk_deserialize_LicenseResponse(
|
||||
const uint8_t* message, size_t core_message_length,
|
||||
ODK_ParseLicense_Args* a, ODK_NonceValues* nonce_values,
|
||||
ODK_ParsedLicense* parsed_lic) {
|
||||
return ODK_ParseLicense(message, SIZE_MAX, core_message_length,
|
||||
static_cast<bool>(a->initial_license_load),
|
||||
static_cast<bool>(a->usage_entry_present),
|
||||
a->request_hash, &a->timer_limits, &a->clock_values,
|
||||
nonce_values, parsed_lic);
|
||||
}
|
||||
|
||||
static bool kdo_serialize_LicenseResponse(const ODK_ParseLicense_Args* args,
|
||||
const ODK_ParsedLicense& parsed_lic,
|
||||
std::string* oemcrypto_core_message) {
|
||||
const auto& common = args->common;
|
||||
ODK_LicenseRequest core_request{common.api_version, common.nonce,
|
||||
ODK_LicenseRequest core_request{common.api_minor_version,
|
||||
common.api_major_version, common.nonce,
|
||||
common.session_id};
|
||||
return CreateCoreLicenseResponse(parsed_lic, core_request,
|
||||
oemcrypto_core_message);
|
||||
std::string core_request_sha_256(
|
||||
reinterpret_cast<const char*>(args->request_hash), 32);
|
||||
return CreateCoreLicenseResponse(
|
||||
parsed_lic, core_request, core_request_sha_256, oemcrypto_core_message);
|
||||
}
|
||||
|
||||
static OEMCryptoResult odk_fun_RenewalResponse(
|
||||
const uint8_t* buf, size_t len, uint32_t api_version, uint32_t nonce,
|
||||
uint32_t session_id, ODK_ParseRenewal_Args* a,
|
||||
ODK_PreparedRenewalRequest& renewal_msg) {
|
||||
static OEMCryptoResult odk_deserialize_RenewalResponse(
|
||||
const uint8_t* buf, size_t len, ODK_ParseRenewal_Args* a,
|
||||
ODK_NonceValues* nonce_values, ODK_PreparedRenewalRequest* renewal_msg) {
|
||||
/* Address Sanitizer doesn't like values other than 0 OR 1 for boolean
|
||||
* variables. Input from fuzzer can be parsed and any random bytes can be
|
||||
* assigned to boolean variables. Using the workaround to mitigate sanitizer
|
||||
* errors in fuzzer code and converting random bytes to 0 OR 1.
|
||||
* This has no negative security impact*/
|
||||
a->timer_limits.soft_enforce_playback_duration =
|
||||
convert_byte_to_valid_boolean(
|
||||
&a->timer_limits.soft_enforce_playback_duration);
|
||||
a->timer_limits.soft_enforce_rental_duration = convert_byte_to_valid_boolean(
|
||||
&a->timer_limits.soft_enforce_rental_duration);
|
||||
uint64_t timer_value = 0;
|
||||
OEMCryptoResult err =
|
||||
ODK_ParseRenewal(buf, len, api_version, nonce, session_id, a->system_time,
|
||||
ODK_ParseRenewal(buf, SIZE_MAX, len, nonce_values, a->system_time,
|
||||
&a->timer_limits, &a->clock_values, &timer_value);
|
||||
if (OEMCrypto_SUCCESS == err) {
|
||||
Message* msg = nullptr;
|
||||
AllocateMessage(&msg, message_block);
|
||||
InitMessage(msg, const_cast<uint8_t*>(buf), len);
|
||||
SetSize(msg, len);
|
||||
Unpack_ODK_PreparedRenewalRequest(msg, &renewal_msg);
|
||||
Unpack_ODK_PreparedRenewalRequest(msg, renewal_msg);
|
||||
assert(ValidMessage(msg));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool kdo_fun_RenewalResponse(
|
||||
static bool kdo_serialize_RenewalResponse(
|
||||
const ODK_ParseRenewal_Args* args,
|
||||
const ODK_PreparedRenewalRequest& renewal_msg,
|
||||
std::string* oemcrypto_core_message) {
|
||||
const auto& common = args->common;
|
||||
ODK_RenewalRequest core_request{common.api_version, common.nonce,
|
||||
ODK_RenewalRequest core_request{common.api_minor_version,
|
||||
common.api_major_version, common.nonce,
|
||||
common.session_id, renewal_msg.playback_time};
|
||||
return CreateCoreRenewalResponse(core_request, oemcrypto_core_message);
|
||||
return CreateCoreRenewalResponse(
|
||||
core_request, args->timer_limits.initial_renewal_duration_seconds,
|
||||
oemcrypto_core_message);
|
||||
}
|
||||
|
||||
static OEMCryptoResult odk_fun_ProvisioningResponse(
|
||||
const uint8_t* buf, size_t len, uint32_t api_version, uint32_t nonce,
|
||||
uint32_t session_id, ODK_ParseProvisioning_Args* a,
|
||||
ODK_ParsedProvisioning& parsed_prov) {
|
||||
return ODK_ParseProvisioning(buf, len, api_version, nonce, session_id,
|
||||
a->device_id, a->device_id_length, &parsed_prov);
|
||||
static OEMCryptoResult odk_deserialize_ProvisioningResponse(
|
||||
const uint8_t* buf, size_t len, ODK_ParseProvisioning_Args* a,
|
||||
ODK_NonceValues* nonce_values, ODK_ParsedProvisioning* parsed_prov) {
|
||||
return ODK_ParseProvisioning(buf, SIZE_MAX, len, nonce_values, a->device_id,
|
||||
a->device_id_length, parsed_prov);
|
||||
}
|
||||
|
||||
static bool kdo_fun_ProvisioningResponse(
|
||||
static bool kdo_serialize_ProvisioningResponse(
|
||||
const ODK_ParseProvisioning_Args* args,
|
||||
const ODK_ParsedProvisioning& parsed_prov,
|
||||
std::string* oemcrypto_core_message) {
|
||||
const auto& common = args->common;
|
||||
assert(args->device_id_length <= sizeof(args->device_id));
|
||||
ODK_ProvisioningRequest core_request{
|
||||
common.api_version, common.nonce, common.session_id,
|
||||
common.api_minor_version, common.api_major_version, common.nonce,
|
||||
common.session_id,
|
||||
std::string(reinterpret_cast<const char*>(args->device_id),
|
||||
args->device_id_length)};
|
||||
return CreateCoreProvisioningResponse(parsed_prov, core_request,
|
||||
oemcrypto_core_message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Template arguments:
|
||||
* A: struct holding function arguments
|
||||
* T: odk deserialize output/kdo serialize input structure
|
||||
* F: odk deserialize function
|
||||
* G: kdo serialize function
|
||||
*
|
||||
* raw bytes -> F deserialize -> struct T -> G serialize -> raw bytes
|
||||
*/
|
||||
template <typename A, typename T, typename F, typename G>
|
||||
static roundtrip_fun odk_kdo(const F& odk_fun, const G& kdo_fun) {
|
||||
auto roundtrip = [&](const uint8_t* in, uint8_t* out, size_t size) -> size_t {
|
||||
if (sizeof(A) > size) {
|
||||
auto roundtrip = [&](const uint8_t* in, uint8_t* out, size_t size,
|
||||
size_t args_size) -> size_t {
|
||||
// Input byte array format: [function arguments][data to parse]
|
||||
if (args_size > size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
T t = {};
|
||||
const uint8_t* buf = in + sizeof(A);
|
||||
size_t len = size - sizeof(A);
|
||||
const uint8_t* buf = in + args_size;
|
||||
size_t len = size - args_size;
|
||||
std::shared_ptr<A> _args(new A());
|
||||
A* args = _args.get();
|
||||
memcpy(args, in, sizeof(A));
|
||||
memcpy(args, in, args_size);
|
||||
const auto& common = args->common;
|
||||
OEMCryptoResult err = odk_fun(buf, len, common.api_version, common.nonce,
|
||||
common.session_id, args, t);
|
||||
ODK_NonceValues nonce_values = {common.api_minor_version,
|
||||
common.api_major_version, common.nonce,
|
||||
common.session_id};
|
||||
OEMCryptoResult err = odk_fun(buf, len, args, &nonce_values, &t);
|
||||
if (err != OEMCrypto_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
@@ -197,33 +262,43 @@ static roundtrip_fun odk_kdo(const F& odk_fun, const G& kdo_fun) {
|
||||
|
||||
// @ fuzz raw -> parsed -> raw
|
||||
static void verify_roundtrip(const uint8_t* in, size_t size,
|
||||
roundtrip_fun roundtrip) {
|
||||
roundtrip_fun roundtrip, size_t args_size) {
|
||||
std::vector<uint8_t> _out(size);
|
||||
auto out = _out.data();
|
||||
size_t n = roundtrip(in, out, size);
|
||||
assert(!n || (n <= size && 0 == memcmp(in, out, n)));
|
||||
size_t n = roundtrip(in, out, size, args_size);
|
||||
assert(n <= size && 0 == memcmp(in + args_size, out, n));
|
||||
}
|
||||
|
||||
// Entry point for fuzzer, data is random bytes program gets from autofuzzer
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
verify_roundtrip(data, size,
|
||||
kdo_odk<ODK_LicenseRequest>(CoreLicenseRequestFromMessage,
|
||||
odk_serialize_LicenseRequest),
|
||||
0);
|
||||
verify_roundtrip(data, size,
|
||||
kdo_odk<ODK_RenewalRequest>(CoreRenewalRequestFromMessage,
|
||||
odk_serialize_RenewalRequest),
|
||||
sizeof(ODK_ClockValues));
|
||||
verify_roundtrip(
|
||||
data, size,
|
||||
kdo_odk<ODK_LicenseRequest>(ParseLicenseRequest, odk_fun_LicenseRequest));
|
||||
kdo_odk<ODK_ProvisioningRequest>(CoreProvisioningRequestFromMessage,
|
||||
odk_serialize_ProvisioningRequest),
|
||||
0);
|
||||
verify_roundtrip(
|
||||
data, size,
|
||||
kdo_odk<ODK_RenewalRequest>(ParseRenewalRequest, odk_fun_RenewalRequest));
|
||||
verify_roundtrip(data, size,
|
||||
kdo_odk<ODK_ProvisioningRequest>(
|
||||
ParseProvisioningRequest, odk_fun_ProvisioningRequest));
|
||||
verify_roundtrip(data, size,
|
||||
odk_kdo<ODK_ParseLicense_Args, ODK_ParsedLicense>(
|
||||
odk_fun_LicenseResponse, kdo_fun_LicenseResponse));
|
||||
verify_roundtrip(data, size,
|
||||
odk_kdo<ODK_ParseRenewal_Args, ODK_PreparedRenewalRequest>(
|
||||
odk_fun_RenewalResponse, kdo_fun_RenewalResponse));
|
||||
odk_kdo<ODK_ParseLicense_Args, ODK_ParsedLicense>(
|
||||
odk_deserialize_LicenseResponse, kdo_serialize_LicenseResponse),
|
||||
sizeof(ODK_ParseLicense_Args));
|
||||
verify_roundtrip(
|
||||
data, size,
|
||||
odk_kdo<ODK_ParseProvisioning_Args, ODK_ParsedProvisioning>(
|
||||
odk_fun_ProvisioningResponse, kdo_fun_ProvisioningResponse));
|
||||
odk_kdo<ODK_ParseRenewal_Args, ODK_PreparedRenewalRequest>(
|
||||
odk_deserialize_RenewalResponse, kdo_serialize_RenewalResponse),
|
||||
sizeof(ODK_ParseRenewal_Args));
|
||||
verify_roundtrip(data, size,
|
||||
odk_kdo<ODK_ParseProvisioning_Args, ODK_ParsedProvisioning>(
|
||||
odk_deserialize_ProvisioningResponse,
|
||||
kdo_serialize_ProvisioningResponse),
|
||||
sizeof(ODK_ParseProvisioning_Args));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
488
libwvdrmengine/oemcrypto/odk/test/odk_test_helper.cpp
Normal file
488
libwvdrmengine/oemcrypto/odk/test/odk_test_helper.cpp
Normal file
@@ -0,0 +1,488 @@
|
||||
// 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_test_helper.h"
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "OEMCryptoCENCCommon.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "odk_structs.h"
|
||||
#include "odk_structs_priv.h"
|
||||
|
||||
namespace wvodk_test {
|
||||
|
||||
void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message,
|
||||
uint32_t message_type) {
|
||||
ASSERT_TRUE(core_message != nullptr);
|
||||
core_message->message_type = message_type;
|
||||
core_message->message_length = 0;
|
||||
core_message->nonce_values.api_minor_version = ODK_MINOR_VERSION;
|
||||
core_message->nonce_values.api_major_version = ODK_MAJOR_VERSION;
|
||||
core_message->nonce_values.nonce = 0xdeadbeef;
|
||||
core_message->nonce_values.session_id = 0xcafebabe;
|
||||
}
|
||||
|
||||
void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params) {
|
||||
ODK_SetDefaultCoreFields(&(params->core_message), ODK_License_Response_Type);
|
||||
params->initial_license_load = true;
|
||||
params->usage_entry_present = true;
|
||||
params->parsed_license = {
|
||||
.enc_mac_keys_iv = {.offset = 0, .length = 1},
|
||||
.enc_mac_keys = {.offset = 2, .length = 3},
|
||||
.pst = {.offset = 4, .length = 5},
|
||||
.srm_restriction_data = {.offset = 6, .length = 7},
|
||||
.license_type = OEMCrypto_EntitlementLicense,
|
||||
.nonce_required = true,
|
||||
.timer_limits =
|
||||
{
|
||||
.soft_enforce_rental_duration = true,
|
||||
.soft_enforce_playback_duration = false,
|
||||
.earliest_playback_start_seconds = 10,
|
||||
.rental_duration_seconds = 11,
|
||||
.total_playback_duration_seconds = 12,
|
||||
.initial_renewal_duration_seconds = 13,
|
||||
},
|
||||
.key_array_length = 3,
|
||||
.key_array =
|
||||
{
|
||||
{
|
||||
.key_id = {.offset = 15, .length = 16},
|
||||
.key_data_iv = {.offset = 17, .length = 18},
|
||||
.key_data = {.offset = 19, .length = 20},
|
||||
.key_control_iv = {.offset = 21, .length = 22},
|
||||
.key_control = {.offset = 23, .length = 24},
|
||||
},
|
||||
{
|
||||
.key_id = {.offset = 25, .length = 26},
|
||||
.key_data_iv = {.offset = 27, .length = 28},
|
||||
.key_data = {.offset = 29, .length = 30},
|
||||
.key_control_iv = {.offset = 31, .length = 32},
|
||||
.key_control = {.offset = 33, .length = 34},
|
||||
},
|
||||
{
|
||||
.key_id = {.offset = 35, .length = 36},
|
||||
.key_data_iv = {.offset = 37, .length = 38},
|
||||
.key_data = {.offset = 39, .length = 40},
|
||||
.key_control_iv = {.offset = 41, .length = 42},
|
||||
.key_control = {.offset = 43, .length = 44},
|
||||
},
|
||||
},
|
||||
};
|
||||
memset(params->request_hash, 0xaa, sizeof(params->request_hash));
|
||||
params->extra_fields = {
|
||||
{ODK_SUBSTRING, &(params->parsed_license.enc_mac_keys_iv),
|
||||
".enc_mac_keys_iv"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.enc_mac_keys), ".enc_mac_keys"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.pst), ".pst"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.srm_restriction_data),
|
||||
".srm_restriction_data"},
|
||||
{ODK_UINT32, &(params->parsed_license.license_type), ".license_type"},
|
||||
{ODK_UINT32, &(params->parsed_license.nonce_required), ".nonce_required"},
|
||||
{ODK_UINT32,
|
||||
&(params->parsed_license.timer_limits.soft_enforce_rental_duration),
|
||||
".soft_enforce_rental_duration"},
|
||||
{ODK_UINT32,
|
||||
&(params->parsed_license.timer_limits.soft_enforce_playback_duration),
|
||||
".soft_enforce_playback_duration"},
|
||||
{ODK_UINT64,
|
||||
&(params->parsed_license.timer_limits.earliest_playback_start_seconds),
|
||||
".earliest_playback_start_seconds"},
|
||||
{ODK_UINT64,
|
||||
&(params->parsed_license.timer_limits.rental_duration_seconds),
|
||||
".rental_duration_seconds"},
|
||||
{ODK_UINT64,
|
||||
&(params->parsed_license.timer_limits.total_playback_duration_seconds),
|
||||
".total_playback_duration_seconds"},
|
||||
{ODK_UINT64,
|
||||
&(params->parsed_license.timer_limits.initial_renewal_duration_seconds),
|
||||
".initial_renewal_duration_seconds"},
|
||||
{ODK_UINT32, &(params->parsed_license.key_array_length),
|
||||
".key_array_length"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_id), ".key_id"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_data_iv),
|
||||
".key_data_iv"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_data),
|
||||
".key_data"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_control_iv),
|
||||
".key_control_iv"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_control),
|
||||
".key_control"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_id), ".key_id"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_data_iv),
|
||||
".key_data_iv"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_data),
|
||||
".key_data"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_control_iv),
|
||||
".key_control_iv"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_control),
|
||||
".key_control"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_id), ".key_id"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_data_iv),
|
||||
".key_data_iv"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_data),
|
||||
".key_data"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_control_iv),
|
||||
".key_control_iv"},
|
||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_control),
|
||||
".key_control"},
|
||||
{ODK_HASH, params->request_hash, ".request_hash"},
|
||||
};
|
||||
}
|
||||
|
||||
void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params) {
|
||||
ODK_SetDefaultCoreFields(&(params->core_message), ODK_Renewal_Response_Type);
|
||||
params->system_time = 0xfaceb00c;
|
||||
params->playback_clock = 10;
|
||||
params->playback_timer = 20;
|
||||
params->renewal_duration = 300;
|
||||
params->extra_fields = {
|
||||
{ODK_UINT64, &(params->playback_clock), "playback_clock"},
|
||||
{ODK_UINT64, &(params->renewal_duration), "renewal_duration"},
|
||||
};
|
||||
params->timer_limits = {
|
||||
.soft_enforce_rental_duration = false,
|
||||
.soft_enforce_playback_duration = false,
|
||||
.earliest_playback_start_seconds = 0,
|
||||
.rental_duration_seconds = 1000,
|
||||
.total_playback_duration_seconds = 2000,
|
||||
.initial_renewal_duration_seconds = 300,
|
||||
};
|
||||
params->clock_values = {
|
||||
.time_of_license_signed =
|
||||
params->system_time - params->playback_clock - 42,
|
||||
.time_of_first_decrypt = params->system_time - params->playback_clock,
|
||||
.time_of_last_decrypt = params->system_time - params->playback_clock,
|
||||
.time_of_renewal_request = params->playback_clock,
|
||||
.time_when_timer_expires = params->system_time + params->playback_timer,
|
||||
.timer_status = ODK_CLOCK_TIMER_STATUS_ACTIVE,
|
||||
.status = kActive,
|
||||
};
|
||||
}
|
||||
|
||||
void ODK_SetDefaultProvisioningResponseParams(
|
||||
ODK_ProvisioningResponseParams* params) {
|
||||
ODK_SetDefaultCoreFields(&(params->core_message),
|
||||
ODK_Provisioning_Response_Type);
|
||||
params->device_id_length = ODK_DEVICE_ID_LEN_MAX / 2;
|
||||
memset(params->device_id, 0xff, params->device_id_length);
|
||||
memset(params->device_id + params->device_id_length, 0,
|
||||
ODK_DEVICE_ID_LEN_MAX - params->device_id_length);
|
||||
params->parsed_provisioning = {
|
||||
.enc_private_key = {.offset = 0, .length = 1},
|
||||
.enc_private_key_iv = {.offset = 2, .length = 3},
|
||||
.encrypted_message_key = {.offset = 4, .length = 5},
|
||||
};
|
||||
params->extra_fields = {
|
||||
{ODK_UINT32, &(params->device_id_length), "device_id_length"},
|
||||
{ODK_DEVICEID, params->device_id, "device_id"},
|
||||
{ODK_UINT32, &(params->parsed_provisioning).key_type, "key_type"},
|
||||
{ODK_SUBSTRING, &(params->parsed_provisioning).enc_private_key,
|
||||
"enc_private_key"},
|
||||
{ODK_SUBSTRING, &(params->parsed_provisioning).enc_private_key_iv,
|
||||
"enc_private_key_iv"},
|
||||
{ODK_SUBSTRING, &(params->parsed_provisioning).encrypted_message_key,
|
||||
"encrypted_message_key"},
|
||||
};
|
||||
}
|
||||
|
||||
size_t ODK_FieldLength(ODK_FieldType type) {
|
||||
switch (type) {
|
||||
case ODK_UINT16:
|
||||
return sizeof(uint16_t);
|
||||
case ODK_UINT32:
|
||||
return sizeof(uint32_t);
|
||||
case ODK_UINT64:
|
||||
return sizeof(uint64_t);
|
||||
case ODK_SUBSTRING:
|
||||
return sizeof(uint32_t) + sizeof(uint32_t);
|
||||
case ODK_DEVICEID:
|
||||
return ODK_DEVICE_ID_LEN_MAX;
|
||||
case ODK_HASH:
|
||||
return ODK_SHA256_HASH_SIZE;
|
||||
default:
|
||||
return SIZE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
size_t ODK_AllocSize(ODK_FieldType type) {
|
||||
if (type == ODK_SUBSTRING) {
|
||||
return sizeof(OEMCrypto_Substring);
|
||||
}
|
||||
return ODK_FieldLength(type);
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_WriteSingleField(uint8_t* buf, const ODK_Field* field) {
|
||||
if (buf == nullptr || field == nullptr || field->value == nullptr) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
switch (field->type) {
|
||||
case ODK_UINT16: {
|
||||
uint16_t u16 = htobe16(*static_cast<uint16_t*>(field->value));
|
||||
memcpy(buf, &u16, sizeof(u16));
|
||||
break;
|
||||
}
|
||||
case ODK_UINT32: {
|
||||
uint32_t u32 = htobe32(*static_cast<uint32_t*>(field->value));
|
||||
memcpy(buf, &u32, sizeof(u32));
|
||||
break;
|
||||
}
|
||||
case ODK_UINT64: {
|
||||
uint64_t u64 = htobe64(*static_cast<uint64_t*>(field->value));
|
||||
memcpy(buf, &u64, sizeof(u64));
|
||||
break;
|
||||
}
|
||||
case ODK_SUBSTRING: {
|
||||
OEMCrypto_Substring* s = static_cast<OEMCrypto_Substring*>(field->value);
|
||||
uint32_t off = htobe32(s->offset);
|
||||
uint32_t len = htobe32(s->length);
|
||||
memcpy(buf, &off, sizeof(off));
|
||||
memcpy(buf + sizeof(off), &len, sizeof(len));
|
||||
break;
|
||||
}
|
||||
case ODK_DEVICEID:
|
||||
case ODK_HASH: {
|
||||
const size_t field_len = ODK_FieldLength(field->type);
|
||||
const uint8_t* const id = static_cast<uint8_t*>(field->value);
|
||||
memcpy(buf, id, field_len);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_ReadSingleField(const uint8_t* buf,
|
||||
const ODK_Field* field) {
|
||||
if (field == nullptr || field->value == nullptr) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
switch (field->type) {
|
||||
case ODK_UINT16: {
|
||||
memcpy(field->value, buf, sizeof(uint16_t));
|
||||
uint16_t* u16p = static_cast<uint16_t*>(field->value);
|
||||
*u16p = be16toh(*u16p);
|
||||
break;
|
||||
}
|
||||
case ODK_UINT32: {
|
||||
memcpy(field->value, buf, sizeof(uint32_t));
|
||||
uint32_t* u32p = static_cast<uint32_t*>(field->value);
|
||||
*u32p = be32toh(*u32p);
|
||||
break;
|
||||
}
|
||||
case ODK_UINT64: {
|
||||
memcpy(field->value, buf, sizeof(uint64_t));
|
||||
uint64_t* u64p = static_cast<uint64_t*>(field->value);
|
||||
*u64p = be64toh(*u64p);
|
||||
break;
|
||||
}
|
||||
case ODK_SUBSTRING: {
|
||||
OEMCrypto_Substring* s = static_cast<OEMCrypto_Substring*>(field->value);
|
||||
uint32_t off = 0;
|
||||
uint32_t len = 0;
|
||||
memcpy(&off, buf, sizeof(off));
|
||||
memcpy(&len, buf + sizeof(off), sizeof(len));
|
||||
s->offset = be32toh(off);
|
||||
s->length = be32toh(len);
|
||||
break;
|
||||
}
|
||||
case ODK_DEVICEID:
|
||||
case ODK_HASH: {
|
||||
const size_t field_len = ODK_FieldLength(field->type);
|
||||
uint8_t* const id = static_cast<uint8_t*>(field->value);
|
||||
memcpy(id, buf, field_len);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf,
|
||||
const ODK_Field* field) {
|
||||
if (field == nullptr || field->value == nullptr) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
switch (field->type) {
|
||||
case ODK_UINT16: {
|
||||
uint16_t val;
|
||||
memcpy(&val, buf, sizeof(uint16_t));
|
||||
val = be16toh(val);
|
||||
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||
<< "\n";
|
||||
break;
|
||||
}
|
||||
case ODK_UINT32: {
|
||||
uint32_t val;
|
||||
memcpy(&val, buf, sizeof(uint32_t));
|
||||
val = be32toh(val);
|
||||
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||
<< "\n";
|
||||
break;
|
||||
}
|
||||
case ODK_UINT64: {
|
||||
uint64_t val;
|
||||
memcpy(&val, buf, sizeof(uint64_t));
|
||||
val = be64toh(val);
|
||||
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||
<< "\n";
|
||||
break;
|
||||
}
|
||||
case ODK_SUBSTRING: {
|
||||
uint32_t off = 0;
|
||||
uint32_t len = 0;
|
||||
memcpy(&off, buf, sizeof(off));
|
||||
memcpy(&len, buf + sizeof(off), sizeof(len));
|
||||
std::cerr << field->name << ": (off=" << off << ", len=" << len << ")\n";
|
||||
break;
|
||||
}
|
||||
case ODK_DEVICEID:
|
||||
case ODK_HASH: {
|
||||
const size_t field_len = ODK_FieldLength(field->type);
|
||||
std::cerr << field->name << ": ";
|
||||
for (size_t i = 0; i < field_len; i++) {
|
||||
std::cerr << std::hex << std::setfill('0') << std::setw(2)
|
||||
<< static_cast<unsigned int>(buf[i]);
|
||||
}
|
||||
std::cerr << "\n";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
std::cerr << std::dec; // Return to normal.
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parameters:
|
||||
* [in] size_in: buffer size
|
||||
* [out] size_out: bytes processed
|
||||
*/
|
||||
OEMCryptoResult ODK_IterFields(ODK_FieldMode mode, uint8_t* buf,
|
||||
const size_t size_in, size_t* size_out,
|
||||
const std::vector<ODK_Field>& fields) {
|
||||
if (buf == nullptr || size_out == nullptr) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
size_t off = 0, off2 = 0;
|
||||
for (size_t i = 0; i < fields.size(); i++) {
|
||||
if (__builtin_add_overflow(off, ODK_FieldLength(fields[i].type), &off2) ||
|
||||
off2 > size_in) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
uintptr_t base = reinterpret_cast<uintptr_t>(buf);
|
||||
if (__builtin_add_overflow(base, off, &base)) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
uint8_t* const buf_off = buf + off;
|
||||
switch (mode) {
|
||||
case ODK_WRITE:
|
||||
ODK_WriteSingleField(buf_off, &fields[i]);
|
||||
break;
|
||||
case ODK_READ:
|
||||
ODK_ReadSingleField(buf_off, &fields[i]);
|
||||
break;
|
||||
case ODK_DUMP:
|
||||
ODK_DumpSingleField(buf_off, &fields[i]);
|
||||
break;
|
||||
default:
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
off = off2;
|
||||
}
|
||||
*size_out = off;
|
||||
if (*size_out > size_in) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
void ODK_ExpectEqualBuf(const void* s1, const void* s2, size_t n,
|
||||
const std::vector<ODK_Field>& fields) {
|
||||
if (memcmp(s1, s2, n) != 0) {
|
||||
const void* buffers[] = {s1, s2};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
char _tmp[] = "/tmp/fileXXXXXX";
|
||||
const int temp_fd = mkstemp(_tmp);
|
||||
if (temp_fd >= 0) {
|
||||
close(temp_fd);
|
||||
} else {
|
||||
std::cerr << "Failed to open temp file." << std::endl;
|
||||
break;
|
||||
}
|
||||
std::string tmp(_tmp);
|
||||
std::fstream out(tmp, std::ios::out | std::ios::binary);
|
||||
out.write(static_cast<const char*>(buffers[i]), n);
|
||||
out.close();
|
||||
std::cerr << "buffer " << i << " dumped to " << tmp << std::endl;
|
||||
size_t bytes_written;
|
||||
uint8_t* buf =
|
||||
const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(buffers[i]));
|
||||
ODK_IterFields(ODK_DUMP, buf, n, &bytes_written, fields);
|
||||
}
|
||||
FAIL();
|
||||
}
|
||||
}
|
||||
|
||||
void ODK_ResetOdkFields(std::vector<ODK_Field>* fields) {
|
||||
if (fields == nullptr) {
|
||||
return;
|
||||
}
|
||||
for (auto& field : *fields) {
|
||||
if (field.value != nullptr) {
|
||||
size_t size = ODK_AllocSize(field.type);
|
||||
memset(field.value, 0, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ODK_BuildMessageBuffer(ODK_CoreMessage* core_message,
|
||||
const std::vector<ODK_Field>& extra_fields,
|
||||
uint8_t*& buf, uint32_t* buf_size) {
|
||||
ASSERT_TRUE(core_message != nullptr);
|
||||
ASSERT_TRUE(buf_size != nullptr);
|
||||
std::vector<ODK_Field> total_fields = {
|
||||
{ODK_UINT32, &(core_message->message_type), "message_type"},
|
||||
{ODK_UINT32, &(core_message->message_length), "message_size"},
|
||||
{ODK_UINT16, &(core_message->nonce_values.api_minor_version),
|
||||
"api_minor_version"},
|
||||
{ODK_UINT16, &(core_message->nonce_values.api_major_version),
|
||||
"api_major_version"},
|
||||
{ODK_UINT32, &(core_message->nonce_values.nonce), "nonce"},
|
||||
{ODK_UINT32, &(core_message->nonce_values.session_id), "session_id"},
|
||||
};
|
||||
|
||||
uint32_t header_size = 0;
|
||||
for (auto& field : total_fields) {
|
||||
header_size += ODK_FieldLength(field.type);
|
||||
}
|
||||
|
||||
total_fields.insert(total_fields.end(), extra_fields.begin(),
|
||||
extra_fields.end());
|
||||
for (auto& field : total_fields) {
|
||||
*buf_size += ODK_FieldLength(field.type);
|
||||
}
|
||||
// update message_size
|
||||
*(reinterpret_cast<uint32_t*>(total_fields[1].value)) = *buf_size;
|
||||
|
||||
buf = new uint8_t[*buf_size]();
|
||||
size_t bytes_written = 0;
|
||||
// serialize ODK fields to message buffer
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_WRITE, buf, SIZE_MAX,
|
||||
&bytes_written, total_fields));
|
||||
EXPECT_EQ(bytes_written, *buf_size);
|
||||
}
|
||||
|
||||
} // namespace wvodk_test
|
||||
99
libwvdrmengine/oemcrypto/odk/test/odk_test_helper.h
Normal file
99
libwvdrmengine/oemcrypto/odk/test/odk_test_helper.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/* 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_TEST_ODK_TEST_HELPER_H_
|
||||
#define WIDEVINE_ODK_TEST_ODK_TEST_HELPER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "odk_structs.h"
|
||||
#include "odk_structs_priv.h"
|
||||
|
||||
namespace wvodk_test {
|
||||
|
||||
enum ODK_FieldType {
|
||||
ODK_UINT16,
|
||||
ODK_UINT32,
|
||||
ODK_UINT64,
|
||||
ODK_SUBSTRING,
|
||||
ODK_DEVICEID,
|
||||
ODK_HASH,
|
||||
ODK_NUMTYPES,
|
||||
};
|
||||
|
||||
enum ODK_FieldMode {
|
||||
ODK_READ,
|
||||
ODK_WRITE,
|
||||
ODK_DUMP,
|
||||
};
|
||||
|
||||
struct ODK_Field {
|
||||
ODK_FieldType type;
|
||||
void* value;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct ODK_LicenseResponseParams {
|
||||
ODK_CoreMessage core_message;
|
||||
bool initial_license_load;
|
||||
bool usage_entry_present;
|
||||
uint8_t request_hash[ODK_SHA256_HASH_SIZE];
|
||||
ODK_TimerLimits timer_limits;
|
||||
ODK_ClockValues clock_values;
|
||||
ODK_ParsedLicense parsed_license;
|
||||
std::vector<ODK_Field> extra_fields;
|
||||
};
|
||||
|
||||
struct ODK_RenewalResponseParams {
|
||||
ODK_CoreMessage core_message;
|
||||
uint64_t system_time;
|
||||
uint64_t playback_clock;
|
||||
uint64_t renewal_duration;
|
||||
ODK_TimerLimits timer_limits;
|
||||
ODK_ClockValues clock_values;
|
||||
uint64_t playback_timer;
|
||||
std::vector<ODK_Field> extra_fields;
|
||||
};
|
||||
|
||||
struct ODK_ProvisioningResponseParams {
|
||||
ODK_CoreMessage core_message;
|
||||
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX];
|
||||
uint32_t device_id_length;
|
||||
ODK_ParsedProvisioning parsed_provisioning;
|
||||
std::vector<ODK_Field> extra_fields;
|
||||
};
|
||||
|
||||
/* Default values in core_message for testing */
|
||||
void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message,
|
||||
uint32_t message_type);
|
||||
void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params);
|
||||
void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params);
|
||||
void ODK_SetDefaultProvisioningResponseParams(
|
||||
ODK_ProvisioningResponseParams* params);
|
||||
|
||||
size_t ODK_FieldLength(ODK_FieldType type);
|
||||
size_t ODK_AllocSize(ODK_FieldType type);
|
||||
|
||||
/* Copy ODK_Field to buf */
|
||||
OEMCryptoResult ODK_WriteSingleField(uint8_t* buf, const ODK_Field* field);
|
||||
/* Load buf to ODK_Field */
|
||||
OEMCryptoResult ODK_ReadSingleField(const uint8_t* buf, const ODK_Field* field);
|
||||
OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf, const ODK_Field* field);
|
||||
OEMCryptoResult ODK_IterFields(ODK_FieldMode mode, uint8_t* buf,
|
||||
const size_t size_in, size_t* size_out,
|
||||
const std::vector<ODK_Field>& fields);
|
||||
void ODK_ExpectEqualBuf(const void* s1, const void* s2, size_t n,
|
||||
const std::vector<ODK_Field>& fields);
|
||||
void ODK_ResetOdkFields(std::vector<ODK_Field>* fields);
|
||||
|
||||
/* Serialize core_message and extra_fields into buf */
|
||||
void ODK_BuildMessageBuffer(ODK_CoreMessage* core_message,
|
||||
const std::vector<ODK_Field>& extra_fields,
|
||||
uint8_t*& buf, uint32_t* buf_size);
|
||||
|
||||
} /* namespace wvodk_test */
|
||||
|
||||
#endif /* WIDEVINE_ODK_TEST_ODK_TEST_HELPER_H_ */
|
||||
Reference in New Issue
Block a user