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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user