From 17d28c35fafa141b50360636e8cd93dc4bd23187 Mon Sep 17 00:00:00 2001 From: Matt Feddersen Date: Mon, 3 Jun 2024 12:55:26 -0700 Subject: [PATCH] Add workaround for VERSION_2_2 back compat Uses the same workaround as whitebox for compatibility with v16.4 and older servers. Test: Locally built in Trusty repo, installed on prod device with DPM, ran custom Exoplayer demo with license server URL replaced with 1642 endpoint. PiperOrigin-RevId: 639882556 Merged from https://widevine-internal-review.googlesource.com/199870 Change-Id: I1669acc3ddae1bb3726bacd0de2f72aca75c9e97 (cherry picked from commit 5f7cd33f9869825bb17992840483807cae83ad24) --- .../oemcrypto/odk/src/odk_serialize.c | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libwvdrmengine/oemcrypto/odk/src/odk_serialize.c b/libwvdrmengine/oemcrypto/odk/src/odk_serialize.c index 04982fa4..1f2e48ed 100644 --- a/libwvdrmengine/oemcrypto/odk/src/odk_serialize.c +++ b/libwvdrmengine/oemcrypto/odk/src/odk_serialize.c @@ -8,6 +8,8 @@ #include "odk_serialize.h" +#include "odk_message.h" +#include "odk_overflow.h" #include "odk_structs_priv.h" #include "serialization_base.h" @@ -237,6 +239,36 @@ static void Unpack_OEMCrypto_KeyObject(ODK_Message* msg, Unpack_OEMCrypto_Substring(msg, &obj->key_data); Unpack_OEMCrypto_Substring(msg, &obj->key_control_iv); Unpack_OEMCrypto_Substring(msg, &obj->key_control); + + /* + Edge case for servers that incorrectly process protocol VERSION_2_2 padding. + Key data in proto is present, but each key's position in the core + message is missing. + + Use the key_data_iv offset to determine if the key_data is present. + This assumes that the serialized protobuf is deterministically ordered, and + that the content key is always 16 bytes. These assumptions should hold true + for v16 and older servers. + */ + if (ODK_Message_GetStatus(msg) == MESSAGE_STATUS_OK && + obj->key_data.offset == 0 && obj->key_data.length == 0) { + const size_t kKeyDataProtoHeaderSize = 2; + obj->key_data.offset = obj->key_data_iv.offset + obj->key_data_iv.length + + kKeyDataProtoHeaderSize; + obj->key_data.length = 16u; // assume 16-byte key + + // Check for overflow. The offset is relative to the end of the core + // message, so add that length to the calculation. + size_t substring_end = 0; // offset + length + size_t end = 0; // offset + length + message_length + if (odk_add_overflow_ux(obj->key_data.offset, obj->key_data.length, + &substring_end) || + odk_add_overflow_ux(substring_end, ODK_Message_GetSize(msg), &end) || + end > ODK_Message_GetCapacity(msg)) { + ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR); + return; + } + } } static void Unpack_ODK_TimerLimits(ODK_Message* msg, ODK_TimerLimits* obj) {