Correctly parse v18.0 provisioning requests
The previous code fixed a backwards compatibility error for v18 provisioning requests being parsed by a v17 or older server. This bumped the minor version number to v18.1. v17 servers are still expected to fail when trying to parse v18.0 provisioning requests, and v18.1 requests will pass. However, it did not correctly account for existing v18.0 requests on v18.1+ servers. v18.0 messages were naively detected by a failure to parse, and the parse function was not run again. This left the resulting nonce and session_id values uninitialized. This CL fixes that by explicitly handling the v18.0 and v18.1+ cases, ensuring that the parse function succeeds and all relevant information is copied over. Furthermore, the unit test that was meant to catch this edge case has been improved to validate the resulting parsed message. All code changes affect the server. This does not affect the client code eg OEMCrypto PiperOrigin-RevId: 523714529 Merged from https://widevine-internal-review.googlesource.com/170110 Change-Id: I21911c4bb4304de2d93f092f356402bbd4240874
This commit is contained in:
committed by
Robert Shih
parent
c6e7c70a6b
commit
a2a27c44ef
@@ -162,44 +162,26 @@ bool CoreRenewalRequestFromMessage(const std::string& oemcrypto_core_message,
|
||||
bool CoreProvisioningRequestFromMessage(
|
||||
const std::string& oemcrypto_core_message,
|
||||
ODK_ProvisioningRequest* core_provisioning_request) {
|
||||
// We can't tell if V18 format or older. Need to partially parse in order
|
||||
// to get the nonce values, which will tell us.
|
||||
// Need to partially parse in order to get the nonce values, which will tell
|
||||
// us the major/minor version
|
||||
ODK_NonceValues nonce;
|
||||
if (!GetNonceFromMessage(oemcrypto_core_message, &nonce)) return false;
|
||||
|
||||
if (nonce.api_major_version == 18) {
|
||||
// Proceed with V18 types
|
||||
const auto unpacker = Unpack_ODK_PreparedProvisioningRequest;
|
||||
// Use special case unpacker for v18.0
|
||||
const auto unpacker = nonce.api_minor_version == 0
|
||||
? Unpack_ODK_PreparedProvisioningRequestV180
|
||||
: Unpack_ODK_PreparedProvisioningRequest;
|
||||
ODK_PreparedProvisioningRequest prepared_provision = {};
|
||||
|
||||
if (!ParseRequest(ODK_Provisioning_Request_Type, oemcrypto_core_message,
|
||||
core_provisioning_request, &prepared_provision,
|
||||
unpacker)) {
|
||||
// check for edge case: initial v18 message which is 4 bytes smaller and
|
||||
// has 0's in the message counter struct
|
||||
const uint8_t* buf =
|
||||
reinterpret_cast<const uint8_t*>(oemcrypto_core_message.c_str());
|
||||
const size_t buf_length = oemcrypto_core_message.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(buf_length + 4 == ODK_PROVISIONING_REQUEST_SIZE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Expected zero padding. Size is the new ODK Provisioning Request (core
|
||||
// message + const uint32_t + the rest) without the core message and const
|
||||
// uint32_t.
|
||||
uint8_t zeros[ODK_PROVISIONING_REQUEST_SIZE - 4 - ODK_CORE_MESSAGE_SIZE] =
|
||||
{0};
|
||||
|
||||
// Compare zeros against the old Provisioning Request (core message + the
|
||||
// rest).
|
||||
if (memcmp(zeros, buf + ODK_CORE_MESSAGE_SIZE, sizeof(zeros)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(&prepared_provision.counter_info, 0,
|
||||
sizeof(prepared_provision.counter_info));
|
||||
} else if (!CopyCounterInfo(&core_provisioning_request->counter_info,
|
||||
&prepared_provision.counter_info)) {
|
||||
if (!CopyCounterInfo(&core_provisioning_request->counter_info,
|
||||
&prepared_provision.counter_info)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@ CoreMessageFeatures CoreMessageFeatures::DefaultFeatures(
|
||||
features.maximum_minor_version = 2; // 17.2
|
||||
break;
|
||||
case 18:
|
||||
features.maximum_minor_version = 1; // 18.0
|
||||
features.maximum_minor_version = 2; // 18.2
|
||||
break;
|
||||
default:
|
||||
features.maximum_minor_version = 0;
|
||||
|
||||
@@ -494,6 +494,12 @@ void Unpack_ODK_PreparedProvisioningRequest(
|
||||
Unpack_ODK_MessageCounterInfo(msg, &obj->counter_info);
|
||||
}
|
||||
|
||||
void Unpack_ODK_PreparedProvisioningRequestV180(
|
||||
ODK_Message* msg, ODK_PreparedProvisioningRequest* obj) {
|
||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
Unpack_ODK_MessageCounterInfo(msg, &obj->counter_info);
|
||||
}
|
||||
|
||||
void Unpack_ODK_PreparedProvisioningRequestV17(
|
||||
ODK_Message* msg, ODK_PreparedProvisioningRequestV17* obj) {
|
||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
|
||||
@@ -69,6 +69,8 @@ void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||
ODK_PreparedRenewalRequest* obj);
|
||||
void Unpack_ODK_PreparedProvisioningRequest(
|
||||
ODK_Message* msg, ODK_PreparedProvisioningRequest* obj);
|
||||
void Unpack_ODK_PreparedProvisioningRequestV180(
|
||||
ODK_Message* msg, ODK_PreparedProvisioningRequest* obj);
|
||||
void Unpack_ODK_PreparedProvisioningRequestV17(
|
||||
ODK_Message* msg, ODK_PreparedProvisioningRequestV17* obj);
|
||||
void Unpack_ODK_PreparedProvisioning40Request(
|
||||
|
||||
Reference in New Issue
Block a user