odk directory copied from wvgerrit. branch oemcrypto-v16 commit 0c9a7dc Bug: 140758896 Test: odk_test Change-Id: I0c631f771b794468a63e4395f6b9c3b60a1dfd4f
210 lines
6.9 KiB
C++
210 lines
6.9 KiB
C++
/*
|
|
* 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 "oec_util.h"
|
|
|
|
#include <stdint.h>
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
#include "odk_overflow.h"
|
|
#include "odk_serialize.h"
|
|
#include "odk_structs.h"
|
|
#include "odk_structs_priv.h"
|
|
#include "oemcrypto_types.h"
|
|
#include "serialization_base.h"
|
|
|
|
using namespace oec_util;
|
|
|
|
namespace oec_util {
|
|
|
|
namespace {
|
|
|
|
/* @ private functions */
|
|
|
|
const int CURRENT_OEC_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 string& oemcrypto_core_message,
|
|
S* core_request, T* prepared, const U unpacker) {
|
|
if (!core_request) {
|
|
return false;
|
|
}
|
|
|
|
const uint8_t* buf =
|
|
reinterpret_cast<const uint8_t*>(oemcrypto_core_message.c_str());
|
|
size_t buf_length = oemcrypto_core_message.size();
|
|
|
|
Message* msg = NULL;
|
|
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 == CURRENT_OEC_VERSION;
|
|
}
|
|
|
|
/**
|
|
* 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,
|
|
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;
|
|
|
|
uint8_t buf[2048] = {0};
|
|
Message* msg = NULL;
|
|
AllocateMessage(&msg, message_block);
|
|
InitMessage(msg, buf, sizeof(buf));
|
|
packer(msg, &response);
|
|
if (!ValidMessage(msg)) {
|
|
return false;
|
|
}
|
|
|
|
uint32_t message_length = GetSize(msg);
|
|
InitMessage(msg, buf + sizeof(header->message_type),
|
|
sizeof(header->message_length));
|
|
Pack_uint32_t(msg, &message_length);
|
|
oemcrypto_core_message->assign(reinterpret_cast<const char*>(buf),
|
|
message_length);
|
|
return true;
|
|
}
|
|
|
|
bool CopyDeviceId(ODK_ProvisioningResponse& dest,
|
|
const ODK_ProvisioningRequest& src) {
|
|
auto& core_provisioning = dest.core_provisioning;
|
|
const 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
|
|
|
|
// @ public parse request (deserializer) functions
|
|
|
|
bool ParseLicenseRequest(const 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 ParseRenewalRequest(const 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 = prepared_renewal.playback_time;
|
|
return true;
|
|
}
|
|
|
|
bool ParseProvisioningRequest(
|
|
const 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;
|
|
}
|
|
|
|
// @ public create response functions
|
|
|
|
bool CreateCoreLicenseResponse(const ODK_ParsedLicense& parsed_lic,
|
|
const ODK_LicenseRequest& core_request,
|
|
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,
|
|
string* oemcrypto_core_message) {
|
|
ODK_RenewalMessage renewal{{}, core_request.playback_time};
|
|
renewal.playback_time = core_request.playback_time;
|
|
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,
|
|
string* oemcrypto_core_message) {
|
|
ODK_ProvisioningResponse prov_response{
|
|
{}, const_cast<ODK_ParsedProvisioning*>(&parsed_prov)};
|
|
if (!CopyDeviceId(prov_response, core_request)) {
|
|
return false;
|
|
}
|
|
|
|
return CreateResponse(ODK_Provisioning_Response_Type, core_request,
|
|
oemcrypto_core_message, prov_response,
|
|
Pack_ODK_ProvisioningResponse);
|
|
}
|
|
|
|
} // namespace oec_util
|