ODK: Address review comments

Merge of http://go/wvgerrit/95666

Mostly fixing coding styles and a few vulnerability check.
Updating tests according to the fix.

Bug: 150614088
Bug: 150881959
Test: Ran cdm and odk unit tests
Change-Id: I109a96ee8ded089d59ab49c2f94b6833c932fd1e
This commit is contained in:
Cong Lin
2020-03-12 18:25:46 -07:00
parent fae5d3f7a9
commit 5a6a2075f5
8 changed files with 129 additions and 119 deletions

View File

@@ -20,7 +20,7 @@
#include "odk_structs.h"
#include "odk_structs_priv.h"
typedef std::function<size_t(const uint8_t*, uint8_t*, size_t, size_t)>
typedef std::function<void(const uint8_t*, uint8_t*, size_t, size_t)>
roundtrip_fun;
using oemcrypto_core_message::ODK_LicenseRequest;
@@ -74,35 +74,32 @@ static OEMCryptoResult odk_serialize_ProvisioningRequest(
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 clock_value_size) -> size_t {
size_t clock_value_size) -> void {
if (size <= clock_value_size) {
return 0;
return;
}
// 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;
return;
}
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;
if (OEMCrypto_SUCCESS != err) {
return;
}
assert(0 == memcmp(in + clock_value_size, out, size));
};
return roundtrip;
}
// @ odk deserialize; kdo serialize
namespace {
struct ODK_Common_Args {
uint16_t api_minor_version;
uint16_t api_major_version;
uint32_t nonce;
uint32_t session_id;
};
struct ODK_ParseLicense_Args {
ODK_Common_Args common;
ODK_NonceValues nonce_values;
uint8_t initial_license_load;
uint8_t usage_entry_present;
uint8_t request_hash[32];
@@ -110,22 +107,21 @@ struct ODK_ParseLicense_Args {
ODK_ClockValues clock_values;
};
struct ODK_ParseRenewal_Args {
ODK_Common_Args common;
ODK_NonceValues nonce_values;
uint64_t system_time;
ODK_TimerLimits timer_limits;
ODK_ClockValues clock_values;
};
struct ODK_ParseProvisioning_Args {
ODK_Common_Args common;
ODK_NonceValues nonce_values;
size_t device_id_length;
uint8_t device_id[64];
};
} // namespace
uint8_t convert_byte_to_valid_boolean(const bool* in) {
uint8_t boolean_value;
memcpy(&boolean_value, in, 1);
return boolean_value % 2;
bool convert_byte_to_valid_boolean(const bool* in) {
const int value = *reinterpret_cast<const int*>(in);
return value != 0;
}
static OEMCryptoResult odk_deserialize_LicenseResponse(
@@ -142,10 +138,10 @@ static OEMCryptoResult odk_deserialize_LicenseResponse(
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_minor_version,
common.api_major_version, common.nonce,
common.session_id};
const auto& nonce_values = args->nonce_values;
ODK_LicenseRequest core_request{nonce_values.api_minor_version,
nonce_values.api_major_version,
nonce_values.nonce, nonce_values.session_id};
std::string core_request_sha_256(
reinterpret_cast<const char*>(args->request_hash), 32);
return CreateCoreLicenseResponse(
@@ -184,10 +180,10 @@ 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_minor_version,
common.api_major_version, common.nonce,
common.session_id, renewal_msg.playback_time};
const auto& nonce_values = args->nonce_values;
ODK_RenewalRequest core_request{
nonce_values.api_minor_version, nonce_values.api_major_version,
nonce_values.nonce, nonce_values.session_id, renewal_msg.playback_time};
return CreateCoreRenewalResponse(
core_request, args->timer_limits.initial_renewal_duration_seconds,
oemcrypto_core_message);
@@ -204,11 +200,13 @@ 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));
const auto& nonce_values = args->nonce_values;
if (args->device_id_length > sizeof(args->device_id)) {
return false;
}
ODK_ProvisioningRequest core_request{
common.api_minor_version, common.api_major_version, common.nonce,
common.session_id,
nonce_values.api_minor_version, nonce_values.api_major_version,
nonce_values.nonce, nonce_values.session_id,
std::string(reinterpret_cast<const char*>(args->device_id),
args->device_id_length)};
return CreateCoreProvisioningResponse(parsed_prov, core_request,
@@ -227,35 +225,60 @@ static bool kdo_serialize_ProvisioningResponse(
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 args_size) -> size_t {
size_t args_size) -> void {
// Input byte array format: [function arguments][data to parse]
if (args_size > size) {
return 0;
return;
}
T t = {};
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, args_size);
const auto& common = args->common;
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;
}
args->nonce_values.api_major_version = ODK_MAJOR_VERSION;
args->nonce_values.api_minor_version = ODK_MINOR_VERSION;
/*
* Input random bytes from autofuzz are interpreted by this script as
* [function args][data to parse]. Odk deserialize functions
* expect the nonce values in function args to match with those
* in data to parse which is not possible with random bytes.
* We follow two pass approach.
*
* 1st pass - We copy random bytes into struct t and call kdo serialize
* with function args which will create oemcrypto core message using nonce
* from function args. Now we have a valid oemcrypto core message which is
* formed using nonce_values from function args which acts as input bytes
* for 2nd pass
*
* 2nd pass - oemcrypto core message from 1st pass guarantees that
* nonce_values in [function args] and core message match. we call
* odk_deserialize using nonce from function args and oemcrypto core message
* from 1st pass. Then we call kdo function which generates oemcrypto core
* message2, which should be equal to oemcrypto_core_message which was input
* to 2nd pass
*/
// TODO(ellurubharath): Use structure aware fuzzing
// 1st pass
memcpy(&t, buf, sizeof(t));
std::string oemcrypto_core_message;
if (!kdo_fun(args, t, &oemcrypto_core_message)) {
return 0;
return;
}
assert(oemcrypto_core_message.size() <= size);
memcpy(out, oemcrypto_core_message.data(), oemcrypto_core_message.size());
return oemcrypto_core_message.size();
// 2nd pass
ODK_NonceValues nonce_values = args->nonce_values;
OEMCryptoResult result =
odk_fun(reinterpret_cast<const uint8_t*>(oemcrypto_core_message.data()),
oemcrypto_core_message.size(), args, &nonce_values, &t);
if (result != OEMCrypto_SUCCESS) {
return;
}
std::string oemcrypto_core_message2;
if (!kdo_fun(args, t, &oemcrypto_core_message2)) {
return;
}
assert(oemcrypto_core_message == oemcrypto_core_message2);
};
return roundtrip;
}
@@ -265,8 +288,7 @@ static void verify_roundtrip(const uint8_t* in, size_t size,
roundtrip_fun roundtrip, size_t args_size) {
std::vector<uint8_t> _out(size);
auto out = _out.data();
size_t n = roundtrip(in, out, size, args_size);
assert(n <= size && 0 == memcmp(in + args_size, out, n));
roundtrip(in, out, size, args_size);
}
// Entry point for fuzzer, data is random bytes program gets from autofuzzer