From adb98d80d317f3ba4c3fc119e5d3e3aee7603669 Mon Sep 17 00:00:00 2001 From: John Rummell Date: Mon, 13 Dec 2021 16:40:24 -0800 Subject: [PATCH] Update to latest version including support for Partner Keys Includes change to WB_License_Create() so that it includes a separate parameter that specifies the init data used for Provider Keys. This updates the repo to match the internal repo at commit: 8c1c4338906a32eed83eb63702690d1f02ff7cd0 --- whitebox/WORKSPACE | 2 +- whitebox/api/BUILD | 24 ++ whitebox/api/license_whitebox.h | 14 +- whitebox/api/license_whitebox_benchmark.cc | 7 +- whitebox/api/license_whitebox_benchmark.h | 7 +- whitebox/api/license_whitebox_create_test.cc | 23 +- .../api/license_whitebox_decrypt_benchmark.cc | 27 +- whitebox/api/license_whitebox_decrypt_test.cc | 150 ++++++--- ...license_whitebox_get_secret_string_test.cc | 17 +- ...license_whitebox_key_control_block_test.cc | 34 +- .../api/license_whitebox_license_key_mode.cc | 2 +- .../license_whitebox_masked_decrypt_test.cc | 178 ++++++++--- ...ebox_process_license_response_benchmark.cc | 82 +++-- ...cess_license_response_core_message_test.cc | 187 ++++++----- ..._whitebox_process_license_response_test.cc | 300 ++++++++++-------- ...license_whitebox_provider_keys_test_data.h | 16 + ..._whitebox_query_content_key_status_test.cc | 2 +- ..._whitebox_query_signing_key_status_test.cc | 2 +- .../license_whitebox_security_level_test.cc | 17 +- .../api/license_whitebox_sign_benchmark.cc | 13 +- ...ense_whitebox_sign_renewal_request_test.cc | 34 +- whitebox/api/license_whitebox_test_base.cc | 5 +- whitebox/api/license_whitebox_uat_test.cc | 20 +- .../api/license_whitebox_verify_benchmark.cc | 27 +- ...e_whitebox_verify_renewal_response_test.cc | 34 +- ...emote_attestation_and_verification_test.cc | 2 +- whitebox/api/test_license_builder.cc | 49 ++- whitebox/api/test_license_builder.h | 7 + whitebox/api/test_license_provider_keys.cc | 23 ++ whitebox/api/test_license_provider_keys.h | 21 ++ .../api/test_license_whitebox_keys_general.cc | 2 + .../api/test_license_whitebox_keys_uat.cc | 2 + .../cdm/protos/defs/license_protocol.proto | 3 + whitebox/crypto_utils/aes_cbc_decryptor.cc | 3 +- whitebox/crypto_utils/aes_cbc_encryptor.cc | 3 +- whitebox/crypto_utils/aes_ctr_encryptor.cc | 3 +- whitebox/crypto_utils/crypto_util.cc | 4 +- whitebox/crypto_utils/private_key_util.h | 4 +- whitebox/crypto_utils/rsa_util.cc | 16 +- whitebox/external/odk.BUILD | 2 +- whitebox/reference/impl/BUILD | 12 + whitebox/reference/impl/aead_whitebox_impl.cc | 2 +- whitebox/reference/impl/license_parser.cc | 46 +++ whitebox/reference/impl/license_parser.h | 23 +- .../reference/impl/license_whitebox_impl.cc | 39 ++- ...icense_whitebox_provider_keys_test_data.cc | 23 ++ whitebox/reference/impl/odk_license_parser.cc | 18 +- whitebox/reference/impl/odk_license_parser.h | 10 +- .../reference/impl/protobuf_license_parser.cc | 24 +- .../reference/impl/protobuf_license_parser.h | 8 +- whitebox/reference/tests/BUILD | 5 + 51 files changed, 1104 insertions(+), 474 deletions(-) create mode 100644 whitebox/api/license_whitebox_provider_keys_test_data.h create mode 100644 whitebox/api/test_license_provider_keys.cc create mode 100644 whitebox/api/test_license_provider_keys.h create mode 100644 whitebox/reference/impl/license_whitebox_provider_keys_test_data.cc diff --git a/whitebox/WORKSPACE b/whitebox/WORKSPACE index caad13f..601fec0 100644 --- a/whitebox/WORKSPACE +++ b/whitebox/WORKSPACE @@ -26,7 +26,7 @@ git_repository( git_repository( name = "boringssl_repo", - commit = "14164f6fef47b7ebd97cdb0cea1624eabd6fe6b8", # 2018-11-26 + commit = "4fb158925f7753d80fb858cb0239dff893ef9f15", # 2021-11-01 remote = "https://github.com/google/boringssl.git", ) diff --git a/whitebox/api/BUILD b/whitebox/api/BUILD index 8f12f69..d961fbc 100644 --- a/whitebox/api/BUILD +++ b/whitebox/api/BUILD @@ -77,6 +77,25 @@ cc_library( visibility = ["//visibility:public"], ) +cc_library( + name = "test_license_provider_keys", + srcs = [ + "test_license_provider_keys.cc", + ], + hdrs = [ + "test_license_provider_keys.h", + ], + visibility = ["//visibility:public"], +) + +cc_library( + name = "license_whitebox_provider_keys_test_data", + hdrs = [ + "license_whitebox_provider_keys_test_data.h", + ], + visibility = ["//visibility:public"], +) + cc_library( name = "golden_data", srcs = [ @@ -109,6 +128,7 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":test_key_types", + ":test_license_provider_keys", ":test_server", "//chromium_deps/cdm/keys:dev_certs", "//chromium_deps/cdm/protos:license_protocol_proto", @@ -163,6 +183,7 @@ cc_library( deps = [ ":golden_data", ":license_whitebox", + ":license_whitebox_provider_keys_test_data", ":test_license_whitebox_keys", "//chromium_deps/testing", "//crypto_utils:rsa_key", @@ -191,6 +212,7 @@ cc_library( deps = [ ":golden_data", ":license_whitebox", + ":license_whitebox_provider_keys_test_data", ":license_whitebox_test_base", ":test_license_builder", "//chromium_deps/testing", @@ -245,6 +267,7 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":license_whitebox", + ":license_whitebox_provider_keys_test_data", ":test_key_types", ":test_license_builder", ":test_license_whitebox_keys", @@ -265,6 +288,7 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":license_whitebox", + ":license_whitebox_provider_keys_test_data", "//chromium_deps/testing", ], alwayslink = True, diff --git a/whitebox/api/license_whitebox.h b/whitebox/api/license_whitebox.h index 1e507f0..f737e08 100644 --- a/whitebox/api/license_whitebox.h +++ b/whitebox/api/license_whitebox.h @@ -62,6 +62,11 @@ typedef enum { // key|. A pointer to the white-box instance will be returned via |whitebox|. // // Args: +// whitebox_init_data (in): The white-box initialization data for Provider +// Keys. +// +// whitebox_init_data_size (in): The number of bytes in whitebox_init_data. +// // whitebox (out) : The output parameter used to return the new white-box // instance. // @@ -71,7 +76,9 @@ typedef enum { // WB_RESULT_INVALID_PARAMETER if |whitebox| was null. // // WB_RESULT_OUT_OF_MEMORY if the necessary memory could not be allocated. -WB_Result WB_License_Create(WB_License_Whitebox** whitebox); +WB_Result WB_License_Create(const uint8_t* whitebox_init_data, + size_t whitebox_init_data_size, + WB_License_Whitebox** whitebox); // Releases all resources used by the white-box instance pointed to by // |whitebox|. @@ -151,6 +158,10 @@ WB_Result WB_License_SignLicenseRequest(const WB_License_Whitebox* whitebox, // // session_key_size (in) : The number of bytes in |session_key|. // +// provider_key_id (in) : The Provider Key Id. If it is 0 or invalid, it falls +// back to no Provider Key; otherwise, the indexed Provider Key is used to +// decrypt the Content Key after it is decrypted by Key Encryption Key. +// // license_request (in) : The license request that was sent in order to get the // license response. // @@ -193,6 +204,7 @@ WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox, size_t signature_size, const uint8_t* session_key, size_t session_key_size, + size_t provider_key_id, const uint8_t* license_request, size_t license_request_size); diff --git a/whitebox/api/license_whitebox_benchmark.cc b/whitebox/api/license_whitebox_benchmark.cc index 79b1ce1..ce8f54e 100644 --- a/whitebox/api/license_whitebox_benchmark.cc +++ b/whitebox/api/license_whitebox_benchmark.cc @@ -37,8 +37,13 @@ void LicenseWhiteboxBenchmark::SetUp() { License LicenseWhiteboxBenchmark::CreateLicense(WB_LicenseKeyMode key_mode, int number_of_content_keys, - SecurityLevel security_level) { + SecurityLevel security_level, + size_t provider_key_id) { + TestLicenseBuilder::Settings settings; + settings.provider_key_id = provider_key_id; + TestLicenseBuilder license_builder; + license_builder.SetSettings(settings); license_builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey()); // Update the first key to match the security level. diff --git a/whitebox/api/license_whitebox_benchmark.h b/whitebox/api/license_whitebox_benchmark.h index 66f5cb8..39230c8 100644 --- a/whitebox/api/license_whitebox_benchmark.h +++ b/whitebox/api/license_whitebox_benchmark.h @@ -21,14 +21,15 @@ class LicenseWhiteboxBenchmark : public ::testing::Test { virtual void SetUp() override; // Create a new license with the specified number of content keys using the - // security_level provided. The first content key will use - // kSoftwareSecureCrypto, while the remainder will be specified by + // security_level and provider key id provided. The first content key will + // use kSoftwareSecureCrypto, while the remainder will be specified by // |security_level|. The given key mode will change how the license is // encrypted and signed. The white-box instance is expected to use the // correct key mode in order to process the license response. License CreateLicense(WB_LicenseKeyMode key_mode, int number_of_content_keys, - SecurityLevel security_level); + SecurityLevel security_level, + size_t provider_key_id); // Sign the message using the default HMAC signing key. std::vector SignAsServer(const std::vector& message) const; diff --git a/whitebox/api/license_whitebox_create_test.cc b/whitebox/api/license_whitebox_create_test.cc index 648f387..3a2bd46 100644 --- a/whitebox/api/license_whitebox_create_test.cc +++ b/whitebox/api/license_whitebox_create_test.cc @@ -2,6 +2,7 @@ #include "api/license_whitebox.h" +#include "api/license_whitebox_provider_keys_test_data.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -15,12 +16,30 @@ class LicenseWhiteboxCreateTest : public ::testing::Test { }; TEST_F(LicenseWhiteboxCreateTest, Succeeds) { - ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); + ASSERT_EQ(WB_License_Create(nullptr, 0, &whitebox_), WB_RESULT_OK); ASSERT_TRUE(whitebox_); } TEST_F(LicenseWhiteboxCreateTest, InvalidParameterForNullWhitebox) { - ASSERT_EQ(WB_License_Create(nullptr), WB_RESULT_INVALID_PARAMETER); + ASSERT_EQ(WB_License_Create(nullptr, 0, nullptr), + WB_RESULT_INVALID_PARAMETER); +} + +TEST_F(LicenseWhiteboxCreateTest, ValidParameterForInitData) { + auto init_data = widevine::GetLicenseWhiteboxProviderKeysInitData(); + ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_), + WB_RESULT_OK); +} + +TEST_F(LicenseWhiteboxCreateTest, InvalidParameterForInitData) { + auto init_data = widevine::GetLicenseWhiteboxProviderKeysInitData(); + ASSERT_EQ(WB_License_Create(nullptr, init_data.size(), &whitebox_), + WB_RESULT_INVALID_PARAMETER); +} + +TEST_F(LicenseWhiteboxCreateTest, ValidParameterForInitDataSize) { + auto init_data = widevine::GetLicenseWhiteboxProviderKeysInitData(); + ASSERT_EQ(WB_License_Create(init_data.data(), 0, &whitebox_), WB_RESULT_OK); } } // namespace diff --git a/whitebox/api/license_whitebox_decrypt_benchmark.cc b/whitebox/api/license_whitebox_decrypt_benchmark.cc index 07f2646..1268bc7 100644 --- a/whitebox/api/license_whitebox_decrypt_benchmark.cc +++ b/whitebox/api/license_whitebox_decrypt_benchmark.cc @@ -8,6 +8,7 @@ #include "api/license_whitebox.h" #include "api/license_whitebox_benchmark.h" +#include "api/license_whitebox_provider_keys_test_data.h" #include "api/result.h" #include "api/test_license_builder.h" #include "benchmarking/data_source.h" @@ -43,18 +44,22 @@ class LicenseWhiteboxDecryptBenchmark masked_text_.resize(bytes_per_call); plaintext_.resize(bytes_per_call); - ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); - - const auto license = CreateLicense(WB_LICENSE_KEY_MODE_DUAL_KEY, 1, - SecurityLevel::kSoftwareSecureCrypto); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), + auto init_data = GetLicenseWhiteboxProviderKeysInitData(); + ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_), WB_RESULT_OK); + + const auto license = + CreateLicense(WB_LICENSE_KEY_MODE_DUAL_KEY, 1, + SecurityLevel::kSoftwareSecureCrypto, kNoProviderKeyId); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, + license.core_message.data(), license.core_message.size(), + license.message.data(), license.message.size(), + license.signature.data(), license.signature.size(), + license.session_key.data(), license.session_key.size(), + kNoProviderKeyId, license.request.data(), license.request.size()), + WB_RESULT_OK); } void TearDown() override { WB_License_Delete(whitebox_); } diff --git a/whitebox/api/license_whitebox_decrypt_test.cc b/whitebox/api/license_whitebox_decrypt_test.cc index 5451b09..78a571f 100644 --- a/whitebox/api/license_whitebox_decrypt_test.cc +++ b/whitebox/api/license_whitebox_decrypt_test.cc @@ -17,10 +17,16 @@ namespace { using Padding = TestLicenseBuilder::Padding; +const size_t kValidProviderKeyId1 = 1; +const size_t kValidProviderKeyId2 = 2; +const size_t kInvalidProviderKeyId = 0xfff; +// There is also kNoProviderKeyId specified in test_license_builder. + } // namespace -class LicenseWhiteboxDecryptTest : public LicenseWhiteboxTestBase, - public testing::WithParamInterface { +class LicenseWhiteboxDecryptTest + : public LicenseWhiteboxTestBase, + public ::testing::WithParamInterface> { protected: void SetUp() override { LicenseWhiteboxTestBase::SetUp(); @@ -34,13 +40,21 @@ class LicenseWhiteboxDecryptTest : public LicenseWhiteboxTestBase, non_content_key_id_ = golden_data_.GetFreeId(); missing_key_id_ = golden_data_.GetFreeId(); - padding_ = GetParam(); + padding_ = std::get<0>(GetParam()); + provider_key_id_ = std::get<1>(GetParam()); } - void LoadLicense(const TestLicenseBuilder::Settings& settings) { + // Creates and loads a license. The license is created using |settings| + // updated to include the test parameters. The license is loaded using + // |provider_key_id|. + void LoadLicense(const TestLicenseBuilder::Settings& settings, + size_t provider_key_id) { TestLicenseBuilder builder; builder.SetSettings(settings); + + // Update settings with the test specified parameters. builder.GetSettings().padding = padding_; + builder.GetSettings().provider_key_id = provider_key_id_; builder.AddContentKey(golden_data_.CBCContent().software_crypto_key); builder.AddContentKey(golden_data_.CBCContent().software_decode_key); @@ -55,14 +69,15 @@ class LicenseWhiteboxDecryptTest : public LicenseWhiteboxTestBase, License license; builder.Build(*server, &license); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, + license.core_message.data(), license.core_message.size(), + license.message.data(), license.message.size(), + license.signature.data(), license.signature.size(), + license.session_key.data(), license.session_key.size(), + provider_key_id, license.request.data(), license.request.size()), + WB_RESULT_OK); } // We need two special keys for this test, one that will be used for a @@ -75,11 +90,12 @@ class LicenseWhiteboxDecryptTest : public LicenseWhiteboxTestBase, std::vector plaintext_; Padding padding_; + size_t provider_key_id_; }; TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCbcMode) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -97,7 +113,7 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCbcMode) { TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCbc) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); memcpy(plaintext_.data(), golden_data_.CBCContent().ciphertext.data(), golden_data_.CBCContent().ciphertext.size()); @@ -117,7 +133,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCbc) { TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCtrMode) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -135,7 +151,7 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCtrMode) { TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCtr) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); memcpy(plaintext_.data(), golden_data_.CTRContent().ciphertext.data(), golden_data_.CTRContent().ciphertext.size()); @@ -157,7 +173,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCtr) { // successful, but the resulting plaintext should not match. TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCtrMode) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -177,7 +193,7 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCtrMode) { // successful, but the resulting plaintext should not match. TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCbcMode) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -197,7 +213,7 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCbcMode) { // different keys can be used at the same time. TEST_P(LicenseWhiteboxDecryptTest, SuccessWithMultipleKeys) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -234,7 +250,7 @@ TEST_P(LicenseWhiteboxDecryptTest, SuccessWithMultipleKeys) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullWhitebox) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( nullptr, WB_CIPHER_MODE_CBC, @@ -250,7 +266,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullWhitebox) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCipherMode) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); // In order to trick the compiler into letting us pass an invalid enum value // to WB__License_Decrypt(), we need to cast it. If we don't do this, the @@ -271,7 +287,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCipherMode) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullKeyId) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, nullptr, @@ -286,7 +302,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullKeyId) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroKeyIdSize) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -301,7 +317,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroKeyIdSize) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullInputData) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -318,7 +334,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullInputData) { // not care. TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCBCInputDataSize) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -334,7 +350,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCBCInputDataSize) { // The white-box (using any cipher mode) should reject input with size zero. TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroInputDataSize) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -349,7 +365,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroInputDataSize) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullIV) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -365,7 +381,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullIV) { // IV size should be 16. Any number other than 16 should fail. TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidIVSize) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -380,7 +396,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidIVSize) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutput) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -395,7 +411,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutput) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutputSize) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ( WB_License_Decrypt( @@ -414,7 +430,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutputSize) { // and "dropped content key", as those keys were in the license but ignored. TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForMissingKeyId) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC, missing_key_id_.data(), missing_key_id_.size(), @@ -428,7 +444,7 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForMissingKeyId) { TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForNonContentKey) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ( WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC, @@ -446,7 +462,7 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForNonContentKey) { TEST_P(LicenseWhiteboxDecryptTest, InsufficientSecurityLevelForHardwareContentKey) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC, golden_data_.CBCContent().hardware_key.id.data(), @@ -461,7 +477,7 @@ TEST_P(LicenseWhiteboxDecryptTest, TEST_P(LicenseWhiteboxDecryptTest, InsufficientSecurityLevelForDecodeKey) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); // Use the software decode key as they are limited to // WB_License_Decrypt(). @@ -479,7 +495,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InsufficientSecurityLevelForDecodeKey) { TEST_P(LicenseWhiteboxDecryptTest, BufferTooSmall) { TestLicenseBuilder::Settings settings; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); // Our ciphertext will be large enough that we should not need to worry about // using a constant here. @@ -524,7 +540,7 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForInvalidKey) { // we just need an invalid key, so we use one way of invalidating the key. TestLicenseBuilder::Settings settings; settings.include_content_key_iv = false; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -538,11 +554,61 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForInvalidKey) { WB_RESULT_KEY_UNAVAILABLE); } -INSTANTIATE_TEST_SUITE_P(NoPadding, - LicenseWhiteboxDecryptTest, - ::testing::Values(Padding::kNone)); +// For this test, we create a license using the test specified Provider Key +// Id, then load the license using a different Provider Key Id. +TEST_P(LicenseWhiteboxDecryptTest, MismatchProviderKeyId) { + // These tests use 2 valid provider key IDs, so try loading the license + // with a different key. Not all possible combinations are tested. + size_t other_provider_key_id = kInvalidProviderKeyId; + switch (provider_key_id_) { + case kNoProviderKeyId: + other_provider_key_id = kValidProviderKeyId1; + break; + case kValidProviderKeyId1: + other_provider_key_id = kValidProviderKeyId2; + break; + case kValidProviderKeyId2: + other_provider_key_id = kNoProviderKeyId; + break; + case kInvalidProviderKeyId: + // This is the same as kNoProviderKeyId, so use one of the valid ids. + other_provider_key_id = kValidProviderKeyId2; + break; + } -INSTANTIATE_TEST_SUITE_P(PKSC8, - LicenseWhiteboxDecryptTest, - ::testing::Values(Padding::kPKSC8)); + TestLicenseBuilder::Settings settings; + LoadLicense(settings, other_provider_key_id); + + // Decryption should succeed, but the plaintext should be incorrect. + ASSERT_EQ(WB_License_Decrypt( + whitebox_, WB_CIPHER_MODE_CBC, + golden_data_.CBCContent().software_crypto_key.id.data(), + golden_data_.CBCContent().software_crypto_key.id.size(), + golden_data_.CBCContent().ciphertext.data(), + golden_data_.CBCContent().ciphertext.size(), + golden_data_.CBCContent().iv.data(), + golden_data_.CBCContent().iv.size(), plaintext_.data(), + &plaintext_size_), + WB_RESULT_OK); + plaintext_.resize(plaintext_size_); + ASSERT_NE(plaintext_, golden_data_.CBCContent().plaintext); +} + +INSTANTIATE_TEST_SUITE_P( + NoPadding, + LicenseWhiteboxDecryptTest, + ::testing::Combine(::testing::Values(Padding::kNone), + ::testing::Values(kNoProviderKeyId, + kValidProviderKeyId1, + kValidProviderKeyId2, + kInvalidProviderKeyId))); + +INSTANTIATE_TEST_SUITE_P( + PKSC8, + LicenseWhiteboxDecryptTest, + ::testing::Combine(::testing::Values(Padding::kPKSC8), + ::testing::Values(kNoProviderKeyId, + kValidProviderKeyId1, + kValidProviderKeyId2, + kInvalidProviderKeyId))); } // namespace widevine diff --git a/whitebox/api/license_whitebox_get_secret_string_test.cc b/whitebox/api/license_whitebox_get_secret_string_test.cc index 118ed0a..3129618 100644 --- a/whitebox/api/license_whitebox_get_secret_string_test.cc +++ b/whitebox/api/license_whitebox_get_secret_string_test.cc @@ -45,14 +45,15 @@ class LicenseWhiteboxGetSecretStringTest : public LicenseWhiteboxTestBase { License license; builder.Build(*server, &license); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, + license.core_message.data(), license.core_message.size(), + license.message.data(), license.message.size(), + license.signature.data(), license.signature.size(), + license.session_key.data(), license.session_key.size(), + kNoProviderKeyId, license.request.data(), license.request.size()), + WB_RESULT_OK); } // We need two special keys for this test, one that will be used for a diff --git a/whitebox/api/license_whitebox_key_control_block_test.cc b/whitebox/api/license_whitebox_key_control_block_test.cc index cc47a0c..79f8f4c 100644 --- a/whitebox/api/license_whitebox_key_control_block_test.cc +++ b/whitebox/api/license_whitebox_key_control_block_test.cc @@ -44,14 +44,15 @@ TEST_P(LicenseWhiteboxKeyControlBlockTest, Decrypt) { License license; builder.Build(*server_, &license); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(), + license.core_message.size(), license.message.data(), + license.message.size(), license.signature.data(), + license.signature.size(), license.session_key.data(), + license.session_key.size(), kNoProviderKeyId, license.request.data(), + license.request.size()), + WB_RESULT_OK); std::vector plaintext(content.ciphertext.size()); size_t plaintext_size = plaintext.size(); @@ -78,14 +79,15 @@ TEST_P(LicenseWhiteboxKeyControlBlockTest, MaskedDecrypt) { License license; builder.Build(*server_, &license); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(), + license.core_message.size(), license.message.data(), + license.message.size(), license.signature.data(), + license.signature.size(), license.session_key.data(), + license.session_key.size(), kNoProviderKeyId, license.request.data(), + license.request.size()), + WB_RESULT_OK); std::vector plaintext(content.ciphertext.size()); size_t plaintext_size = plaintext.size(); diff --git a/whitebox/api/license_whitebox_license_key_mode.cc b/whitebox/api/license_whitebox_license_key_mode.cc index 55b2631..ae41318 100644 --- a/whitebox/api/license_whitebox_license_key_mode.cc +++ b/whitebox/api/license_whitebox_license_key_mode.cc @@ -70,7 +70,7 @@ class LicenseWhiteboxLicenseKeyMode license.core_message.size(), license.message.data(), license.message.size(), license.signature.data(), license.signature.size(), license.session_key.data(), - license.session_key.size(), license.request.data(), + license.session_key.size(), kNoProviderKeyId, license.request.data(), license.request.size()); } diff --git a/whitebox/api/license_whitebox_masked_decrypt_test.cc b/whitebox/api/license_whitebox_masked_decrypt_test.cc index 778be30..5f7ca4d 100644 --- a/whitebox/api/license_whitebox_masked_decrypt_test.cc +++ b/whitebox/api/license_whitebox_masked_decrypt_test.cc @@ -19,11 +19,16 @@ namespace { using Padding = TestLicenseBuilder::Padding; +const size_t kValidProviderKeyId1 = 1; +const size_t kValidProviderKeyId2 = 2; +const size_t kInvalidProviderKeyId = 0xfff; +// There is also kNoProviderKeyId specified in test_license_builder. + } // namespace class LicenseWhiteboxMaskedDecryptTest : public LicenseWhiteboxTestBase, - public testing::WithParamInterface { + public ::testing::WithParamInterface> { protected: void SetUp() override { LicenseWhiteboxTestBase::SetUp(); @@ -42,13 +47,19 @@ class LicenseWhiteboxMaskedDecryptTest non_content_key_id_ = golden_data_.GetFreeId(); missing_key_id_ = golden_data_.GetFreeId(); - padding_ = GetParam(); + padding_ = std::get<0>(GetParam()); + provider_key_id_ = std::get<1>(GetParam()); } - void LoadLicense(const TestLicenseBuilder::Settings& settings) { + // Creates and loads a license. The license is created using |settings| + // updated to include the test parameters. The license is loaded using + // |provider_key_id|. + void LoadLicense(const TestLicenseBuilder::Settings& settings, + size_t provider_key_id) { TestLicenseBuilder builder; builder.SetSettings(settings); builder.GetSettings().padding = padding_; + builder.GetSettings().provider_key_id = provider_key_id_; builder.AddContentKey(golden_data_.CBCContent().software_crypto_key); builder.AddContentKey(golden_data_.CBCContent().software_decode_key); @@ -64,14 +75,15 @@ class LicenseWhiteboxMaskedDecryptTest License license; builder.Build(*server, &license); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, + license.core_message.data(), license.core_message.size(), + license.message.data(), license.message.size(), + license.signature.data(), license.signature.size(), + license.session_key.data(), license.session_key.size(), + provider_key_id, license.request.data(), license.request.size()), + WB_RESULT_OK); } // We need two special keys for this test, one that will be used for a @@ -88,12 +100,13 @@ class LicenseWhiteboxMaskedDecryptTest std::vector plaintext_; Padding padding_; + size_t provider_key_id_; }; TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCbcMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -132,7 +145,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCbcMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCbc) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); memcpy(masked_text_.data(), golden_data_.CBCContent().ciphertext.data(), golden_data_.CBCContent().ciphertext.size()); @@ -173,7 +186,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCbc) { TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCtrMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -212,7 +225,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCtrMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCtr) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); memcpy(masked_text_.data(), golden_data_.CTRContent().ciphertext.data(), golden_data_.CTRContent().ciphertext.size()); @@ -255,7 +268,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCtr) { TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCtrMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -295,7 +308,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCtrMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCbcMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -333,7 +346,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCbcMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -372,7 +385,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCtrMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -413,7 +426,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCtrMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCtrMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -453,7 +466,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCtrMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCbcMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -491,7 +504,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCbcMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kPKSC8; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -530,7 +543,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataAndPKCS8Padding) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kPKSC8; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -574,7 +587,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataAndPKCS8Padding) { TEST_P(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -654,7 +667,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullWhitebox) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( nullptr, WB_CIPHER_MODE_CBC, @@ -671,7 +684,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullWhitebox) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidCipherMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); // In order to trick the compiler into letting us pass an invalid enum value // to WB__License_MaskedDecrypt(), we need to cast it. If we don't do this, @@ -693,7 +706,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidCipherMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullKeyId) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, nullptr, @@ -709,7 +722,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullKeyId) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullZeroKeyIdSize) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -725,7 +738,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullZeroKeyIdSize) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullInputData) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -744,7 +757,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidCBCInputDataSize) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -761,7 +774,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForZeroInputDataSize) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -777,7 +790,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForZeroInputDataSize) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullIV) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -794,7 +807,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullIV) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidIVSize) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -810,7 +823,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidIVSize) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutput) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ( WB_License_MaskedDecrypt( @@ -827,7 +840,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutput) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutputSize) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ( WB_License_MaskedDecrypt( @@ -847,7 +860,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutputSize) { TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForMissingKeyId) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ( WB_License_MaskedDecrypt(whitebox_, WB_CIPHER_MODE_CBC, @@ -863,7 +876,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForMissingKeyId) { TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForNonContentKey) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, non_content_key_id_.data(), @@ -882,7 +895,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InsufficientSecurityLevelForHardwareContentKey) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ( WB_License_MaskedDecrypt(whitebox_, WB_CIPHER_MODE_CBC, @@ -915,7 +928,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidState) { TEST_P(LicenseWhiteboxMaskedDecryptTest, BufferTooSmall) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); // Our ciphertext will be large enough that we should not need to worry about // using a constant here. @@ -942,7 +955,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, BufferTooSmall) { TEST_P(LicenseWhiteboxMaskedDecryptTest, SuccessForSubRangeUnmask) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -984,7 +997,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForInvalidKey) { // we just need an invalid key, so we use one way of invalidating the key. TestLicenseBuilder::Settings settings; settings.include_content_key_iv = false; - LoadLicense(settings); + LoadLicense(settings, provider_key_id_); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -998,11 +1011,82 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForInvalidKey) { WB_RESULT_KEY_UNAVAILABLE); } -INSTANTIATE_TEST_SUITE_P(NoPadding, - LicenseWhiteboxMaskedDecryptTest, - ::testing::Values(Padding::kNone)); +// For this test, we create a license using the test specified Provider Key +// Id, then load the license using a different Provider Key Id. +TEST_P(LicenseWhiteboxMaskedDecryptTest, MismatchProviderKeyId) { + // These tests use 2 valid provider key IDs, so try loading the license + // with a different key. Not all possible combinations are tested. + size_t alternate_provider_key_id = kInvalidProviderKeyId; + switch (provider_key_id_) { + case kNoProviderKeyId: + alternate_provider_key_id = kValidProviderKeyId2; + break; + case kValidProviderKeyId1: + alternate_provider_key_id = kNoProviderKeyId; + break; + case kValidProviderKeyId2: + alternate_provider_key_id = kValidProviderKeyId1; + break; + case kInvalidProviderKeyId: + // This is the same as kNoProviderKeyId, so use one of the valid ids. + alternate_provider_key_id = kValidProviderKeyId1; + break; + } -INSTANTIATE_TEST_SUITE_P(PKSC8, - LicenseWhiteboxMaskedDecryptTest, - ::testing::Values(Padding::kPKSC8)); + TestLicenseBuilder::Settings settings; + LoadLicense(settings, alternate_provider_key_id); + + // Decryption should succeed, but the plaintext should be incorrect. + ASSERT_EQ(WB_License_MaskedDecrypt( + whitebox_, WB_CIPHER_MODE_CBC, + golden_data_.CBCContent().software_decode_key.id.data(), + golden_data_.CBCContent().software_decode_key.id.size(), + golden_data_.CBCContent().ciphertext.data(), + golden_data_.CBCContent().ciphertext.size(), + golden_data_.CBCContent().iv.data(), + golden_data_.CBCContent().iv.size(), masked_text_.data(), + &masked_text_size_), + WB_RESULT_OK); + masked_text_.resize(masked_text_size_); + + // Returned data is masked, so it should be the correct size but not + // match the original text. + ASSERT_EQ(masked_text_.size(), golden_data_.CBCContent().plaintext.size()); + ASSERT_NE(masked_text_, golden_data_.CBCContent().plaintext); + + // Now unmask the data. It should successfully unmask, but be incorrect as + // a different provider key ID was used. + ASSERT_EQ(WB_License_GetSecretString( + whitebox_, WB_CIPHER_MODE_CBC, + golden_data_.CBCContent().software_decode_key.id.data(), + golden_data_.CBCContent().software_decode_key.id.size(), + secret_string_.data(), &secret_string_size_), + WB_RESULT_OK); + secret_string_.resize(secret_string_size_); + + plaintext_.resize(masked_text_size_); + WB_License_Unmask(masked_text_.data(), 0, masked_text_size_, + secret_string_.data(), secret_string_.size(), + plaintext_.data()); + + ASSERT_NE(plaintext_, golden_data_.CBCContent().plaintext); +} + +INSTANTIATE_TEST_SUITE_P( + NoPadding, + LicenseWhiteboxMaskedDecryptTest, + ::testing::Combine(::testing::Values(Padding::kNone), + ::testing::Values(kNoProviderKeyId, + kValidProviderKeyId1, + kValidProviderKeyId2, + kInvalidProviderKeyId))); + +INSTANTIATE_TEST_SUITE_P( + PKSC8, + LicenseWhiteboxMaskedDecryptTest, + ::testing::Combine(::testing::Values(Padding::kNone), + ::testing::Values(kNoProviderKeyId, + kValidProviderKeyId1, + kValidProviderKeyId2, + kInvalidProviderKeyId))); } // namespace widevine diff --git a/whitebox/api/license_whitebox_process_license_response_benchmark.cc b/whitebox/api/license_whitebox_process_license_response_benchmark.cc index 52271a2..a206431 100644 --- a/whitebox/api/license_whitebox_process_license_response_benchmark.cc +++ b/whitebox/api/license_whitebox_process_license_response_benchmark.cc @@ -6,6 +6,7 @@ #include "api/license_whitebox.h" #include "api/license_whitebox_benchmark.h" +#include "api/license_whitebox_provider_keys_test_data.h" #include "api/result.h" #include "api/test_license_builder.h" #include "benchmarking/measurements.h" @@ -16,26 +17,32 @@ namespace { // The white-box implementation is slow, so the build bots keep timing out. To // work around this, use a fixed number of iterations. constexpr size_t kIterations = 10; + +const size_t kValidProviderKeyId = 1; } // namespace -// This test takes 3 parameters. The first (key mode) will change how the +// This test takes 4 parameters. The first (key mode) will change how the // license is encrypted and signed. The second (int) determines the number of // content keys in the license. The third (security level) determines the // security level of the content keys other than the first one (which is // always kSoftwareSecureCrypto so that it works with both Decrypt() and -// MaskedDecrypt()). +// MaskedDecrypt()). The fourth (provider key id) specifies the provider key +// id to be used (can be kNoProviderKeyId). class LicenseWhiteboxProcessLicenseResponseBenchmark : public LicenseWhiteboxBenchmark, public ::testing::WithParamInterface< - std::tuple> { + std::tuple> { protected: void SetUp() override { LicenseWhiteboxBenchmark::SetUp(); key_mode_ = ::testing::get<0>(GetParam()); + provider_key_id_ = ::testing::get<3>(GetParam()); + + init_data_ = GetLicenseWhiteboxProviderKeysInitData(); license_ = CreateLicense(key_mode_, ::testing::get<1>(GetParam()), - ::testing::get<2>(GetParam())); + ::testing::get<2>(GetParam()), provider_key_id_); } void TearDown() override { WB_License_Delete(whitebox_); } @@ -44,6 +51,11 @@ class LicenseWhiteboxProcessLicenseResponseBenchmark // with both single-key and dual-key. WB_LicenseKeyMode key_mode_; + // Specifies which provider key id should be used. + size_t provider_key_id_; + + std::vector init_data_; + WB_License_Whitebox* whitebox_; License license_; }; @@ -54,7 +66,9 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, ProcessLicenseCreate) { for (size_t i = 0; i < kIterations; i++) { timer.Reset(); - ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); + ASSERT_EQ( + WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_), + WB_RESULT_OK); sampler.Push(timer.Get()); WB_License_Delete(whitebox_); @@ -77,15 +91,17 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, // license. timer.Reset(); - ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); + ASSERT_EQ( + WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_), + WB_RESULT_OK); ASSERT_EQ(WB_License_ProcessLicenseResponse( whitebox_, key_mode_, license_.core_message.data(), license_.core_message.size(), license_.message.data(), license_.message.size(), license_.signature.data(), license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), license_.request.data(), - license_.request.size()), + license_.session_key.size(), provider_key_id_, + license_.request.data(), license_.request.size()), WB_RESULT_OK); WB_License_Delete(whitebox_); @@ -110,15 +126,17 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, // process license so that we know the true start-up cost. timer.Reset(); - ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); + ASSERT_EQ( + WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_), + WB_RESULT_OK); ASSERT_EQ(WB_License_ProcessLicenseResponse( whitebox_, key_mode_, license_.core_message.data(), license_.core_message.size(), license_.message.data(), license_.message.size(), license_.signature.data(), license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), license_.request.data(), - license_.request.size()), + license_.session_key.size(), provider_key_id_, + license_.request.data(), license_.request.size()), WB_RESULT_OK); sampler.Push(timer.Get()); @@ -139,7 +157,9 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, ProcessLicenseResponse) { // We can only call ProcessLicenseResponse() once per whitebox instance. So // we need to create a new instance each time. Do this before we reset the // timer so that we are not counting it in the execution time. - ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); + ASSERT_EQ( + WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_), + WB_RESULT_OK); timer.Reset(); @@ -148,8 +168,8 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, ProcessLicenseResponse) { license_.core_message.size(), license_.message.data(), license_.message.size(), license_.signature.data(), license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), license_.request.data(), - license_.request.size()), + license_.session_key.size(), provider_key_id_, + license_.request.data(), license_.request.size()), WB_RESULT_OK); sampler.Push(timer.Get()); @@ -167,41 +187,63 @@ INSTANTIATE_TEST_SUITE_P( LicenseWhiteboxProcessLicenseResponseBenchmark, ::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_SINGLE_KEY, 1, - SecurityLevel::kSoftwareSecureCrypto))); + SecurityLevel::kSoftwareSecureCrypto, + kNoProviderKeyId))); INSTANTIATE_TEST_SUITE_P( FiveCryptoKeysWithSingleKeyServer, LicenseWhiteboxProcessLicenseResponseBenchmark, ::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_SINGLE_KEY, 5, - SecurityLevel::kSoftwareSecureCrypto))); + SecurityLevel::kSoftwareSecureCrypto, + kNoProviderKeyId))); INSTANTIATE_TEST_SUITE_P( FiveDecodeKeysWithSingleKeyServer, LicenseWhiteboxProcessLicenseResponseBenchmark, ::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_SINGLE_KEY, 5, - SecurityLevel::kSoftwareSecureDecode))); + SecurityLevel::kSoftwareSecureDecode, + kNoProviderKeyId))); INSTANTIATE_TEST_SUITE_P( SingleKeyWithDualKeyServer, LicenseWhiteboxProcessLicenseResponseBenchmark, ::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_DUAL_KEY, 1, - SecurityLevel::kSoftwareSecureCrypto))); + SecurityLevel::kSoftwareSecureCrypto, + kNoProviderKeyId))); INSTANTIATE_TEST_SUITE_P( FiveCryptoKeysWithDualKeyServer, LicenseWhiteboxProcessLicenseResponseBenchmark, ::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_DUAL_KEY, 5, - SecurityLevel::kSoftwareSecureCrypto))); + SecurityLevel::kSoftwareSecureCrypto, + kNoProviderKeyId))); INSTANTIATE_TEST_SUITE_P( FiveDecodeKeysWithDualKeyServer, LicenseWhiteboxProcessLicenseResponseBenchmark, ::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_DUAL_KEY, 5, - SecurityLevel::kSoftwareSecureDecode))); + SecurityLevel::kSoftwareSecureDecode, + kNoProviderKeyId))); + +INSTANTIATE_TEST_SUITE_P( + SingleKeyWithSingleKeyServerAndProviderKeyId, + LicenseWhiteboxProcessLicenseResponseBenchmark, + ::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_SINGLE_KEY, + 1, + SecurityLevel::kSoftwareSecureCrypto, + kValidProviderKeyId))); + +INSTANTIATE_TEST_SUITE_P( + SingleKeyWithDualKeyServerAndProviderKeyId, + LicenseWhiteboxProcessLicenseResponseBenchmark, + ::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_DUAL_KEY, + 1, + SecurityLevel::kSoftwareSecureCrypto, + kValidProviderKeyId))); } // namespace widevine diff --git a/whitebox/api/license_whitebox_process_license_response_core_message_test.cc b/whitebox/api/license_whitebox_process_license_response_core_message_test.cc index 11892bb..a41c0f6 100644 --- a/whitebox/api/license_whitebox_process_license_response_core_message_test.cc +++ b/whitebox/api/license_whitebox_process_license_response_core_message_test.cc @@ -45,137 +45,147 @@ class LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithoutOdkAndWithoutSigningKey) { UseLicenseWithoutSigningKey(OdkVersion::kNone); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithOdk16_3AndWithoutSigningKey) { UseLicenseWithoutSigningKey(OdkVersion::k16_3); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithOdk16_5AndWithoutSigningKey) { UseLicenseWithoutSigningKey(OdkVersion::k16_5); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithoutOdkAndWithSigningKeyNoPadding) { UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone, OdkVersion::kNone); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithOdk16_3AndWithSigningKeyNoPadding) { UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone, OdkVersion::k16_3); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithOdk16_5AndWithSigningKeyNoPadding) { UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone, OdkVersion::k16_5); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithoutOdkAndWithSigningKeyPKSC8Padding) { UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8, OdkVersion::kNone); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithOdk16_3AndWithSigningKeyPKSC8Padding) { UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8, OdkVersion::k16_3); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithOdk16_5AndWithSigningKeyPKSC8Padding) { UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8, OdkVersion::k16_5); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, InvalidParameterForNullCoreMessage) { UseLicenseWithoutSigningKey(OdkVersion::k16_5); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - /*core_message=*/nullptr, license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_INVALID_PARAMETER); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, + /*core_message=*/nullptr, license_.core_message.size(), + license_.message.data(), license_.message.size(), + license_.signature.data(), license_.signature.size(), + license_.session_key.data(), license_.session_key.size(), + kNoProviderKeyId, license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, @@ -186,14 +196,15 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, // no parameter check will be done. However, since the license was created // with one, signature checking will fail as there is no core message // to be included when checking the signature. - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), /*core_message_size=*/0, - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_INVALID_SIGNATURE); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + /*core_message_size=*/0, license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_SIGNATURE); } } // namespace widevine diff --git a/whitebox/api/license_whitebox_process_license_response_test.cc b/whitebox/api/license_whitebox_process_license_response_test.cc index 10db006..3cb33a7 100644 --- a/whitebox/api/license_whitebox_process_license_response_test.cc +++ b/whitebox/api/license_whitebox_process_license_response_test.cc @@ -50,42 +50,45 @@ class LicenseWhiteboxProcessLicenseResponseTest TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithoutSigningKey) { UseLicenseWithoutSigningKey(); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithSigningKeyNoPadding) { UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithSigningKeyPKSC8Padding) { UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } // If there were multiple signing keys (this can only happen if a license server @@ -101,27 +104,69 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseTest, builder.AddContentKey(golden_data_.CBCContent().software_crypto_key); builder.Build(*server_, &license_); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseTest, InvalidParameterWithNoKeys) { UseLicenseWithNoKeys(); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); +} + +TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithProviderKey) { + const size_t kProviderKeyId = 1; + + TestLicenseBuilder builder; + builder.GetSettings().padding = TestLicenseBuilder::Padding::kPKSC8; + builder.GetSettings().provider_key_id = kProviderKeyId; + + builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey()); + builder.AddContentKey(golden_data_.CBCContent().software_crypto_key); + builder.Build(*server_, &license_); + + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kProviderKeyId, license_.request.data(), + license_.request.size()), + WB_RESULT_OK); +} + +TEST_F(LicenseWhiteboxProcessLicenseResponseTest, InvalidProviderKey) { + // Other tests pass in kNoProviderKeyId (0). However, invalid keys should also + // be treated as if no key is provided. It is expected to only have a small + // number of provider keys (starting at index 1), so pick a large number. + const size_t kInvalidProviderKey = 0xfff; + UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone); + + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kInvalidProviderKey, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } class LicenseWhiteboxProcessLicenseResponseErrorTest @@ -145,7 +190,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, license_.core_message.size(), license_.message.data(), license_.message.size(), license_.signature.data(), license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), license_.request.data(), + license_.session_key.size(), kNoProviderKeyId, license_.request.data(), license_.request.size()); // Depending on where/how the message is verified, an implementation can @@ -159,14 +204,15 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidSignatureForModifedSignature) { Modify(&license_.signature); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_INVALID_SIGNATURE); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_SIGNATURE); } // The license request is used to derive the signing key. If the request was @@ -175,14 +221,15 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidSignatureForModifedLicenseRequest) { Modify(&license_.request); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_INVALID_SIGNATURE); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_SIGNATURE); } // If the session key is modified, unwrapping it will fail. Therefore, we will @@ -193,26 +240,28 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidSignatureForModifedSessionKey) { Modify(&license_.session_key); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_INVALID_SIGNATURE); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_SIGNATURE); } TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidParameterForNullWhitebox) { - ASSERT_EQ(WB_License_ProcessLicenseResponse( - nullptr, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_INVALID_PARAMETER); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + nullptr, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, @@ -223,7 +272,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, license_.core_message.size(), nullptr, license_.message.size(), license_.signature.data(), license_.signature.size(), license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), + kNoProviderKeyId, license_.request.data(), license_.request.size()), WB_RESULT_INVALID_PARAMETER); } @@ -235,7 +284,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, license_.core_message.size(), license_.message.data(), 0, license_.signature.data(), license_.signature.size(), license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), + kNoProviderKeyId, license_.request.data(), license_.request.size()), WB_RESULT_INVALID_PARAMETER); } @@ -247,7 +296,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, license_.core_message.size(), license_.message.data(), license_.message.size(), nullptr, license_.signature.size(), license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), + kNoProviderKeyId, license_.request.data(), license_.request.size()), WB_RESULT_INVALID_PARAMETER); } @@ -259,7 +308,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, license_.core_message.size(), license_.message.data(), license_.message.size(), license_.signature.data(), 5, license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), + kNoProviderKeyId, license_.request.data(), license_.request.size()), WB_RESULT_INVALID_PARAMETER); } @@ -271,7 +320,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, license_.core_message.size(), license_.message.data(), license_.message.size(), license_.signature.data(), license_.signature.size(), nullptr, license_.session_key.size(), - license_.request.data(), license_.request.size()), + kNoProviderKeyId, license_.request.data(), license_.request.size()), WB_RESULT_INVALID_PARAMETER); } @@ -283,32 +332,32 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, license_.core_message.size(), license_.message.data(), license_.message.size(), license_.signature.data(), license_.signature.size(), license_.session_key.data(), 5, - license_.request.data(), license_.request.size()), + kNoProviderKeyId, license_.request.data(), license_.request.size()), WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidParameterForNullLicenseRequest) { - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), - license_.core_message.size(), license_.message.data(), - license_.message.size(), license_.signature.data(), - license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), nullptr, license_.request.size()), - WB_RESULT_INVALID_PARAMETER); + ASSERT_EQ(WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, + license_.core_message.data(), license_.core_message.size(), + license_.message.data(), license_.message.size(), + license_.signature.data(), license_.signature.size(), + license_.session_key.data(), license_.session_key.size(), + kNoProviderKeyId, nullptr, license_.request.size()), + WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidParameterForZeroLienseRequestSize) { - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), - license_.core_message.size(), license_.message.data(), - license_.message.size(), license_.signature.data(), - license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), license_.request.data(), 0), - WB_RESULT_INVALID_PARAMETER); + ASSERT_EQ(WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, + license_.core_message.data(), license_.core_message.size(), + license_.message.data(), license_.message.size(), + license_.signature.data(), license_.signature.size(), + license_.session_key.data(), license_.session_key.size(), + kNoProviderKeyId, license_.request.data(), 0), + WB_RESULT_INVALID_PARAMETER); } class LicenseWhiteboxMultiLicenseTest @@ -328,25 +377,27 @@ class LicenseWhiteboxMultiLicenseTest TEST_F(LicenseWhiteboxMultiLicenseTest, InvalidState) { // Load the first license. This one is expected to succeed as the whitebox has // not loaded a license yet. - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); // Attempt to load the same license again. This should fail as it already has // a license (even though it is the same license). - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), - WB_RESULT_INVALID_STATE); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_STATE); } // Even though a whitebox can only load a license once, if it fails to load a @@ -356,25 +407,26 @@ TEST_F(LicenseWhiteboxMultiLicenseTest, SuccessAfterFailure) { // in key derivation which is a later step of license parsing. std::vector bad_request = license_.request; Modify(&bad_request); - ASSERT_NE( - WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), - license_.core_message.size(), license_.message.data(), - license_.message.size(), license_.signature.data(), - license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), bad_request.data(), bad_request.size()), - WB_RESULT_OK); - - // Attempt to load the license again, but use the correct (unmodified) - // request. - ASSERT_EQ(WB_License_ProcessLicenseResponse( + ASSERT_NE(WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), license_.core_message.size(), license_.message.data(), license_.message.size(), license_.signature.data(), license_.signature.size(), license_.session_key.data(), license_.session_key.size(), - license_.request.data(), license_.request.size()), + kNoProviderKeyId, bad_request.data(), bad_request.size()), WB_RESULT_OK); + + // Attempt to load the license again, but use the correct (unmodified) + // request. + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } } // namespace widevine diff --git a/whitebox/api/license_whitebox_provider_keys_test_data.h b/whitebox/api/license_whitebox_provider_keys_test_data.h new file mode 100644 index 0000000..4454866 --- /dev/null +++ b/whitebox/api/license_whitebox_provider_keys_test_data.h @@ -0,0 +1,16 @@ +// Copyright 2021 Google LLC. All Rights Reserved. + +#ifndef WHITEBOX_API_LICENSE_WHITEBOX_PROVIDER_KEYS_TEST_DATA_H_ +#define WHITEBOX_API_LICENSE_WHITEBOX_PROVIDER_KEYS_TEST_DATA_H_ + +#include +#include + +namespace widevine { + +// Returns init data that the license white-box will accept. +std::vector GetLicenseWhiteboxProviderKeysInitData(); + +} // namespace widevine + +#endif // WHITEBOX_API_LICENSE_WHITEBOX_PROVIDER_KEYS_TEST_DATA_H_ diff --git a/whitebox/api/license_whitebox_query_content_key_status_test.cc b/whitebox/api/license_whitebox_query_content_key_status_test.cc index d6bb74c..b6de010 100644 --- a/whitebox/api/license_whitebox_query_content_key_status_test.cc +++ b/whitebox/api/license_whitebox_query_content_key_status_test.cc @@ -76,7 +76,7 @@ class LicenseWhiteboxQueryContentKeyStatus license.core_message.size(), license.message.data(), license.message.size(), license.signature.data(), license.signature.size(), license.session_key.data(), - license.session_key.size(), license.request.data(), + license.session_key.size(), kNoProviderKeyId, license.request.data(), license.request.size()); } diff --git a/whitebox/api/license_whitebox_query_signing_key_status_test.cc b/whitebox/api/license_whitebox_query_signing_key_status_test.cc index bbc2028..d0f6f54 100644 --- a/whitebox/api/license_whitebox_query_signing_key_status_test.cc +++ b/whitebox/api/license_whitebox_query_signing_key_status_test.cc @@ -73,7 +73,7 @@ class LicenseWhiteboxQuerySigningKeyStatus license.core_message.size(), license.message.data(), license.message.size(), license.signature.data(), license.signature.size(), license.session_key.data(), - license.session_key.size(), license.request.data(), + license.session_key.size(), kNoProviderKeyId, license.request.data(), license.request.size()); } diff --git a/whitebox/api/license_whitebox_security_level_test.cc b/whitebox/api/license_whitebox_security_level_test.cc index adbc3aa..bbf7fc6 100644 --- a/whitebox/api/license_whitebox_security_level_test.cc +++ b/whitebox/api/license_whitebox_security_level_test.cc @@ -62,14 +62,15 @@ TEST_P(LicenseWhiteboxSecurityLevelTest, CanLoadAndUseKey) { License license; builder.Build(*server, &license); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(), + license.core_message.size(), license.message.data(), + license.message.size(), license.signature.data(), + license.signature.size(), license.session_key.data(), + license.session_key.size(), kNoProviderKeyId, license.request.data(), + license.request.size()), + WB_RESULT_OK); plaintext_size_ = golden_data_.CBCContent().ciphertext.size(); plaintext_.resize(plaintext_size_); diff --git a/whitebox/api/license_whitebox_sign_benchmark.cc b/whitebox/api/license_whitebox_sign_benchmark.cc index 7754111..8f56418 100644 --- a/whitebox/api/license_whitebox_sign_benchmark.cc +++ b/whitebox/api/license_whitebox_sign_benchmark.cc @@ -8,6 +8,7 @@ #include "api/license_whitebox.h" #include "api/license_whitebox_benchmark.h" +#include "api/license_whitebox_provider_keys_test_data.h" #include "api/result.h" #include "api/test_license_builder.h" #include "benchmarking/data_source.h" @@ -35,17 +36,19 @@ class LicenseWhiteboxSignBenchmark key_mode_ = GetParam(); - ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); + auto init_data = GetLicenseWhiteboxProviderKeysInitData(); + ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_), + WB_RESULT_OK); - const auto license = - CreateLicense(key_mode_, 1, SecurityLevel::kSoftwareSecureCrypto); + const auto license = CreateLicense( + key_mode_, 1, SecurityLevel::kSoftwareSecureCrypto, kNoProviderKeyId); ASSERT_EQ(WB_License_ProcessLicenseResponse( whitebox_, key_mode_, license.core_message.data(), license.core_message.size(), license.message.data(), license.message.size(), license.signature.data(), license.signature.size(), license.session_key.data(), - license.session_key.size(), license.request.data(), - license.request.size()), + license.session_key.size(), kNoProviderKeyId, + license.request.data(), license.request.size()), WB_RESULT_OK); } diff --git a/whitebox/api/license_whitebox_sign_renewal_request_test.cc b/whitebox/api/license_whitebox_sign_renewal_request_test.cc index a9ace5e..ee68929 100644 --- a/whitebox/api/license_whitebox_sign_renewal_request_test.cc +++ b/whitebox/api/license_whitebox_sign_renewal_request_test.cc @@ -44,14 +44,15 @@ class LicenseWhiteboxSignRenewalPstTest License license; builder.Build(*server, &license); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, + license.core_message.data(), license.core_message.size(), + license.message.data(), license.message.size(), + license.signature.data(), license.signature.size(), + license.session_key.data(), license.session_key.size(), + kNoProviderKeyId, license.request.data(), license.request.size()), + WB_RESULT_OK); } // Get the expected signature for |message|. By returning the message, this @@ -226,14 +227,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, KeyUnavailableForNoSigningKey) { License license; builder.Build(*server, &license); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(), + license.core_message.size(), license.message.data(), + license.message.size(), license.signature.data(), + license.signature.size(), license.session_key.data(), + license.session_key.size(), kNoProviderKeyId, license.request.data(), + license.request.size()), + WB_RESULT_OK); ASSERT_EQ( sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(), diff --git a/whitebox/api/license_whitebox_test_base.cc b/whitebox/api/license_whitebox_test_base.cc index 46a3609..5479078 100644 --- a/whitebox/api/license_whitebox_test_base.cc +++ b/whitebox/api/license_whitebox_test_base.cc @@ -2,12 +2,15 @@ #include "api/license_whitebox_test_base.h" +#include "api/license_whitebox_provider_keys_test_data.h" #include "api/test_license_whitebox_keys.h" namespace widevine { void LicenseWhiteboxTestBase::SetUp() { - ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); + auto init_data = GetLicenseWhiteboxProviderKeysInitData(); + ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_), + WB_RESULT_OK); } void LicenseWhiteboxTestBase::TearDown() { diff --git a/whitebox/api/license_whitebox_uat_test.cc b/whitebox/api/license_whitebox_uat_test.cc index 2f9ceb4..b4f3542 100644 --- a/whitebox/api/license_whitebox_uat_test.cc +++ b/whitebox/api/license_whitebox_uat_test.cc @@ -5,6 +5,7 @@ #include #include "api/license_whitebox.h" +#include "api/license_whitebox_provider_keys_test_data.h" #include "testing/gtest/include/gtest/gtest.h" namespace widevine { @@ -342,6 +343,9 @@ const uint8_t kIv[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const size_t kIvSize = sizeof(kIv); + +const size_t kNoProviderKeyId = 0; + } // namespace class LicenseWhiteboxDecryptUatTest : public ::testing::Test { @@ -352,14 +356,16 @@ class LicenseWhiteboxDecryptUatTest : public ::testing::Test { }; TEST_F(LicenseWhiteboxDecryptUatTest, CryptoKeyWithCbcDataInCbcMode) { - ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); + auto init_data = GetLicenseWhiteboxProviderKeysInitData(); + ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_), + WB_RESULT_OK); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, kCoreMessage, - kCoreMessageSize, kMessage, kMessageSize, kSignature, kSignatureSize, - kSessionKey, kSessionKeySize, kLicenseRequest, kLicenseRequestSize), - WB_RESULT_OK); + ASSERT_EQ(WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, kCoreMessage, + kCoreMessageSize, kMessage, kMessageSize, kSignature, + kSignatureSize, kSessionKey, kSessionKeySize, kNoProviderKeyId, + kLicenseRequest, kLicenseRequestSize), + WB_RESULT_OK); size_t plaintext_size = kCiphertextSize; std::vector plaintext(plaintext_size); diff --git a/whitebox/api/license_whitebox_verify_benchmark.cc b/whitebox/api/license_whitebox_verify_benchmark.cc index 0a6e0c8..284574b 100644 --- a/whitebox/api/license_whitebox_verify_benchmark.cc +++ b/whitebox/api/license_whitebox_verify_benchmark.cc @@ -8,6 +8,7 @@ #include "api/license_whitebox.h" #include "api/license_whitebox_benchmark.h" +#include "api/license_whitebox_provider_keys_test_data.h" #include "api/result.h" #include "api/test_license_builder.h" #include "benchmarking/data_source.h" @@ -27,18 +28,22 @@ class LicenseWhiteboxVerifyBenchmark : public LicenseWhiteboxBenchmark { message_ = Data().Get(kMessageSize); signature_ = SignAsServer(message_); - ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); - - const auto license = CreateLicense(WB_LICENSE_KEY_MODE_DUAL_KEY, 1, - SecurityLevel::kSoftwareSecureCrypto); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), + auto init_data = GetLicenseWhiteboxProviderKeysInitData(); + ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_), WB_RESULT_OK); + + const auto license = + CreateLicense(WB_LICENSE_KEY_MODE_DUAL_KEY, 1, + SecurityLevel::kSoftwareSecureCrypto, kNoProviderKeyId); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, + license.core_message.data(), license.core_message.size(), + license.message.data(), license.message.size(), + license.signature.data(), license.signature.size(), + license.session_key.data(), license.session_key.size(), + kNoProviderKeyId, license.request.data(), license.request.size()), + WB_RESULT_OK); } void TearDown() override { WB_License_Delete(whitebox_); } diff --git a/whitebox/api/license_whitebox_verify_renewal_response_test.cc b/whitebox/api/license_whitebox_verify_renewal_response_test.cc index bed9e88..02ecb2e 100644 --- a/whitebox/api/license_whitebox_verify_renewal_response_test.cc +++ b/whitebox/api/license_whitebox_verify_renewal_response_test.cc @@ -39,14 +39,15 @@ class LicenseWhiteboxVerifyRenewalResponseTest License license; builder.Build(*server, &license); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, + license.core_message.data(), license.core_message.size(), + license.message.data(), license.message.size(), + license.signature.data(), license.signature.size(), + license.session_key.data(), license.session_key.size(), + kNoProviderKeyId, license.request.data(), license.request.size()), + WB_RESULT_OK); } std::vector Sign(const std::vector& message) { @@ -236,14 +237,15 @@ TEST_F(LicenseWhiteboxVerifyRenewalResponseTest, License license; builder.Build(*server, &license); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - license.request.data(), license.request.size()), - WB_RESULT_OK); + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(), + license.core_message.size(), license.message.data(), + license.message.size(), license.signature.data(), + license.signature.size(), license.session_key.data(), + license.session_key.size(), kNoProviderKeyId, license.request.data(), + license.request.size()), + WB_RESULT_OK); ASSERT_EQ(WB_License_VerifyRenewalResponse(whitebox_, garbage_renewal_message_.data(), diff --git a/whitebox/api/remote_attestation_and_verification_test.cc b/whitebox/api/remote_attestation_and_verification_test.cc index c8d29bf..89557ab 100644 --- a/whitebox/api/remote_attestation_and_verification_test.cc +++ b/whitebox/api/remote_attestation_and_verification_test.cc @@ -151,7 +151,7 @@ class RemoteAttestationAndVerificationTest license.core_message.size(), license.message.data(), license.message.size(), license.signature.data(), license.signature.size(), license.session_key.data(), - license.session_key.size(), license.request.data(), + license.session_key.size(), kNoProviderKeyId, license.request.data(), license.request.size()); } diff --git a/whitebox/api/test_license_builder.cc b/whitebox/api/test_license_builder.cc index 4bb1084..755ddbe 100644 --- a/whitebox/api/test_license_builder.cc +++ b/whitebox/api/test_license_builder.cc @@ -6,6 +6,7 @@ #include #include +#include "api/test_license_provider_keys.h" #include "base/check.h" #include "base/check_op.h" #include "cdm/keys/certs.h" @@ -236,6 +237,44 @@ std::vector GetPadding(TestLicenseBuilder::Padding padding) { return {}; } +// Wrap the content key |unwrapped_content_key| using |provider_key_id| and +// |key_encryption_key|, as appropriate. +std::string WrapContentKey(const std::vector& unwrapped_content_key, + size_t provider_key_id, + const std::string& key_encryption_key, + const std::string& key_encryption_key_iv) { + auto provider_keys = GetProviderKeys(); + const bool provider_key_id_valid = + (provider_key_id >= 1 && provider_key_id <= provider_keys.size()); + + // If |provider_key_id| is used, encrypt the unwrapped key using the + // appropriate provider key. Otherwise, use |unwrapped_content_key| for the + // next step. + std::string provider_encrypted_key; + if (provider_key_id_valid) { + const auto& provider_key = provider_keys[provider_key_id - 1].key; + const std::string no_iv(16, 0); + provider_encrypted_key = + Encrypt(provider_key, no_iv, unwrapped_content_key); + } else { + provider_encrypted_key.assign(unwrapped_content_key.begin(), + unwrapped_content_key.end()); + } + + // Now apply the Key Encryption Key. + auto encrypted_key = Encrypt(key_encryption_key, key_encryption_key_iv, + provider_encrypted_key); + + // If |provider_key_id| is used, then mask the resulting key. + if (provider_key_id_valid) { + const auto& mask = provider_keys[provider_key_id - 1].mask; + for (size_t i = 0; i < encrypted_key.size(); ++i) + encrypted_key[i] ^= mask[i]; + } + + return encrypted_key; +} + void AddContentKeyToContainer(const ContentKeyData& key_data, const TestLicenseBuilder::Settings& settings, const std::string& container_key, @@ -271,9 +310,9 @@ void AddContentKeyToContainer(const ContentKeyData& key_data, auto padding = GetPadding(settings.padding); key.insert(key.end(), padding.begin(), padding.end()); - auto encrypted_key = Encrypt(container_key, key_iv, key); - - container->set_key(encrypted_key); + auto wrapped_content_key = + WrapContentKey(key, settings.provider_key_id, container_key, key_iv); + container->set_key(wrapped_content_key); if (settings.content_key_key_size_override) { container->mutable_key()->resize(settings.content_key_key_size); @@ -456,6 +495,10 @@ void TestLicenseBuilder::Build(const TestServer& server, break; } + if (settings_.provider_key_id != kNoProviderKeyId) { + response.set_provider_key_id(settings_.provider_key_id); + } + for (const auto& key : signing_keys_) { AddSigningKeyToContainer(key, settings_, container_key_, response.add_key()); diff --git a/whitebox/api/test_license_builder.h b/whitebox/api/test_license_builder.h index f758a56..cb03083 100644 --- a/whitebox/api/test_license_builder.h +++ b/whitebox/api/test_license_builder.h @@ -13,6 +13,8 @@ namespace widevine { +constexpr size_t kNoProviderKeyId = 0; + struct License { std::vector request; @@ -101,6 +103,11 @@ class TestLicenseBuilder { bool signing_key_key_size_override = false; size_t signing_key_key_size = 64; size_t signing_key_iv_size = 16; + + // If required, use a ProviderKey when encrypting the content keys. + // By default, no Provider key is used. Note that the list of available + // provider keys is fixed. + size_t provider_key_id = kNoProviderKeyId; }; // Returns a default signing key that can be used with AddSigningKey(). diff --git a/whitebox/api/test_license_provider_keys.cc b/whitebox/api/test_license_provider_keys.cc new file mode 100644 index 0000000..ecd031b --- /dev/null +++ b/whitebox/api/test_license_provider_keys.cc @@ -0,0 +1,23 @@ +// Copyright 2021 Google LLC. All Rights Reserved. + +#include "api/test_license_provider_keys.h" + +namespace widevine { + +std::vector GetProviderKeys() { + // Note that both mask and key must be 16 bytes each. + // This data must match what is provided to the whitebox in + // GetLicenseWhiteboxProviderKeysInitData(). + return { + {// provider key 1 + {0xd0, 0xc6, 0x91, 0xd7, 0x1d, 0xfd, 0xfb, 0x12, 0xa3, 0x41, 0x65, 0x68, + 0x34, 0x72, 0xe5, 0xf6}, + "ProviderKey12345"}, + {// provider key 2 + {0x67, 0x51, 0xa8, 0x7f, 0xe9, 0x9e, 0x28, 0xe4, 0x46, 0x7b, 0x8b, 0x7c, + 0x7e, 0x69, 0xc6, 0x5e}, + "ProviderKey23456"}, + }; +} + +} // namespace widevine diff --git a/whitebox/api/test_license_provider_keys.h b/whitebox/api/test_license_provider_keys.h new file mode 100644 index 0000000..abb8f7f --- /dev/null +++ b/whitebox/api/test_license_provider_keys.h @@ -0,0 +1,21 @@ +// Copyright 2021 Google LLC. All Rights Reserved. + +#ifndef WHITEBOX_API_TEST_LICENSE_PROVIDER_KEYS_H_ +#define WHITEBOX_API_TEST_LICENSE_PROVIDER_KEYS_H_ + +#include +#include +#include + +namespace widevine { + +struct ProviderKey { + std::vector mask; + std::string key; +}; + +std::vector GetProviderKeys(); + +} // namespace widevine + +#endif // WHITEBOX_API_TEST_LICENSE_PROVIDER_KEYS_H_ diff --git a/whitebox/api/test_license_whitebox_keys_general.cc b/whitebox/api/test_license_whitebox_keys_general.cc index 3d2c914..5c9e39d 100644 --- a/whitebox/api/test_license_whitebox_keys_general.cc +++ b/whitebox/api/test_license_whitebox_keys_general.cc @@ -4,6 +4,8 @@ #include "api/test_license_whitebox_keys.h" +#include + namespace widevine { namespace { diff --git a/whitebox/api/test_license_whitebox_keys_uat.cc b/whitebox/api/test_license_whitebox_keys_uat.cc index 0de2110..87f821e 100644 --- a/whitebox/api/test_license_whitebox_keys_uat.cc +++ b/whitebox/api/test_license_whitebox_keys_uat.cc @@ -2,6 +2,8 @@ #include "api/test_license_whitebox_keys.h" +#include + namespace widevine { namespace { diff --git a/whitebox/chromium_deps/cdm/protos/defs/license_protocol.proto b/whitebox/chromium_deps/cdm/protos/defs/license_protocol.proto index 5975bb3..8dff7ea 100644 --- a/whitebox/chromium_deps/cdm/protos/defs/license_protocol.proto +++ b/whitebox/chromium_deps/cdm/protos/defs/license_protocol.proto @@ -285,6 +285,9 @@ message License { [default = PLATFORM_NO_VERIFICATION]; // IDs of the groups for which keys are delivered in this license, if any. repeated bytes group_ids = 11; + // Optional: The provider key id indicates which provider key was used + // during provider key encryption. + optional uint32 provider_key_id = 13; } enum ProtocolVersion { diff --git a/whitebox/crypto_utils/aes_cbc_decryptor.cc b/whitebox/crypto_utils/aes_cbc_decryptor.cc index 116b46f..7e1026b 100644 --- a/whitebox/crypto_utils/aes_cbc_decryptor.cc +++ b/whitebox/crypto_utils/aes_cbc_decryptor.cc @@ -23,7 +23,8 @@ bool AesCbcDecryptor::SetKey(const uint8_t* key, size_t key_size) { LOG(WARNING) << "Incorrect key size " << key_size; return false; } - if (AES_set_decrypt_key(key, key_size * 8, &aes_key_) != 0) { + if (AES_set_decrypt_key(key, static_cast(key_size * 8), &aes_key_) != + 0) { LOG(WARNING) << "Invalid AES key."; return false; } diff --git a/whitebox/crypto_utils/aes_cbc_encryptor.cc b/whitebox/crypto_utils/aes_cbc_encryptor.cc index c7ca79a..9ff6bb6 100644 --- a/whitebox/crypto_utils/aes_cbc_encryptor.cc +++ b/whitebox/crypto_utils/aes_cbc_encryptor.cc @@ -23,7 +23,8 @@ bool AesCbcEncryptor::SetKey(const uint8_t* key, size_t key_size) { LOG(WARNING) << "Incorrect key size " << key_size; return false; } - if (AES_set_encrypt_key(key, key_size * 8, &aes_key_) != 0) { + if (AES_set_encrypt_key(key, static_cast(key_size * 8), &aes_key_) != + 0) { LOG(WARNING) << "Invalid AES key."; return false; } diff --git a/whitebox/crypto_utils/aes_ctr_encryptor.cc b/whitebox/crypto_utils/aes_ctr_encryptor.cc index b94d82d..0f303f4 100644 --- a/whitebox/crypto_utils/aes_ctr_encryptor.cc +++ b/whitebox/crypto_utils/aes_ctr_encryptor.cc @@ -35,7 +35,8 @@ bool AesCtrEncryptor::SetKey(const uint8_t* key, size_t key_size) { LOG(WARNING) << "Incorrect key size " << key_size; return false; } - if (AES_set_encrypt_key(key, key_size * 8, &aes_key_) != 0) { + if (AES_set_encrypt_key(key, static_cast(key_size * 8), &aes_key_) != + 0) { LOG(WARNING) << "Invalid AES key."; return false; } diff --git a/whitebox/crypto_utils/crypto_util.cc b/whitebox/crypto_utils/crypto_util.cc index 9a08e27..cde009e 100644 --- a/whitebox/crypto_utils/crypto_util.cc +++ b/whitebox/crypto_utils/crypto_util.cc @@ -57,7 +57,7 @@ std::string CreateSignatureHmacSha256(absl::string_view key, absl::string_view message) { HMAC_CTX ctx; HMAC_CTX_init(&ctx); - HMAC_Init(&ctx, key.data(), key.size(), EVP_sha256()); + HMAC_Init(&ctx, key.data(), static_cast(key.size()), EVP_sha256()); HMAC_Update(&ctx, reinterpret_cast(message.data()), message.size()); unsigned char digest[SHA256_DIGEST_LENGTH]; @@ -80,7 +80,7 @@ std::string CreateSignatureHmacSha1(absl::string_view key, absl::string_view message) { HMAC_CTX ctx; HMAC_CTX_init(&ctx); - HMAC_Init(&ctx, key.data(), key.size(), EVP_sha1()); + HMAC_Init(&ctx, key.data(), static_cast(key.size()), EVP_sha1()); HMAC_Update(&ctx, reinterpret_cast(message.data()), message.size()); unsigned char digest[SHA_DIGEST_LENGTH]; diff --git a/whitebox/crypto_utils/private_key_util.h b/whitebox/crypto_utils/private_key_util.h index f9686b5..fa8fdd1 100644 --- a/whitebox/crypto_utils/private_key_util.h +++ b/whitebox/crypto_utils/private_key_util.h @@ -39,7 +39,7 @@ bool SerializeKey(const Key* key, } bool success = false; if (serialization_func(bio, const_cast(key)) != 0) { - int serialized_size = BIO_pending(bio); + int serialized_size = static_cast(BIO_pending(bio)); serialized_key->assign(serialized_size, 0); if (BIO_read(bio, &(*serialized_key)[0], serialized_size) == serialized_size) { @@ -67,7 +67,7 @@ bool DeserializeKey(const std::string& serialized_key, return false; } BIO* bio = BIO_new_mem_buf(const_cast(serialized_key.data()), - serialized_key.size()); + static_cast(serialized_key.size())); if (bio == nullptr) { LOG(ERROR) << "BIO_new_mem_buf returned nullptr"; return false; diff --git a/whitebox/crypto_utils/rsa_util.cc b/whitebox/crypto_utils/rsa_util.cc index e30ff7d..eae8cb6 100644 --- a/whitebox/crypto_utils/rsa_util.cc +++ b/whitebox/crypto_utils/rsa_util.cc @@ -101,7 +101,7 @@ bool SerializePrivateKeyInfo(const RSA* private_key, goto cleanup; } { - int serialized_size = BIO_pending(bio); + int serialized_size = static_cast(BIO_pending(bio)); serialized_private_key->assign(serialized_size, 0); if (BIO_read(bio, &(*serialized_private_key)[0], serialized_size) != serialized_size) { @@ -137,7 +137,7 @@ bool DeserializePrivateKeyInfo(const std::string& serialized_private_key, // mechanism via d2i_PKCS8PrivateKey_bio is broken in the current openssl // version (1.0.0c). Please refer to b/8560683. BIO* bio = BIO_new_mem_buf(const_cast(serialized_private_key.data()), - serialized_private_key.size()); + static_cast(serialized_private_key.size())); if (bio == nullptr) { LOG(ERROR) << "BIO_new_mem_buf returned nullptr"; return false; @@ -226,14 +226,14 @@ bool SerializeEncryptedPrivateKeyInfo(const RSA* private_key, LOG(ERROR) << "BIO_new returned nullptr."; goto cleanup; } - if (i2d_PKCS8PrivateKey_bio(bio, evp, EVP_aes_256_cbc(), - const_cast(passphrase.data()), - passphrase.size(), nullptr, nullptr) == 0) { + if (i2d_PKCS8PrivateKey_bio( + bio, evp, EVP_aes_256_cbc(), const_cast(passphrase.data()), + static_cast(passphrase.size()), nullptr, nullptr) == 0) { LOG(ERROR) << "i2d_PKCS8PrivateKey_bio failed."; goto cleanup; } { - int serialized_size = BIO_pending(bio); + int serialized_size = static_cast(BIO_pending(bio)); serialized_private_key->assign(serialized_size, 0); if (BIO_read(bio, &(*serialized_private_key)[0], serialized_size) != serialized_size) { @@ -259,7 +259,7 @@ int get_password(char* buf, int size, int rwflag, void* u) { const std::string* pass(static_cast(u)); if (!pass->empty() && size >= static_cast(pass->size())) { memcpy(buf, pass->data(), pass->size()); - return pass->size(); + return static_cast(pass->size()); } return 0; } @@ -282,7 +282,7 @@ bool DeserializeEncryptedPrivateKeyInfo( return false; } BIO* bio = BIO_new_mem_buf(const_cast(serialized_private_key.data()), - serialized_private_key.size()); + static_cast(serialized_private_key.size())); if (bio == nullptr) { LOG(ERROR) << "BIO_new_mem_buf returned nullptr"; return false; diff --git a/whitebox/external/odk.BUILD b/whitebox/external/odk.BUILD index 9cb9a06..97a5ad5 100644 --- a/whitebox/external/odk.BUILD +++ b/whitebox/external/odk.BUILD @@ -36,7 +36,7 @@ cc_library( "oemcrypto/odk/include/odk_structs.h", "oemcrypto/odk/include/odk_target.h", ], - copts = ["-std=c99"], + copts = ["-std=c99 -Wno-array-parameter"], includes = [ "oemcrypto/odk/include", ], diff --git a/whitebox/reference/impl/BUILD b/whitebox/reference/impl/BUILD index 26f02b9..1857991 100644 --- a/whitebox/reference/impl/BUILD +++ b/whitebox/reference/impl/BUILD @@ -144,6 +144,18 @@ cc_library( ], ) +# The "license_whitebox_provider_keys_test_data" target provides the data for +# the license whitebox init data (Provider Keys) defined in +# "api/license_whitebox_provider_keys_test_data.h". +cc_library( + name = "license_whitebox_provider_keys_test_data", + srcs = ["license_whitebox_provider_keys_test_data.cc"], + visibility = ["//visibility:public"], + deps = [ + "//api:license_whitebox_provider_keys_test_data", + ], +) + # ============================================================================== # AEAD White-box Targets # ============================================================================== diff --git a/whitebox/reference/impl/aead_whitebox_impl.cc b/whitebox/reference/impl/aead_whitebox_impl.cc index 390eb7c..fc9f956 100644 --- a/whitebox/reference/impl/aead_whitebox_impl.cc +++ b/whitebox/reference/impl/aead_whitebox_impl.cc @@ -46,7 +46,7 @@ std::vector DeriveKey(const WB_Aead_Whitebox* whitebox, // While we get the key size in bytes, DeriveKey() needs the key size in bits. const auto derived_key = widevine::crypto_util::DeriveKey( init_data_view, kLabel, context_view, - EVP_AEAD_key_length(whitebox->algorithm) * 8); + static_cast(EVP_AEAD_key_length(whitebox->algorithm) * 8)); return std::vector(derived_key.begin(), derived_key.end()); } diff --git a/whitebox/reference/impl/license_parser.cc b/whitebox/reference/impl/license_parser.cc index ae28d29..a2e5690 100644 --- a/whitebox/reference/impl/license_parser.cc +++ b/whitebox/reference/impl/license_parser.cc @@ -5,6 +5,7 @@ #include "base/check.h" #include "base/check_op.h" #include "crypto_utils/aes_cbc_decryptor.h" +#include "crypto_utils/crypto_util.h" namespace widevine { @@ -29,6 +30,51 @@ bool LicenseParser::Decrypt(const std::string& key, reinterpret_cast(&decrypted->front())); } +bool LicenseParser::UnwrapContentKey( + const std::string& wrapped_content_key, + const std::vector& provider_keys, + size_t provider_key_id, + const std::string& key_decryption_key, + const std::string& key_decryption_key_iv, + std::string* unwrapped_content_key) { + const bool provider_key_id_valid = + (provider_key_id >= 1 && provider_key_id <= provider_keys.size()); + + // If |provider_key_id| is used and valid, then start by unmasking it. + std::string key(wrapped_content_key); + if (provider_key_id_valid) { + const auto& mask = provider_keys[provider_key_id - 1].mask; + for (size_t i = 0; i < key.size(); ++i) + key[i] ^= mask[i]; + } + + // Now decrypt the key using the Key Encryption Key. + std::string unwrapped_key(key); + if (!Decrypt(key_decryption_key, key_decryption_key_iv, key, + &unwrapped_key)) { + DVLOG(1) << "Failed to decrypt content key using KEK."; + return false; + } + + // If |provider_key_id| not used, simply return the key decrypted so far. + if (!provider_key_id_valid) { + unwrapped_content_key->swap(unwrapped_key); + return true; + } + + // |provider_key_id| is used, so decrypt the unwrapped key using the + // appropriate provider key. + std::string final_key(unwrapped_key); + const auto& provider_key = provider_keys[provider_key_id - 1].key; + const std::string no_iv(16, 0); + if (!Decrypt(provider_key, no_iv, unwrapped_key, &final_key)) { + DVLOG(1) << "Failed to decrypt content key using Provider Key."; + return false; + } + unwrapped_content_key->swap(final_key); + return true; +} + ContentKey LicenseParser::CreateContentKey( video_widevine::License_KeyContainer_SecurityLevel level, bool is_hw_verified, diff --git a/whitebox/reference/impl/license_parser.h b/whitebox/reference/impl/license_parser.h index e7aa8d6..cb11ec9 100644 --- a/whitebox/reference/impl/license_parser.h +++ b/whitebox/reference/impl/license_parser.h @@ -5,6 +5,7 @@ #include #include +#include #include "license_protocol.pb.h" #include "reference/impl/content_key.h" #include "reference/impl/odk.h" @@ -14,6 +15,11 @@ namespace widevine { class LicenseParser { public: + struct ProviderKey { + std::vector mask; + std::string key; + }; + LicenseParser() = default; virtual ~LicenseParser() = default; @@ -21,9 +27,14 @@ class LicenseParser { LicenseParser(const LicenseParser&) = delete; LicenseParser& operator=(const LicenseParser&) = delete; + // If |provider_key_id| is valid, then use the appropriate provider key + // when extracting the content keys. If invalid, then assume no provider + // key was used. virtual WB_Result Parse(const std::string& decryption_key, const ODKContext& odk_context, - const std::string& message) = 0; + const std::string& message, + const std::vector& provider_keys, + size_t provider_key_id) = 0; // If there is no renewal key, then `nullptr` should be returned. virtual const widevine::RenewalKey* GetRenewalKey() const = 0; @@ -36,6 +47,16 @@ class LicenseParser { const std::string& encrypted, std::string* decrypted); + // Unwrap key |wrapped_content_key| using |provider_key_id| and + // |key_decryption_key|, as necessary. Returns true and + // |unwrapped_content_key| is updated on success, false otherwise. + static bool UnwrapContentKey(const std::string& wrapped_content_key, + const std::vector& provider_keys, + size_t provider_key_id, + const std::string& key_decryption_key, + const std::string& key_decryption_key_iv, + std::string* unwrapped_content_key); + // Creates and returns a ContentKey based on the values provided. // |level| determines whether decrypt or masked_decrypt is allowed. // |is_hw_verified|, if set, overrides |level| so that both decrypt and diff --git a/whitebox/reference/impl/license_whitebox_impl.cc b/whitebox/reference/impl/license_whitebox_impl.cc index 64df28e..f65dfc3 100644 --- a/whitebox/reference/impl/license_whitebox_impl.cc +++ b/whitebox/reference/impl/license_whitebox_impl.cc @@ -108,6 +108,8 @@ struct WB_License_Whitebox { std::unique_ptr renewal_key; std::map content_keys; + + std::vector provider_keys; }; namespace { @@ -226,14 +228,43 @@ std::unique_ptr LoadPrivateKey( return std::unique_ptr(RsaPrivateKey::Create(key_string)); } +std::vector CreateProviderKeys( + const uint8_t* whitebox_init_data, + size_t whitebox_init_data_size) { + std::vector result; + for (size_t i = 0; i < whitebox_init_data_size / 32; ++i) { + widevine::LicenseParser::ProviderKey provider_key; + provider_key.mask.assign(whitebox_init_data, whitebox_init_data + 16); + provider_key.key.assign(whitebox_init_data + 16, whitebox_init_data + 32); + result.emplace_back(provider_key); + whitebox_init_data += 32; + } + return result; +} + } // namespace -WB_Result WB_License_Create(WB_License_Whitebox** whitebox) { +WB_Result WB_License_Create(const uint8_t* whitebox_init_data, + size_t whitebox_init_data_size, + WB_License_Whitebox** whitebox) { if (whitebox == nullptr) { DVLOG(1) << "Invalid parameter: null pointer."; return WB_RESULT_INVALID_PARAMETER; } + // whitebox_init_data is optional. + if (whitebox_init_data_size != 0 && whitebox_init_data == nullptr) { + DVLOG(1) << "Invalid parameter: Missing whitebox_init_data."; + return WB_RESULT_INVALID_PARAMETER; + } + // However, if specified, it must be a multiple of 32 bytes (as each Provider + // Key is a 16-byte mask followed by a 16-byte key). + if (whitebox_init_data_size % 32 != 0) { + DVLOG(1) << "Invalid parameter: whitebox_init_data_size must be a multiple " + "of 32."; + return WB_RESULT_INVALID_PARAMETER; + } + auto signing_key = LoadPrivateKey(widevine::GetSigningPrivateKey()); CHECK(signing_key) << "Failed to load (internal) signing private key."; @@ -245,6 +276,8 @@ WB_Result WB_License_Create(WB_License_Whitebox** whitebox) { *whitebox = new WB_License_Whitebox(); (*whitebox)->signing_key.swap(signing_key); (*whitebox)->encryption_key.swap(encryption_key); + (*whitebox)->provider_keys = + CreateProviderKeys(whitebox_init_data, whitebox_init_data_size); return WB_RESULT_OK; } @@ -303,6 +336,7 @@ WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox, size_t signature_size, const uint8_t* session_key, size_t session_key_size, + size_t provider_key_id, const uint8_t* license_request, size_t license_request_size) { const size_t kSigningKeySizeBytes = @@ -440,7 +474,8 @@ WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox, parser.reset(new widevine::ProtobufLicenseParser); } - WB_Result result = parser->Parse(decryption_key, odk_context, message_str); + WB_Result result = parser->Parse(decryption_key, odk_context, message_str, + whitebox->provider_keys, provider_key_id); if (result != WB_RESULT_OK) { return result; diff --git a/whitebox/reference/impl/license_whitebox_provider_keys_test_data.cc b/whitebox/reference/impl/license_whitebox_provider_keys_test_data.cc new file mode 100644 index 0000000..9d2934c --- /dev/null +++ b/whitebox/reference/impl/license_whitebox_provider_keys_test_data.cc @@ -0,0 +1,23 @@ +// Copyright 2021 Google LLC. All Rights Reserved. + +#include "api/license_whitebox_provider_keys_test_data.h" + +namespace widevine { + +std::vector GetLicenseWhiteboxProviderKeysInitData() { + // This data must match what is used by the test license server, provided by + // GetProviderKeys() in api/test_license_provider_keys.cc. Format of the + // data below is dependent on the whitebox implementation. + return { + 0xd0, 0xc6, 0x91, 0xd7, 0x1d, 0xfd, 0xfb, 0x12, // provider key 1 mask + 0xa3, 0x41, 0x65, 0x68, 0x34, 0x72, 0xe5, 0xf6, // + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, // provider key 1 key + 0x4b, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34, 0x35, // + 0x67, 0x51, 0xa8, 0x7f, 0xe9, 0x9e, 0x28, 0xe4, // provider key 2 mask + 0x46, 0x7b, 0x8b, 0x7c, 0x7e, 0x69, 0xc6, 0x5e, // + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, // provider key 2 key + 0x4b, 0x65, 0x79, 0x32, 0x33, 0x34, 0x35, 0x36, // + }; +} + +} // namespace widevine diff --git a/whitebox/reference/impl/odk_license_parser.cc b/whitebox/reference/impl/odk_license_parser.cc index afe8b51..0d0e97a 100644 --- a/whitebox/reference/impl/odk_license_parser.cc +++ b/whitebox/reference/impl/odk_license_parser.cc @@ -66,7 +66,9 @@ std::string ExtractItem(const OEMCrypto_Substring& item, WB_Result OdkLicenseParser::Parse(const std::string& decryption_key, const ODKContext& odk_context, - const std::string& message) { + const std::string& message, + const std::vector& provider_keys, + size_t provider_key_id) { // Extract the signing keys. const std::string signing_key_encrypted = ExtractItem(odk_context.license.enc_mac_keys, message); @@ -93,7 +95,8 @@ WB_Result OdkLicenseParser::Parse(const std::string& decryption_key, // Add the key right away. The key will be invalid, so if we fail to // parse the key, we'll already have an entry for the invalid key. - content_keys_[key_id] = ParseContentKey(decryption_key, message, key); + content_keys_[key_id] = ParseContentKey(decryption_key, message, key, + provider_keys, provider_key_id); } return WB_RESULT_OK; @@ -150,7 +153,9 @@ RenewalKey OdkLicenseParser::ParseSigningKeys(const std::string& decryption_key, ContentKey OdkLicenseParser::ParseContentKey( const std::string& decryption_key, const std::string& message, - const OEMCrypto_KeyObject& key) const { + const OEMCrypto_KeyObject& key, + const std::vector& provider_keys, + size_t provider_key_id) const { // This should have been verified before calling the parser. CHECK_EQ(decryption_key.size(), 16u) << "Incorrect decryption key size."; @@ -161,7 +166,7 @@ ContentKey OdkLicenseParser::ParseContentKey( return ContentKey(); } - const std::string wrapped_key = ExtractItem(key.key_data, message); + std::string wrapped_key = ExtractItem(key.key_data, message); // Unlike with protobufs, we don't need to handle padding here. The ODK will // not include the padding as part of the key's size. @@ -170,8 +175,9 @@ ContentKey OdkLicenseParser::ParseContentKey( return ContentKey(); } - std::string unwrapped_key(wrapped_key); - if (!Decrypt(decryption_key, iv, wrapped_key, &unwrapped_key)) { + std::string unwrapped_key; + if (!UnwrapContentKey(wrapped_key, provider_keys, provider_key_id, + decryption_key, iv, &unwrapped_key)) { VLOG(3) << "Failed to decrypt content key."; return ContentKey(); } diff --git a/whitebox/reference/impl/odk_license_parser.h b/whitebox/reference/impl/odk_license_parser.h index fb6ad9a..52881f2 100644 --- a/whitebox/reference/impl/odk_license_parser.h +++ b/whitebox/reference/impl/odk_license_parser.h @@ -3,6 +3,8 @@ #ifndef WHITEBOX_REFERENCE_IMPL_ODK_LICENSE_PARSER_H_ #define WHITEBOX_REFERENCE_IMPL_ODK_LICENSE_PARSER_H_ +#include + #include "reference/impl/content_key.h" #include "reference/impl/license_parser.h" @@ -12,7 +14,9 @@ class OdkLicenseParser : public LicenseParser { public: WB_Result Parse(const std::string& decryption_key, const ODKContext& odk_context, - const std::string& message) override; + const std::string& message, + const std::vector& provider_keys, + size_t provider_key_id) override; const widevine::RenewalKey* GetRenewalKey() const override; @@ -25,7 +29,9 @@ class OdkLicenseParser : public LicenseParser { ContentKey ParseContentKey(const std::string& decryption_key, const std::string& message, - const OEMCrypto_KeyObject& key) const; + const OEMCrypto_KeyObject& key, + const std::vector& provider_keys, + size_t provider_key_id) const; std::vector renewal_keys_; std::map content_keys_; diff --git a/whitebox/reference/impl/protobuf_license_parser.cc b/whitebox/reference/impl/protobuf_license_parser.cc index 523680c..c5a33e0 100644 --- a/whitebox/reference/impl/protobuf_license_parser.cc +++ b/whitebox/reference/impl/protobuf_license_parser.cc @@ -64,11 +64,15 @@ bool IsPlatformHardwareVerified(const video_widevine::License& license) { return table[vmp][ra] == 1; } + } // namespace -WB_Result ProtobufLicenseParser::Parse(const std::string& decryption_key, - const ODKContext& odk_context, - const std::string& message) { +WB_Result ProtobufLicenseParser::Parse( + const std::string& decryption_key, + const ODKContext& odk_context, + const std::string& message, + const std::vector& provider_keys, + size_t provider_key_id) { video_widevine::License license; if (!license.ParseFromString(message)) { VLOG(3) << "Invalid parameter: Invalid license."; @@ -101,8 +105,8 @@ WB_Result ProtobufLicenseParser::Parse(const std::string& decryption_key, if (key.id().empty()) { VLOG(3) << "Skipping content key : no key id."; } else { - content_keys_[key.id()] = - ParseContentKey(decryption_key, key, is_verified); + content_keys_[key.id()] = ParseContentKey( + decryption_key, key, is_verified, provider_keys, provider_key_id); } break; default: @@ -172,7 +176,9 @@ RenewalKey ProtobufLicenseParser::ParseSigningKey( ContentKey ProtobufLicenseParser::ParseContentKey( const std::string& decryption_key, const video_widevine::License_KeyContainer& key, - bool is_verified) const { + bool is_verified, + const std::vector& provider_keys, + size_t provider_key_id) const { // This should have been verified before calling the parser. CHECK_EQ(decryption_key.size(), 16u) << "Incorrect decryption key size."; CHECK_EQ(key.type(), video_widevine::License_KeyContainer::CONTENT); @@ -192,9 +198,9 @@ ContentKey ProtobufLicenseParser::ParseContentKey( } std::string wrapped_key = key.key().substr(0, kKeySizeWithoutPadding); - std::string unwrapped_key(wrapped_key); - - if (!Decrypt(decryption_key, key.iv(), wrapped_key, &unwrapped_key)) { + std::string unwrapped_key; + if (!UnwrapContentKey(wrapped_key, provider_keys, provider_key_id, + decryption_key, key.iv(), &unwrapped_key)) { VLOG(3) << "Failed to decrypt content key."; return ContentKey(); } diff --git a/whitebox/reference/impl/protobuf_license_parser.h b/whitebox/reference/impl/protobuf_license_parser.h index e39fb1c..a47cf47 100644 --- a/whitebox/reference/impl/protobuf_license_parser.h +++ b/whitebox/reference/impl/protobuf_license_parser.h @@ -13,7 +13,9 @@ class ProtobufLicenseParser : public LicenseParser { public: WB_Result Parse(const std::string& decryption_key, const ODKContext& odk_context, - const std::string& message) override; + const std::string& message, + const std::vector& provider_keys, + size_t provider_key_id) override; const widevine::RenewalKey* GetRenewalKey() const override; @@ -25,7 +27,9 @@ class ProtobufLicenseParser : public LicenseParser { ContentKey ParseContentKey(const std::string& decryption_key, const video_widevine::License_KeyContainer& key, - bool is_verified) const; + bool is_verified, + const std::vector& provider_keys, + size_t provider_key_id) const; private: std::vector renewal_keys_; diff --git a/whitebox/reference/tests/BUILD b/whitebox/reference/tests/BUILD index fe2cda1..88fa500 100644 --- a/whitebox/reference/tests/BUILD +++ b/whitebox/reference/tests/BUILD @@ -54,6 +54,7 @@ cc_test( deps = [ "//api:license_whitebox_test", "//reference/impl:general_license_whitebox_without_vmpra", + "//reference/impl:license_whitebox_provider_keys_test_data" ], ) @@ -63,6 +64,7 @@ cc_test( deps = [ "//api:remote_attestation_and_verification_with_vmpra_test", "//reference/impl:general_license_whitebox_with_vmpra", + "//reference/impl:license_whitebox_provider_keys_test_data" ], ) @@ -72,6 +74,7 @@ cc_test( deps = [ "//api:remote_attestation_and_verification_without_vmpra_test", "//reference/impl:general_license_whitebox_without_vmpra", + "//reference/impl:license_whitebox_provider_keys_test_data" ], ) @@ -81,6 +84,7 @@ cc_test( deps = [ "//api:license_whitebox_benchmark", "//reference/impl:general_license_whitebox_without_vmpra", + "//reference/impl:license_whitebox_provider_keys_test_data" ], ) @@ -90,5 +94,6 @@ cc_test( deps = [ "//api:license_whitebox_uat_test", "//reference/impl:uat_license_whitebox", + "//reference/impl:license_whitebox_provider_keys_test_data" ], )