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:
@@ -1,31 +1,61 @@
|
||||
/*
|
||||
* 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 <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <endian.h>
|
||||
#include "OEMCryptoCENCCommon.h"
|
||||
#include "core_message_deserialize.h"
|
||||
#include "core_message_serialize.h"
|
||||
#include "core_message_types.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "odk_structs.h"
|
||||
#include "odk_structs_priv.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
namespace {
|
||||
|
||||
#include "odk.h"
|
||||
#include "odk_test.h"
|
||||
#include "oec_util.h"
|
||||
using oemcrypto_core_message::ODK_LicenseRequest;
|
||||
using oemcrypto_core_message::ODK_ProvisioningRequest;
|
||||
using oemcrypto_core_message::ODK_RenewalRequest;
|
||||
|
||||
using namespace oec_util;
|
||||
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;
|
||||
|
||||
enum ODK_FieldType {
|
||||
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;
|
||||
};
|
||||
|
||||
size_t ODK_FieldLength(ODK_FieldType type) {
|
||||
switch (type) {
|
||||
@@ -130,6 +160,54 @@ OEMCryptoResult ODK_ReadSingleField(const uint8_t* const buf,
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_DumpSingleField(const uint8_t* const buf,
|
||||
const ODK_Field* const field) {
|
||||
if (!field || !field->value) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
switch (field->type) {
|
||||
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) << buf[i]
|
||||
<< "\n";
|
||||
}
|
||||
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
|
||||
@@ -137,7 +215,7 @@ OEMCryptoResult ODK_ReadSingleField(const uint8_t* const buf,
|
||||
*/
|
||||
OEMCryptoResult ODK_IterFields(ODK_FieldMode mode, uint8_t* const buf,
|
||||
const size_t size_in, size_t* size_out,
|
||||
std::vector<ODK_Field>& fields) {
|
||||
const std::vector<ODK_Field>& fields) {
|
||||
if (!buf || !size_out) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
@@ -156,6 +234,8 @@ OEMCryptoResult ODK_IterFields(ODK_FieldMode mode, uint8_t* const buf,
|
||||
ODK_WriteSingleField(buf_off, &fields[i]);
|
||||
} else if (mode == ODK_READ) {
|
||||
ODK_ReadSingleField(buf_off, &fields[i]);
|
||||
} else if (mode == ODK_DUMP) {
|
||||
ODK_DumpSingleField(buf_off, &fields[i]);
|
||||
} else {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
@@ -168,31 +248,28 @@ OEMCryptoResult ODK_IterFields(ODK_FieldMode mode, uint8_t* const buf,
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_ReadFields(const uint8_t* const buf, const size_t size_in,
|
||||
size_t* size_out,
|
||||
std::vector<ODK_Field>& fields) {
|
||||
return ODK_IterFields(ODK_READ, const_cast<uint8_t*>(buf), size_in, size_out,
|
||||
fields);
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_WriteFields(uint8_t* const buf, const size_t size_in,
|
||||
size_t* size_out,
|
||||
std::vector<ODK_Field>& fields) {
|
||||
return ODK_IterFields(ODK_WRITE, buf, size_in, size_out, fields);
|
||||
}
|
||||
|
||||
void expect_eq_buf(const void* s1, const void* s2, size_t n) {
|
||||
void expect_eq_buf(const void* s1, const void* s2, size_t n,
|
||||
const std::vector<ODK_Field>& fields) {
|
||||
if (memcmp(s1, s2, n)) {
|
||||
const void* buffers[] = {s1, s2};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
char _tmp[] = "/tmp/fileXXXXXX";
|
||||
mkstemp(_tmp);
|
||||
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((char*)buffers[i], n);
|
||||
out.write(static_cast<const char*>(buffers[i]), n);
|
||||
out.close();
|
||||
std:
|
||||
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();
|
||||
}
|
||||
@@ -200,7 +277,7 @@ void expect_eq_buf(const void* s1, const void* s2, size_t n) {
|
||||
|
||||
template <typename T, typename F, typename G>
|
||||
void ValidateRequest(uint32_t message_type,
|
||||
std::vector<ODK_Field>& extra_fields,
|
||||
const std::vector<ODK_Field>& extra_fields,
|
||||
const F& odk_prepare_func, const G& kdo_parse_func) {
|
||||
uint32_t message_size = 0;
|
||||
uint32_t api_version = 16;
|
||||
@@ -208,9 +285,11 @@ void ValidateRequest(uint32_t message_type,
|
||||
uint32_t session_id = 0xcafebabe;
|
||||
ODK_NonceValues nonce_values{api_version, nonce, session_id};
|
||||
std::vector<ODK_Field> total_fields = {
|
||||
{ODK_UINT32, &message_type}, {ODK_UINT32, &message_size},
|
||||
{ODK_UINT32, &api_version}, {ODK_UINT32, &nonce},
|
||||
{ODK_UINT32, &session_id},
|
||||
{ODK_UINT32, &message_type, "message_type"},
|
||||
{ODK_UINT32, &message_size, "message_size"},
|
||||
{ODK_UINT32, &api_version, "api_version"},
|
||||
{ODK_UINT32, &nonce, "nonce"},
|
||||
{ODK_UINT32, &session_id, "session_id"},
|
||||
};
|
||||
|
||||
total_fields.insert(total_fields.end(), extra_fields.begin(),
|
||||
@@ -231,7 +310,7 @@ void ValidateRequest(uint32_t message_type,
|
||||
&bytes_written, total_fields));
|
||||
EXPECT_EQ(bytes_written, message_size);
|
||||
|
||||
expect_eq_buf(buf, buf2, message_size);
|
||||
EXPECT_NO_FATAL_FAILURE(expect_eq_buf(buf, buf2, message_size, total_fields));
|
||||
|
||||
// odk kdo roundtrip
|
||||
T t = {};
|
||||
@@ -244,7 +323,7 @@ void ValidateRequest(uint32_t message_type,
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
odk_prepare_func(buf2, &bytes_written, &nonce_values));
|
||||
EXPECT_EQ(bytes_written, message_size);
|
||||
expect_eq_buf(buf, buf2, message_size);
|
||||
EXPECT_NO_FATAL_FAILURE(expect_eq_buf(buf, buf2, message_size, total_fields));
|
||||
|
||||
delete[] buf;
|
||||
delete[] buf2;
|
||||
@@ -258,16 +337,18 @@ void ValidateRequest(uint32_t message_type,
|
||||
*/
|
||||
template <typename T, typename F, typename G>
|
||||
void ValidateResponse(uint32_t message_type,
|
||||
std::vector<ODK_Field>& extra_fields,
|
||||
const std::vector<ODK_Field>& extra_fields,
|
||||
const F& odk_parse_func, const G& kdo_prepare_func) {
|
||||
uint32_t message_size = 0;
|
||||
uint32_t api_version = 16;
|
||||
uint32_t nonce = 0xdeadbeef;
|
||||
uint32_t session_id = 0xcafebabe;
|
||||
std::vector<ODK_Field> total_fields = {
|
||||
{ODK_UINT32, &message_type}, {ODK_UINT32, &message_size},
|
||||
{ODK_UINT32, &api_version}, {ODK_UINT32, &nonce},
|
||||
{ODK_UINT32, &session_id},
|
||||
{ODK_UINT32, &message_type, "message_type"},
|
||||
{ODK_UINT32, &message_size, "message_size"},
|
||||
{ODK_UINT32, &api_version, "api_version"},
|
||||
{ODK_UINT32, &nonce, "nonce"},
|
||||
{ODK_UINT32, &session_id, "session_id"},
|
||||
};
|
||||
|
||||
uint32_t header_size = 0;
|
||||
@@ -311,7 +392,8 @@ void ValidateResponse(uint32_t message_type,
|
||||
EXPECT_TRUE(kdo_prepare_func(t, &oemcrypto_core_message));
|
||||
EXPECT_EQ(bytes_written, message_size);
|
||||
|
||||
expect_eq_buf(buf, oemcrypto_core_message.data(), message_size);
|
||||
EXPECT_NO_FATAL_FAILURE(expect_eq_buf(buf, oemcrypto_core_message.data(),
|
||||
message_size, total_fields));
|
||||
delete[] buf;
|
||||
delete[] zero;
|
||||
}
|
||||
@@ -321,9 +403,10 @@ TEST(OdkTest, SerializeFields) {
|
||||
uint64_t y[] = {3ll << 32, 4ll << 32, 5ll << 32};
|
||||
OEMCrypto_Substring s = {.offset = 6, .length = 7};
|
||||
std::vector<ODK_Field> fields = {
|
||||
{ODK_UINT32, &x[0]}, {ODK_UINT32, &x[1]}, {ODK_UINT32, &x[2]},
|
||||
{ODK_UINT64, &y[0]}, {ODK_UINT64, &y[1]}, {ODK_UINT64, &y[2]},
|
||||
{ODK_SUBSTRING, &s},
|
||||
{ODK_UINT32, &x[0], "x[0]"}, {ODK_UINT32, &x[1], "x[1]"},
|
||||
{ODK_UINT32, &x[2], "x[2]"}, {ODK_UINT64, &y[0], "y[0]"},
|
||||
{ODK_UINT64, &y[1], "y[1]"}, {ODK_UINT64, &y[2], "y[2]"},
|
||||
{ODK_SUBSTRING, &s, "s"},
|
||||
};
|
||||
uint8_t buf[1024] = {0};
|
||||
uint8_t buf2[1024] = {0};
|
||||
@@ -332,7 +415,7 @@ TEST(OdkTest, SerializeFields) {
|
||||
ODK_IterFields(ODK_READ, buf, bytes_read, &bytes_written, fields);
|
||||
ODK_IterFields(ODK_WRITE, buf2, SIZE_MAX, &bytes_read, fields);
|
||||
|
||||
expect_eq_buf(buf, buf2, bytes_read);
|
||||
EXPECT_NO_FATAL_FAILURE(expect_eq_buf(buf, buf2, bytes_read, fields));
|
||||
}
|
||||
|
||||
TEST(OdkTest, SerializeFieldsStress) {
|
||||
@@ -343,8 +426,8 @@ TEST(OdkTest, SerializeFieldsStress) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
fields[i].type = static_cast<ODK_FieldType>(std::rand() %
|
||||
static_cast<int>(ODK_NUMTYPES));
|
||||
size_t field_size = ODK_AllocSize(fields[i].type);
|
||||
fields[i].value = malloc(ODK_AllocSize(fields[i].type));
|
||||
fields[i].name = "stress";
|
||||
total_size += ODK_FieldLength(fields[i].type);
|
||||
}
|
||||
|
||||
@@ -360,7 +443,7 @@ TEST(OdkTest, SerializeFieldsStress) {
|
||||
ODK_IterFields(ODK_WRITE, buf2, total_size, &bytes_written, fields);
|
||||
EXPECT_EQ(bytes_written, total_size);
|
||||
|
||||
expect_eq_buf(buf, buf2, total_size);
|
||||
EXPECT_NO_FATAL_FAILURE(expect_eq_buf(buf, buf2, total_size, fields));
|
||||
|
||||
// cleanup
|
||||
for (int i = 0; i < n; i++) {
|
||||
@@ -376,17 +459,20 @@ TEST(OdkTest, LicenseRequest) {
|
||||
ODK_NonceValues* nonce_values) {
|
||||
return ODK_PrepareCoreLicenseRequest(buf, SIZE_MAX, size, nonce_values);
|
||||
};
|
||||
auto kdo_parse_func = ParseLicenseRequest;
|
||||
auto kdo_parse_func = CoreLicenseRequestFromMessage;
|
||||
ValidateRequest<ODK_LicenseRequest>(ODK_License_Request_Type, empty,
|
||||
odk_prepare_func, kdo_parse_func);
|
||||
}
|
||||
|
||||
TEST(OdkTest, RenewalRequest) {
|
||||
uint64_t system_time_seconds = 0xBADDCAFE000FF1CE;
|
||||
const uint64_t system_time_seconds = 0xBADDCAFE000FF1CE;
|
||||
uint64_t playback_time = 0xCAFE00000000;
|
||||
const uint64_t playback_start = system_time_seconds - playback_time;
|
||||
std::vector<ODK_Field> extra_fields = {
|
||||
{ODK_UINT64, &system_time_seconds},
|
||||
{ODK_UINT64, &playback_time, "playback_time"},
|
||||
};
|
||||
ODK_ClockValues clock_values = {0};
|
||||
clock_values.time_of_first_decrypt = playback_start;
|
||||
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
|
||||
const ODK_NonceValues* nonce_values) {
|
||||
return ODK_PrepareCoreRenewalRequest(buf, SIZE_MAX, size, nonce_values,
|
||||
@@ -394,9 +480,10 @@ TEST(OdkTest, RenewalRequest) {
|
||||
};
|
||||
auto kdo_parse_func = [&](const std::string& oemcrypto_core_message,
|
||||
ODK_RenewalRequest* core_renewal_request) {
|
||||
bool ok = ParseRenewalRequest(oemcrypto_core_message, core_renewal_request);
|
||||
bool ok = CoreRenewalRequestFromMessage(oemcrypto_core_message,
|
||||
core_renewal_request);
|
||||
if (ok) {
|
||||
system_time_seconds = core_renewal_request->playback_time;
|
||||
playback_time = core_renewal_request->playback_time_seconds;
|
||||
}
|
||||
return ok;
|
||||
};
|
||||
@@ -405,12 +492,12 @@ TEST(OdkTest, RenewalRequest) {
|
||||
}
|
||||
|
||||
TEST(OdkTest, ProvisionRequest) {
|
||||
uint32_t device_id_length = DEVICE_ID_MAX / 2;
|
||||
uint8_t device_id[DEVICE_ID_MAX] = {0};
|
||||
uint32_t device_id_length = ODK_DEVICE_ID_LEN_MAX / 2;
|
||||
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||
memset(device_id, 0xff, device_id_length);
|
||||
std::vector<ODK_Field> extra_fields = {
|
||||
{ODK_UINT32, &device_id_length},
|
||||
{ODK_DEVICEID, device_id},
|
||||
{ODK_UINT32, &device_id_length, "device_id_length"},
|
||||
{ODK_DEVICEID, device_id, "device_id"},
|
||||
};
|
||||
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
|
||||
const ODK_NonceValues* nonce_values) {
|
||||
@@ -420,8 +507,8 @@ TEST(OdkTest, ProvisionRequest) {
|
||||
auto kdo_parse_func =
|
||||
[&](const std::string& oemcrypto_core_message,
|
||||
ODK_ProvisioningRequest* core_provisioning_request) {
|
||||
bool ok = ParseProvisioningRequest(oemcrypto_core_message,
|
||||
core_provisioning_request);
|
||||
bool ok = CoreProvisioningRequestFromMessage(oemcrypto_core_message,
|
||||
core_provisioning_request);
|
||||
if (ok) {
|
||||
const std::string& device_id_str =
|
||||
core_provisioning_request->device_id;
|
||||
@@ -482,48 +569,58 @@ TEST(OdkTest, LicenseResponse) {
|
||||
},
|
||||
};
|
||||
|
||||
uint32_t message_type = ODK_License_Response_Type;
|
||||
std::vector<ODK_Field> extra_fields = {
|
||||
{ODK_SUBSTRING, &parsed_license.enc_mac_keys_iv},
|
||||
{ODK_SUBSTRING, &parsed_license.enc_mac_keys},
|
||||
{ODK_SUBSTRING, &parsed_license.pst},
|
||||
{ODK_SUBSTRING, &parsed_license.srm_restriction_data},
|
||||
{ODK_UINT32, &parsed_license.license_type},
|
||||
{ODK_UINT32, &parsed_license.nonce_required},
|
||||
{ODK_UINT32, &parsed_license.timer_limits.soft_expiry},
|
||||
{ODK_SUBSTRING, &parsed_license.enc_mac_keys_iv, ".enc_mac_keys_iv"},
|
||||
{ODK_SUBSTRING, &parsed_license.enc_mac_keys, ".enc_mac_keys"},
|
||||
{ODK_SUBSTRING, &parsed_license.pst, ".pst"},
|
||||
{ODK_SUBSTRING, &parsed_license.srm_restriction_data,
|
||||
".srm_restriction_data"},
|
||||
{ODK_UINT32, &parsed_license.license_type, ".license_type"},
|
||||
{ODK_UINT32, &parsed_license.nonce_required, ".nonce_required"},
|
||||
{ODK_UINT32, &parsed_license.timer_limits.soft_expiry, ".soft_expiry"},
|
||||
{ODK_UINT64, &parsed_license.timer_limits.earliest_playback_start_seconds,
|
||||
".earliest_playback_start_seconds"},
|
||||
{ODK_UINT64, &parsed_license.timer_limits.latest_playback_start_seconds,
|
||||
".latest_playback_start_seconds"},
|
||||
{ODK_UINT64,
|
||||
&parsed_license.timer_limits.earliest_playback_start_seconds},
|
||||
{ODK_UINT64, &parsed_license.timer_limits.latest_playback_start_seconds},
|
||||
&parsed_license.timer_limits.initial_playback_duration_seconds,
|
||||
".initial_playback_duration_seconds"},
|
||||
{ODK_UINT64,
|
||||
&parsed_license.timer_limits.initial_playback_duration_seconds},
|
||||
{ODK_UINT64,
|
||||
&parsed_license.timer_limits.renewal_playback_duration_seconds},
|
||||
{ODK_UINT64, &parsed_license.timer_limits.license_duration_seconds},
|
||||
{ODK_HASH, &parsed_license.request_hash},
|
||||
{ODK_UINT32, &parsed_license.key_array_length},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_id},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_data_iv},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_data},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_control_iv},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_control},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[1].key_id},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[1].key_data_iv},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[1].key_data},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[1].key_control_iv},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[1].key_control},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_id},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_data_iv},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_data},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_control_iv},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_control},
|
||||
&parsed_license.timer_limits.renewal_playback_duration_seconds,
|
||||
".renewal_playback_duration_seconds"},
|
||||
{ODK_UINT64, &parsed_license.timer_limits.license_duration_seconds,
|
||||
".license_duration_seconds"},
|
||||
{ODK_HASH, &parsed_license.request_hash, ".request_hash"},
|
||||
{ODK_UINT32, &parsed_license.key_array_length, ".key_array_length"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_id, ".key_id"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_data_iv, ".key_data_iv"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_data, ".key_data"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_control_iv,
|
||||
".key_control_iv"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[0].key_control, ".key_control"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[1].key_id, ".key_id"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[1].key_data_iv, ".key_data_iv"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[1].key_data, ".key_data"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[1].key_control_iv,
|
||||
".key_control_iv"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[1].key_control, ".key_control"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_id, ".key_id"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_data_iv, ".key_data_iv"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_data, ".key_data"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_control_iv,
|
||||
".key_control_iv"},
|
||||
{ODK_SUBSTRING, &parsed_license.key_array[2].key_control, ".key_control"},
|
||||
};
|
||||
|
||||
uint8_t request_hash[ODK_SHA256_HASH_SIZE] = {};
|
||||
memcpy(request_hash, parsed_license.request_hash, ODK_SHA256_HASH_SIZE);
|
||||
auto odk_parse_func = [&](const uint8_t* buf, size_t size,
|
||||
ODK_NonceValues* nonce_values) {
|
||||
return ODK_ParseLicense(buf, size + 128, size, 1, 0, request_hash, nullptr,
|
||||
nullptr, nonce_values, &parsed_license);
|
||||
ODK_TimerLimits timer_limits;
|
||||
ODK_ClockValues clock_values;
|
||||
return ODK_ParseLicense(buf, size + 128, size, true, false, request_hash,
|
||||
&timer_limits, &clock_values, nonce_values,
|
||||
&parsed_license);
|
||||
};
|
||||
auto kdo_prepare_func = [&](const ODK_LicenseRequest& core_request,
|
||||
std::string* oemcrypto_core_message) {
|
||||
@@ -540,7 +637,7 @@ TEST(OdkTest, RenewalResponse) {
|
||||
uint64_t playback_timer = 12;
|
||||
uint64_t message_playback_clock = 10;
|
||||
std::vector<ODK_Field> extra_fields = {
|
||||
{ODK_UINT64, &message_playback_clock},
|
||||
{ODK_UINT64, &message_playback_clock, "message_playback_clock"},
|
||||
};
|
||||
|
||||
ODK_TimerLimits timer_limits = {
|
||||
@@ -556,6 +653,7 @@ TEST(OdkTest, RenewalResponse) {
|
||||
.time_of_license_signed = 0,
|
||||
.time_of_first_decrypt = system_time - playback_clock,
|
||||
.time_of_last_decrypt = 0,
|
||||
.time_of_renewal_request = message_playback_clock,
|
||||
.time_when_timer_expires = system_time + playback_timer,
|
||||
.timer_status = 0,
|
||||
.status = kUnused,
|
||||
@@ -579,7 +677,7 @@ TEST(OdkTest, RenewalResponse) {
|
||||
};
|
||||
auto kdo_prepare_func = [&](ODK_RenewalRequest& core_request,
|
||||
std::string* oemcrypto_core_message) {
|
||||
core_request.playback_time = message_playback_clock;
|
||||
core_request.playback_time_seconds = message_playback_clock;
|
||||
return CreateCoreRenewalResponse(core_request, oemcrypto_core_message);
|
||||
};
|
||||
ValidateResponse<ODK_RenewalRequest>(ODK_Renewal_Response_Type, extra_fields,
|
||||
@@ -587,8 +685,8 @@ TEST(OdkTest, RenewalResponse) {
|
||||
}
|
||||
|
||||
TEST(OdkTest, ProvisionResponse) {
|
||||
uint32_t device_id_length = DEVICE_ID_MAX / 2;
|
||||
uint8_t device_id[DEVICE_ID_MAX] = {0};
|
||||
uint32_t device_id_length = ODK_DEVICE_ID_LEN_MAX / 2;
|
||||
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||
memset(device_id, 0xff, device_id_length);
|
||||
|
||||
ODK_ParsedProvisioning parsed_response = {
|
||||
@@ -598,18 +696,20 @@ TEST(OdkTest, ProvisionResponse) {
|
||||
};
|
||||
|
||||
std::vector<ODK_Field> extra_fields = {
|
||||
{ODK_UINT32, &device_id_length},
|
||||
{ODK_DEVICEID, device_id},
|
||||
{ODK_UINT32, &parsed_response.key_type},
|
||||
{ODK_SUBSTRING, &parsed_response.enc_private_key},
|
||||
{ODK_SUBSTRING, &parsed_response.enc_private_key_iv},
|
||||
{ODK_SUBSTRING, &parsed_response.encrypted_message_key},
|
||||
{ODK_UINT32, &device_id_length, "device_id_length"},
|
||||
{ODK_DEVICEID, device_id, "device_id"},
|
||||
{ODK_UINT32, &parsed_response.key_type, "key_type"},
|
||||
{ODK_SUBSTRING, &parsed_response.enc_private_key, "enc_private_key"},
|
||||
{ODK_SUBSTRING, &parsed_response.enc_private_key_iv,
|
||||
"enc_private_key_iv"},
|
||||
{ODK_SUBSTRING, &parsed_response.encrypted_message_key,
|
||||
"encrypted_message_key"},
|
||||
};
|
||||
|
||||
auto odk_parse_func = [&](const uint8_t* buf, size_t size,
|
||||
ODK_NonceValues* nonce_values) {
|
||||
// restore device id because it is not part of parsed_response
|
||||
device_id_length = DEVICE_ID_MAX / 2;
|
||||
device_id_length = ODK_DEVICE_ID_LEN_MAX / 2;
|
||||
memset(device_id, 0xff, device_id_length);
|
||||
OEMCryptoResult err =
|
||||
ODK_ParseProvisioning(buf, size + 16, size, nonce_values, device_id,
|
||||
@@ -671,7 +771,6 @@ TEST(OdkSizeTest, ProvisioningRequest) {
|
||||
uint32_t api_version = 0;
|
||||
uint32_t nonce = 0;
|
||||
uint32_t session_id = 0;
|
||||
uint8_t* device_id = nullptr;
|
||||
uint32_t device_id_length = 0;
|
||||
ODK_NonceValues nonce_values{api_version, nonce, session_id};
|
||||
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||
@@ -682,3 +781,5 @@ TEST(OdkSizeTest, ProvisioningRequest) {
|
||||
size_t minimum_message_size = 5 * 4;
|
||||
EXPECT_GE(core_message_length, minimum_message_size);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user