From a7cded376e86e27512066501bfc5d636be93821d Mon Sep 17 00:00:00 2001 From: "John \"Juce\" Bruce" Date: Mon, 16 May 2022 18:32:00 -0700 Subject: [PATCH] Skip padding for content keys differently (This is a merge of http://go/wvgerrit/151891.) A previous patch changed how we skip padding when extracting keys from key containers in license.cpp. Unfortunately, this broke generic signing when an ODK core message is not in use: 1) "Content" keys for signing are 32 bytes long, but content keys were assumed to be 16 bytes long. 2) When an ODK core message IS in use, the result of the extraction in license.cpp is ignored. The only way to know the correct length of a content key container in License Protocol 2.1 is to leverage the knowledge that it will always be padded by exactly 16 bytes. This will have to change if we ever implement support for License Protocol 2.2, as all key containers are unpadded in that version. Bug: 231439638 Bug: 114159862 Test: oemcrypto_dynamic_v15 Change-Id: I1d6c24b3a922247b970fd1517c6f23aded570adf --- .../cdm/core/include/wv_cdm_constants.h | 2 ++ libwvdrmengine/cdm/core/src/license.cpp | 30 ++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h index 3bdb90ab..66c99487 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h @@ -20,6 +20,8 @@ static const size_t ENTITLEMENT_KEY_SIZE = 32; static const size_t KEYBOX_KEY_DATA_SIZE = 72; static const size_t SRM_REQUIREMENT_SIZE = 12; +static const size_t LICENSE_PROTOCOL_2_1_PADDING = 16; + // Initial estimate of certificate size. Code that // uses this estimate should be able to adapt to a larger or smaller size. static const size_t CERTIFICATE_DATA_SIZE = 4 * 1024; diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index 5e8d477c..2f99a056 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -59,6 +59,10 @@ std::vector ExtractEntitlementKeys(const License& license) { case License_KeyContainer::ENTITLEMENT: { // We always take the first ENTITLEMENT_KEY_SIZE bytes and ignore the // rest in order to ignore any padding. + // + // TODO(b/232464183): When we switch to License Protocol 2.2, there will + // no longer be padding on these keys, so this + // removal code can be removed at the same time. if (license.key(i).key().size() < ENTITLEMENT_KEY_SIZE) { LOGE( "Skipping key %s because it is too small. Expected: %zu vs. " @@ -117,17 +121,29 @@ std::vector ExtractContentKeys(const License& license) { case License_KeyContainer::CONTENT: case License_KeyContainer::OPERATOR_SESSION: { key.set_key_id(license.key(i).id()); - // We always take the first CONTENT_KEY_SIZE bytes and ignore the rest - // in order to ignore any padding. - if (license.key(i).key().size() < CONTENT_KEY_SIZE) { + // KeyContainers have a fixed 16 bytes of padding in License Protocol + // 2.1. Note that OPERATION_SESSION keys may be CONTENT_KEY_SIZE or + // MAC_KEY_SIZE, so we cannot assume the key size here. + // + // TODO(b/232464183): When we switch to License Protocol 2.2, there will + // no longer be padding on these keys, so this + // removal code must be removed at the same time. + if (license.key(i).key().size() != + CONTENT_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING && + license.key(i).key().size() != + MAC_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING) { LOGE( - "Skipping key %s because it is too small. Expected: %zu vs. " - "Actual: %zu", - license.key(i).id().c_str(), CONTENT_KEY_SIZE, + "Skipping key %s because it is an unexpected size. Expected: %zu " + "or %zu, Actual: %zu", + license.key(i).id().c_str(), + CONTENT_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING, + MAC_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING, license.key(i).key().size()); continue; } - key.set_key_data(license.key(i).key().substr(0, CONTENT_KEY_SIZE)); + const size_t length = + license.key(i).key().size() - LICENSE_PROTOCOL_2_1_PADDING; + key.set_key_data(license.key(i).key().substr(0, length)); key.set_key_data_iv(license.key(i).iv()); if (license.key(i).has_key_control()) { key.set_key_control(license.key(i).key_control().key_control_block());