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:
Matt Feddersen
2023-04-12 09:00:41 -07:00
committed by Robert Shih
parent c6e7c70a6b
commit a2a27c44ef
7 changed files with 147 additions and 68 deletions

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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(