From f936dd2983e101199320b05d640f1b320dda6446 Mon Sep 17 00:00:00 2001 From: Aaron Vaage Date: Mon, 5 Apr 2021 12:05:15 -0700 Subject: [PATCH] Add "License Key Mode" To API In order to support both single-key and dual-key RSA implementations where single-key will use key 0 for both sign and encryption and where dual-key will use key 0 for sign and key 1 for encryption. Additional changes in this code drop: - Added VMP / RA override enabled tests - Added VMP / RA override disabled tests This brings the partner repo in sync with the internal repo at commit 71760b6da1ec546c65b56e2f86b39b73b53f6734. --- whitebox-impl/impl/BUILD | 31 +- whitebox-impl/tests/BUILD | 32 +- whitebox/api/BUILD | 64 +- whitebox/api/license_whitebox.h | 17 + whitebox/api/license_whitebox_benchmark.cc | 10 +- whitebox/api/license_whitebox_benchmark.h | 4 +- .../api/license_whitebox_decrypt_benchmark.cc | 16 +- whitebox/api/license_whitebox_decrypt_test.cc | 22 +- ...license_whitebox_get_secret_string_test.cc | 22 +- ...license_whitebox_key_control_block_test.cc | 40 +- .../api/license_whitebox_license_key_mode.cc | 157 +++++ .../license_whitebox_masked_decrypt_test.cc | 22 +- ...ebox_process_license_response_benchmark.cc | 36 +- ...cess_license_response_core_message_test.cc | 184 ++--- ..._whitebox_process_license_response_test.cc | 343 ++++----- ..._whitebox_query_content_key_status_test.cc | 16 +- ..._whitebox_query_signing_key_status_test.cc | 15 +- .../license_whitebox_security_level_test.cc | 22 +- .../api/license_whitebox_sign_benchmark.cc | 16 +- ...ense_whitebox_sign_license_request_test.cc | 14 +- ...ense_whitebox_sign_renewal_request_test.cc | 44 +- whitebox/api/license_whitebox_test_base.cc | 8 - whitebox/api/license_whitebox_test_base.h | 2 - whitebox/api/license_whitebox_uat_test.cc | 11 +- .../api/license_whitebox_verify_benchmark.cc | 16 +- ...e_whitebox_verify_renewal_response_test.cc | 44 +- ...emote_attestation_and_verification_test.cc | 650 ++++++++++-------- whitebox/api/test_license_builder.cc | 17 +- whitebox/api/test_license_builder.h | 8 +- whitebox/api/test_license_whitebox_keys.h | 23 +- .../api/test_license_whitebox_keys_general.cc | 291 ++++++++ ...s.cc => test_license_whitebox_keys_uat.cc} | 34 +- whitebox/api/test_server.cc | 59 ++ whitebox/api/test_server.h | 40 ++ whitebox/reference/impl/BUILD | 105 ++- .../reference/impl/license_whitebox_impl.cc | 67 +- whitebox/reference/impl/odk_license_parser.cc | 5 +- whitebox/reference/impl/private_keys.cc | 24 + whitebox/reference/impl/private_keys.h | 29 + .../reference/impl/protobuf_license_parser.cc | 20 +- whitebox/reference/tests/BUILD | 32 +- 41 files changed, 1803 insertions(+), 809 deletions(-) create mode 100644 whitebox/api/license_whitebox_license_key_mode.cc create mode 100644 whitebox/api/test_license_whitebox_keys_general.cc rename whitebox/api/{test_license_whitebox_keys.cc => test_license_whitebox_keys_uat.cc} (92%) create mode 100644 whitebox/api/test_server.cc create mode 100644 whitebox/api/test_server.h create mode 100644 whitebox/reference/impl/private_keys.cc create mode 100644 whitebox/reference/impl/private_keys.h diff --git a/whitebox-impl/impl/BUILD b/whitebox-impl/impl/BUILD index 6cfc748..af074b1 100644 --- a/whitebox-impl/impl/BUILD +++ b/whitebox-impl/impl/BUILD @@ -7,20 +7,35 @@ # # test_aead_whitebox : The target for testing the AEAD white-box. # -# test_license_whitebox : The target for testing the license white-box. The -# white-box should use the private key provided in -# "//api/test_license_whitebox_keys.cc". +# general_license_whitebox_with_vmpra : The target for testing the license +# white-box against generated licenses with VMP/RA functionality. +# +# general_license_whitebox_without_vmpra : The target for testing the license +# white-box against generated licenses without VMP/RA functionality. +# +# uat_license_whitebox : The target for testing the license white-box against +# licenses from Widevine's UAT server. package(default_visibility = [ "//visibility:private", ]) cc_library( - name = "test_aead_whitebox", - visibility = ["//visibility:public"], + name = "test_aead_whitebox", + visibility = ["//visibility:public"], ) cc_library( - name = "test_license_whitebox", - visibility = ["//visibility:public"], -) \ No newline at end of file + name = "general_license_whitebox_with_vmpra", + visibility = ["//visibility:public"], +) + +cc_library( + name = "general_license_whitebox_without_vmpra", + visibility = ["//visibility:public"], +) + +cc_library( + name = "uat_license_whitebox", + visibility = ["//visibility:public"], +) diff --git a/whitebox-impl/tests/BUILD b/whitebox-impl/tests/BUILD index 952529c..f4f1898 100644 --- a/whitebox-impl/tests/BUILD +++ b/whitebox-impl/tests/BUILD @@ -13,9 +13,14 @@ package(default_visibility = [ # # test_aead_whitebox : The target for testing the AEAD white-box. # -# test_license_whitebox : The target for testing the license white-box. The -# white-box should use the private key provided in -# "//api/test_license_whitebox_keys.cc". +# general_license_whitebox_with_vmpra : The target for testing the license +# white-box against generated licenses with VMP/RA functionality. +# +# general_license_whitebox_without_vmpra : The target for testing the license +# white-box against generated licenses without VMP/RA functionality. +# +# uat_license_whitebox : The target for testing the license white-box against +# licenses from Widevine's UAT server. # ============================================================================== # AEAD Test Targets @@ -48,16 +53,25 @@ cc_test( size = "small", deps = [ "@whitebox_api//api:license_whitebox_test", - "//impl:test_license_whitebox", + "//impl:general_license_whitebox_without_vmpra", ], ) cc_test( - name = "remote_attestation_and_verification_test", + name = "remote_attestation_and_verification_with_vmpra_test", size = "small", deps = [ - "@whitebox_api//api:remote_attestation_and_verification_test", - "//impl:test_license_whitebox", + "@whitebox_api//api:remote_attestation_and_verification_with_vmpra_test", + "//impl:general_license_whitebox_with_vmpra", + ], +) + +cc_test( + name = "remote_attestation_and_verification_without_vmpra_test", + size = "small", + deps = [ + "@whitebox_api//api:remote_attestation_and_verification_without_vmpra_test", + "//impl:general_license_whitebox_without_vmpra", ], ) @@ -66,7 +80,7 @@ cc_test( size = "small", deps = [ "@whitebox_api//api:license_whitebox_benchmark", - "//impl:test_license_whitebox", + "//impl:general_license_whitebox_without_vmpra", ], ) @@ -75,6 +89,6 @@ cc_test( size = "small", deps = [ "@whitebox_api//api:license_whitebox_uat_test", - "//impl:test_license_whitebox", + "//impl:uat_license_whitebox", ], ) diff --git a/whitebox/api/BUILD b/whitebox/api/BUILD index 346d3f5..8f12f69 100644 --- a/whitebox/api/BUILD +++ b/whitebox/api/BUILD @@ -39,17 +39,36 @@ cc_library( ], ) +# This target provided the header needed to access the test keys. The +# implementation will be provided by "test_license_whitebox_keys_general" and +# "test_license_whitebox_keys_uat". Depending on which keys are needed, one of +# those targets will be used. cc_library( name = "test_license_whitebox_keys", - srcs = [ - "test_license_whitebox_keys.cc", - ], hdrs = [ "test_license_whitebox_keys.h", ], visibility = ["//visibility:public"], ) +cc_library( + name = "test_license_whitebox_keys_general", + srcs = [ + "test_license_whitebox_keys_general.cc", + ], + visibility = ["//visibility:public"], + deps = [":test_license_whitebox_keys"], +) + +cc_library( + name = "test_license_whitebox_keys_uat", + srcs = [ + "test_license_whitebox_keys_uat.cc", + ], + visibility = ["//visibility:public"], + deps = [":test_license_whitebox_keys"], +) + cc_library( name = "aead_test_data", hdrs = [ @@ -72,6 +91,17 @@ cc_library( ], ) +cc_library( + name = "test_server", + srcs = ["test_server.cc"], + hdrs = ["test_server.h"], + deps = [ + ":test_license_whitebox_keys", + "//chromium_deps/base:glog", + "//crypto_utils:rsa_key", + ], +) + cc_library( name = "test_license_builder", srcs = ["test_license_builder.cc"], @@ -79,11 +109,11 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":test_key_types", + ":test_server", "//chromium_deps/cdm/keys:dev_certs", "//chromium_deps/cdm/protos:license_protocol_proto", "//crypto_utils:aes_cbc_encryptor", "//crypto_utils:crypto_util", - "//crypto_utils:rsa_key", "//external:odk", ], ) @@ -146,6 +176,7 @@ cc_library( "license_whitebox_decrypt_test.cc", "license_whitebox_get_secret_string_test.cc", "license_whitebox_key_control_block_test.cc", + "license_whitebox_license_key_mode.cc", "license_whitebox_masked_decrypt_test.cc", "license_whitebox_process_license_response_core_message_test.cc", "license_whitebox_process_license_response_test.cc", @@ -167,17 +198,28 @@ cc_library( alwayslink = True, ) -# These tests should only be ran when using a VMP+RA supported white-box as -# they are testing that the white-box will reduce the key security level when -# RA + VMP are present. -# -# TODO(vaage): Create another version of these tests for the non-VMP+RA -# white-boxes to ensure that they are not reducing key security levels. cc_library( - name = "remote_attestation_and_verification_test", + name = "remote_attestation_and_verification_with_vmpra_test", srcs = [ "remote_attestation_and_verification_test.cc", ], + defines = ["WV_ENABLE_HW_VERIFICATION=1"], + visibility = ["//visibility:public"], + deps = [ + ":license_whitebox", + ":license_whitebox_test_base", + ":test_license_builder", + "//chromium_deps/testing", + ], + alwayslink = True, +) + +cc_library( + name = "remote_attestation_and_verification_without_vmpra_test", + srcs = [ + "remote_attestation_and_verification_test.cc", + ], + defines = ["WV_ENABLE_HW_VERIFICATION=0"], visibility = ["//visibility:public"], deps = [ ":license_whitebox", diff --git a/whitebox/api/license_whitebox.h b/whitebox/api/license_whitebox.h index 4db179c..db55213 100644 --- a/whitebox/api/license_whitebox.h +++ b/whitebox/api/license_whitebox.h @@ -48,6 +48,16 @@ typedef enum { WB_KEY_STATUS_CONTENT_KEY_DECRYPT, } WB_KeyStatus; +typedef enum { + // The license response uses single key - the license signing and encryption + // key are the same. + WB_LICENSE_KEY_MODE_SINGLE_KEY, + + // The license response uses two keys - the license signing and encryption + // key are different. + WB_LICENSE_KEY_MODE_DUAL_KEY, +} WB_LicenseKeyMode; + // Creates a new white-box instance using the implementation's internal private // key|. A pointer to the white-box instance will be returned via |whitebox|. // @@ -114,6 +124,12 @@ WB_Result WB_License_SignLicenseRequest(const WB_License_Whitebox* whitebox, // Args: // whitebox (in/out) : The white-box instance that will load the keys. // +// license_key_mode (in) : Signal for which private key to use when processing +// the license response. When |license_key_mode| is +// WB_LICENSE_KEY_MODE_SINGLE_KEY, the signing key should be used to decrypt +// the session key. When |license_key_mode| is WB_LICENSE_KEY_MODE_DUAL_KEY the +// encryption key should be used to decrypt the session key.. +// // core_message (in) : Serialized information communicating the structure of // |message|. Signature verification should be done on |core_message| + // |message|. @@ -166,6 +182,7 @@ WB_Result WB_License_SignLicenseRequest(const WB_License_Whitebox* whitebox, // 1. The key is considered value and is loaded. // 2. The key is considered invalid and is not loaded. WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox, + WB_LicenseKeyMode license_key_mode, const uint8_t* core_message, size_t core_message_size, const uint8_t* message, diff --git a/whitebox/api/license_whitebox_benchmark.cc b/whitebox/api/license_whitebox_benchmark.cc index e4ed96b..0e35c81 100644 --- a/whitebox/api/license_whitebox_benchmark.cc +++ b/whitebox/api/license_whitebox_benchmark.cc @@ -24,10 +24,10 @@ void LicenseWhiteboxBenchmark::SetUp() { key_ = data_source_.Get(); iv_ = data_source_.Get(); - const auto public_key_data = GetLicensePublicKey(); - public_key_.reset(RsaPublicKey::Create( + const auto public_key_data = GetEncryptionKey().public_key; + encryption_public_key_.reset(RsaPublicKey::Create( std::string(public_key_data.begin(), public_key_data.end()))); - ASSERT_TRUE(public_key_); + ASSERT_TRUE(encryption_public_key_); } License LicenseWhiteboxBenchmark::CreateLicense() const { @@ -38,8 +38,10 @@ License LicenseWhiteboxBenchmark::CreateLicense() const { license_builder.AddContentKey(SecurityLevel::kSoftwareSecureCrypto, key_id_, key_); + auto server = TestServer::CreateDualKey(); + License license; - license_builder.Build(*public_key_, &license); + license_builder.Build(*server, &license); return license; } diff --git a/whitebox/api/license_whitebox_benchmark.h b/whitebox/api/license_whitebox_benchmark.h index d773f5e..96f24c8 100644 --- a/whitebox/api/license_whitebox_benchmark.h +++ b/whitebox/api/license_whitebox_benchmark.h @@ -26,8 +26,6 @@ class LicenseWhiteboxBenchmark : public ::testing::Test { DataSource& Data() { return data_source_; } - const RsaPublicKey* PublicKey() const { return public_key_.get(); } - const KeyId& ContentKeyId() const { return key_id_; } const AesKey& ContentKey() const { return key_; } @@ -36,7 +34,7 @@ class LicenseWhiteboxBenchmark : public ::testing::Test { private: DataSource data_source_; - std::unique_ptr public_key_; + std::unique_ptr encryption_public_key_; KeyId key_id_; AesKey key_; diff --git a/whitebox/api/license_whitebox_decrypt_benchmark.cc b/whitebox/api/license_whitebox_decrypt_benchmark.cc index 3627846..5042774 100644 --- a/whitebox/api/license_whitebox_decrypt_benchmark.cc +++ b/whitebox/api/license_whitebox_decrypt_benchmark.cc @@ -46,14 +46,14 @@ class LicenseWhiteboxDecryptBenchmark ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); const auto license = CreateLicense(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + 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 1862ebe..356d761 100644 --- a/whitebox/api/license_whitebox_decrypt_test.cc +++ b/whitebox/api/license_whitebox_decrypt_test.cc @@ -60,17 +60,19 @@ class LicenseWhiteboxDecryptTest : public LicenseWhiteboxTestBase, builder.AddOperatorSessionKey(non_content_key_id_); - License license; - builder.Build(*public_key_, &license); + auto server = TestServer::CreateDualKey(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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); + 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); } // We need two special keys for this test, one that will be used for a diff --git a/whitebox/api/license_whitebox_get_secret_string_test.cc b/whitebox/api/license_whitebox_get_secret_string_test.cc index d2e271d..d833cb5 100644 --- a/whitebox/api/license_whitebox_get_secret_string_test.cc +++ b/whitebox/api/license_whitebox_get_secret_string_test.cc @@ -45,17 +45,19 @@ class LicenseWhiteboxGetSecretStringTest : public LicenseWhiteboxTestBase { builder.AddOperatorSessionKey(non_content_key_id_); - License license; - builder.Build(*public_key_, &license); + auto server = TestServer::CreateDualKey(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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); + 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); } // 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 4e3a421..248fef7 100644 --- a/whitebox/api/license_whitebox_key_control_block_test.cc +++ b/whitebox/api/license_whitebox_key_control_block_test.cc @@ -17,6 +17,8 @@ class LicenseWhiteboxKeyControlBlockTest void SetUp() override { LicenseWhiteboxTestBase::SetUp(); std::tie(kcb_, odk_) = GetParam(); + + server_ = TestServer::CreateDualKey(); } void AddKeyToLicense(const GoldenData::Key& key, @@ -26,6 +28,8 @@ class LicenseWhiteboxKeyControlBlockTest TestLicenseBuilder::KeyControlBlock kcb_; TestLicenseBuilder::OdkVersion odk_; + + std::unique_ptr server_; }; // Even though we are saying to use the ODK, since the key control block is @@ -42,16 +46,16 @@ TEST_P(LicenseWhiteboxKeyControlBlockTest, Decrypt) { AddKeyToLicense(cbc_test_data, &builder); License license; - builder.Build(*public_key_, &license); + builder.Build(*server_, &license); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license.request.data(), license.request.size()), + WB_RESULT_OK); std::vector plaintext(cbc_test_data.content->ciphertext.size()); size_t plaintext_size = plaintext.size(); @@ -77,16 +81,16 @@ TEST_P(LicenseWhiteboxKeyControlBlockTest, MaskedDecrypt) { AddKeyToLicense(cbc_test_data, &builder); License license; - builder.Build(*public_key_, &license); + builder.Build(*server_, &license); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license.request.data(), license.request.size()), + WB_RESULT_OK); std::vector plaintext(cbc_test_data.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 new file mode 100644 index 0000000..8e8392f --- /dev/null +++ b/whitebox/api/license_whitebox_license_key_mode.cc @@ -0,0 +1,157 @@ +// Copyright 2020 Google LLC. All Rights Reserved. + +#include "api/license_whitebox.h" + +#include +#include +#include + +#include "api/golden_data.h" +#include "api/license_whitebox_test_base.h" +#include "api/test_license_builder.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace widevine { + +constexpr bool kSuccess = true; +constexpr bool kFailure = false; + +// These tests verify that the white-box use the correct key when communicating +// with a single-key server and when communicating witha dual-key server. +// +// To do this, we simulate a license exchange between the client and the server +// by signing a (fake) license request and verifying it. +// +// Next we create a license response and have the client process it. +// +// Lastly, we decrypt some content (and verify the plaintext) to ensure that the +// content key was successfully loaded. +// +// The parameters for the test are: +// 1. server mode +// 2. client mode +// 3. pass expected +class LicenseWhiteboxLicenseKeyMode + : public LicenseWhiteboxTestBase, + public testing::WithParamInterface< + std::tuple> { + protected: + void SetUp() { + LicenseWhiteboxTestBase::SetUp(); + std::tie(server_mode_, client_mode_, should_pass_) = GetParam(); + } + + void SignLicenseRequest(const TestServer& server) { + // This is not an actual license request, it is just some random data. + std::vector message = { + 0x1e, 0x70, 0xbd, 0xeb, 0x24, 0xf2, 0x9d, 0x05, 0xc5, 0xb5, + 0xf4, 0xca, 0xe6, 0x1d, 0x01, 0x97, 0x29, 0xf4, 0xe0, 0x7c, + 0xfd, 0xcc, 0x97, 0x8d, 0xc2, 0xbb, 0x2d, 0x9b, 0x6b, 0x45, + 0x06, 0xbd, 0x2c, 0x66, 0x10, 0x42, 0x73, 0x8d, 0x88, 0x9b, + 0x18, 0xcc, 0xcb, 0x7e, 0x43, 0x23, 0x06, 0xe9, 0x8f, 0x8f, + }; + + size_t signature_size = 256; + std::vector signature(signature_size); + + ASSERT_EQ( + WB_License_SignLicenseRequest(whitebox_, message.data(), message.size(), + signature.data(), &signature_size), + WB_RESULT_OK); + signature.resize(signature_size); + + ASSERT_TRUE(server.Verify(message, signature)); + } + + WB_Result LoadLicense(const License& license, + WB_LicenseKeyMode license_key_mode) { + return WB_License_ProcessLicenseResponse( + whitebox_, license_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()); + } + + void Decrypt(const GoldenData::Key& golden_data) { + size_t plaintext_size = golden_data.content->plaintext.size(); + std::vector plaintext(plaintext_size); + + ASSERT_EQ(WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC, + golden_data.id.data(), golden_data.id.size(), + golden_data.content->ciphertext.data(), + golden_data.content->ciphertext.size(), + golden_data.content->iv.data(), + golden_data.content->iv.size(), + plaintext.data(), &plaintext_size), + WB_RESULT_OK); + + plaintext.resize(plaintext_size); + ASSERT_EQ(plaintext, golden_data.content->plaintext); + } + + std::unique_ptr server_; + + WB_LicenseKeyMode server_mode_; + WB_LicenseKeyMode client_mode_; + bool should_pass_; +}; + +TEST_P(LicenseWhiteboxLicenseKeyMode, SignAndProcessLicense) { + std::unique_ptr server; + + switch (server_mode_) { + case WB_LICENSE_KEY_MODE_SINGLE_KEY: + server = TestServer::CreateSingleKey(); + break; + + case WB_LICENSE_KEY_MODE_DUAL_KEY: + server = TestServer::CreateDualKey(); + break; + + default: + FAIL() << "Unknown key mode"; + break; + } + + SignLicenseRequest(*server); + + const auto& golden_data = golden_data_.CBCCryptoKey(); + + TestLicenseBuilder builder; + builder.AddContentKey(golden_data.level, golden_data.id, + golden_data.content->key); + + License license; + builder.Build(*server, &license); + + if (should_pass_) { + ASSERT_EQ(LoadLicense(license, client_mode_), WB_RESULT_OK); + Decrypt(golden_data); + } else { + ASSERT_NE(LoadLicense(license, client_mode_), WB_RESULT_OK); + } +} + +INSTANTIATE_TEST_SUITE_P( + ClientAndServerMatch, + LicenseWhiteboxLicenseKeyMode, + ::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_SINGLE_KEY, + WB_LICENSE_KEY_MODE_SINGLE_KEY, + kSuccess), + std::make_tuple(WB_LICENSE_KEY_MODE_DUAL_KEY, + WB_LICENSE_KEY_MODE_DUAL_KEY, + kSuccess))); + +INSTANTIATE_TEST_SUITE_P( + ClientAndServerMismatch, + LicenseWhiteboxLicenseKeyMode, + ::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_SINGLE_KEY, + WB_LICENSE_KEY_MODE_DUAL_KEY, + kFailure), + std::make_tuple(WB_LICENSE_KEY_MODE_DUAL_KEY, + WB_LICENSE_KEY_MODE_SINGLE_KEY, + kFailure))); + +} // namespace widevine diff --git a/whitebox/api/license_whitebox_masked_decrypt_test.cc b/whitebox/api/license_whitebox_masked_decrypt_test.cc index 1c4bbf6..69472b9 100644 --- a/whitebox/api/license_whitebox_masked_decrypt_test.cc +++ b/whitebox/api/license_whitebox_masked_decrypt_test.cc @@ -72,17 +72,19 @@ class LicenseWhiteboxMaskedDecryptTest builder.AddOperatorSessionKey(non_content_key_id_); - License license; - builder.Build(*public_key_, &license); + const auto server = TestServer::CreateDualKey(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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); + 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); } // We need two special keys for this test, one that will be used for a diff --git a/whitebox/api/license_whitebox_process_license_response_benchmark.cc b/whitebox/api/license_whitebox_process_license_response_benchmark.cc index a7fbbaf..c9f1116 100644 --- a/whitebox/api/license_whitebox_process_license_response_benchmark.cc +++ b/whitebox/api/license_whitebox_process_license_response_benchmark.cc @@ -45,12 +45,12 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark, ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, 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()), + 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); WB_License_Delete(whitebox_); @@ -78,12 +78,12 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark, ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, 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()), + 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); sampler.Push(timer.Get()); @@ -109,12 +109,12 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark, ProcessLicenseResponse) { timer.Reset(); ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, 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()), + 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); sampler.Push(timer.Get()); 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 556e96b..a7755ae 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 @@ -18,9 +18,10 @@ class LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest void UseLicenseWithoutSigningKey(OdkVersion odk_version) { TestLicenseBuilder builder; builder.GetSettings().odk_version = odk_version; - builder.AddStubbedContentKey(); - builder.Build(*public_key_, &license_); + + const auto server = TestServer::CreateDualKey(); + builder.Build(*server, &license_); } void UseLicenseWithSigningKey(TestLicenseBuilder::Padding padding, @@ -32,7 +33,8 @@ class LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey()); builder.AddStubbedContentKey(); - builder.Build(*public_key_, &license_); + auto server = TestServer::CreateDualKey(); + builder.Build(*server, &license_); } License license_; @@ -43,137 +45,137 @@ class LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithoutOdkAndWithoutSigningKey) { UseLicenseWithoutSigningKey(OdkVersion::kNone); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithOdk16_3AndWithoutSigningKey) { UseLicenseWithoutSigningKey(OdkVersion::k16_3); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, SuccessWithOdk16_5AndWithoutSigningKey) { UseLicenseWithoutSigningKey(OdkVersion::k16_5); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + 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_, 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(), + 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_, 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(), + 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_, 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(), + 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_, 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(), + 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_, 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(), + 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_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, InvalidParameterForNullCoreMessage) { UseLicenseWithoutSigningKey(OdkVersion::k16_5); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, /*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(), + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, @@ -184,14 +186,14 @@ 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_, 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(), + 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 9898a82..5d39f30 100644 --- a/whitebox/api/license_whitebox_process_license_response_test.cc +++ b/whitebox/api/license_whitebox_process_license_response_test.cc @@ -17,16 +17,21 @@ namespace widevine { class LicenseWhiteboxProcessLicenseResponseTest : public LicenseWhiteboxTestBase { protected: + void SetUp() { + LicenseWhiteboxTestBase::SetUp(); + server_ = TestServer::CreateDualKey(); + } + // No content keys. No signing keys. void UseLicenseWithNoKeys() { TestLicenseBuilder builder; - builder.Build(*public_key_, &license_); + builder.Build(*server_, &license_); } void UseLicenseWithoutSigningKey() { TestLicenseBuilder builder; builder.AddStubbedContentKey(); - builder.Build(*public_key_, &license_); + builder.Build(*server_, &license_); } void UseLicenseWithSigningKey(TestLicenseBuilder::Padding padding) { @@ -35,51 +40,52 @@ class LicenseWhiteboxProcessLicenseResponseTest builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey()); builder.AddStubbedContentKey(); - builder.Build(*public_key_, &license_); + builder.Build(*server_, &license_); } + std::unique_ptr server_; License license_; }; TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithoutSigningKey) { UseLicenseWithoutSigningKey(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithSigningKeyNoPadding) { UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithSigningKeyPKSC8Padding) { UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } // If there were multiple signing keys (this can only happen if a license server @@ -93,29 +99,29 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseTest, builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey()); builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey()); builder.AddStubbedContentKey(); - builder.Build(*public_key_, &license_); + builder.Build(*server_, &license_); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseTest, InvalidParameterWithNoKeys) { UseLicenseWithNoKeys(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } class LicenseWhiteboxProcessLicenseResponseErrorTest @@ -135,11 +141,12 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, Modify(&license_.message); WB_Result result = WB_License_ProcessLicenseResponse( - whitebox_, 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()); + 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()); // Depending on where/how the message is verified, an implementation can // return invalid parameter or invalid signature. Preferably it would be @@ -152,14 +159,14 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidSignatureForModifedSignature) { Modify(&license_.signature); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_SIGNATURE); } // The license request is used to derive the signing key. If the request was @@ -168,14 +175,14 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidSignatureForModifedLicenseRequest) { Modify(&license_.request); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_SIGNATURE); } // If the session key is modified, unwrapping it will fail. Therefore, we will @@ -186,114 +193,122 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidSignatureForModifedSessionKey) { Modify(&license_.session_key); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + 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); +} + +TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, + InvalidParameterForNullMessage) { ASSERT_EQ( WB_License_ProcessLicenseResponse( - nullptr, license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + 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()), WB_RESULT_INVALID_PARAMETER); } -TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, - InvalidParameterForNullMessage) { - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, license_.core_message.data(), - 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()), - WB_RESULT_INVALID_PARAMETER); -} - TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidParameterForZeroMessageSize) { - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, license_.core_message.data(), - 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()), - 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(), 0, + license_.signature.data(), license_.signature.size(), + license_.session_key.data(), license_.session_key.size(), + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidParameterForNullSignature) { - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, license_.core_message.data(), - 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()), - 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(), nullptr, license_.signature.size(), + license_.session_key.data(), license_.session_key.size(), + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidParameterForInvalidSignatureSize) { - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, license_.core_message.data(), - 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()), - 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(), 5, + license_.session_key.data(), license_.session_key.size(), + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidParameterForNullSessionKey) { - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, license_.core_message.data(), - 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()), - 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(), nullptr, license_.session_key.size(), + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidParameterForInvalidSessionKeySize) { - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, license_.core_message.data(), - 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()), - 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(), 5, + license_.request.data(), license_.request.size()), + WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidParameterForNullLicenseRequest) { - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, 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(), nullptr, license_.request.size()), + WB_RESULT_INVALID_PARAMETER); } TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, InvalidParameterForZeroLienseRequestSize) { - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, 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(), license_.request.data(), 0), + WB_RESULT_INVALID_PARAMETER); } class LicenseWhiteboxMultiLicenseTest @@ -313,25 +328,25 @@ 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_, 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(), + 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_, 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(), + 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 @@ -343,23 +358,23 @@ TEST_F(LicenseWhiteboxMultiLicenseTest, SuccessAfterFailure) { Modify(&bad_request); ASSERT_NE( WB_License_ProcessLicenseResponse( - whitebox_, 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()), + 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( - whitebox_, 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(), + license_.request.data(), license_.request.size()), + WB_RESULT_OK); } } // namespace widevine 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 5684840..f368488 100644 --- a/whitebox/api/license_whitebox_query_content_key_status_test.cc +++ b/whitebox/api/license_whitebox_query_content_key_status_test.cc @@ -32,6 +32,8 @@ class LicenseWhiteboxQueryContentKeyStatus masked_decrypt_key_ = &golden_data_.CBCDecodeKey(); std::tie(license_parsing_, padding_) = GetParam(); + + server_ = TestServer::CreateDualKey(); } void SetSettings(const TestLicenseBuilder::Settings& settings) { @@ -69,20 +71,22 @@ class LicenseWhiteboxQueryContentKeyStatus builder_.SetSettings(settings); License license; - builder_.Build(*public_key_, &license); + builder_.Build(*server_, &license); return WB_License_ProcessLicenseResponse( - whitebox_, 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()); + 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()); } const GoldenData::Key* decrypt_key_; const GoldenData::Key* masked_decrypt_key_; private: + std::unique_ptr server_; TestLicenseBuilder builder_; LicenseParsing license_parsing_; Padding padding_; 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 21b7c72..01c65c2 100644 --- a/whitebox/api/license_whitebox_query_signing_key_status_test.cc +++ b/whitebox/api/license_whitebox_query_signing_key_status_test.cc @@ -65,15 +65,18 @@ class LicenseWhiteboxQuerySigningKeyStatus builder_.AddContentKey(content_key->level, content_key->id, content_key->content->key); + auto server = TestServer::CreateDualKey(); + License license; - builder_.Build(*public_key_, &license); + builder_.Build(*server, &license); return WB_License_ProcessLicenseResponse( - whitebox_, 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()); + 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()); } private: diff --git a/whitebox/api/license_whitebox_security_level_test.cc b/whitebox/api/license_whitebox_security_level_test.cc index d9ce4b9..94382fe 100644 --- a/whitebox/api/license_whitebox_security_level_test.cc +++ b/whitebox/api/license_whitebox_security_level_test.cc @@ -40,17 +40,19 @@ TEST_P(LicenseWhiteboxSecurityLevelTest, CanLoadAndUseKey) { builder.AddContentKey(security_level_, golden_data_.CBCCryptoKey().id, golden_data_.CBCCryptoKey().content->key); - License license; - builder.Build(*public_key_, &license); + auto server = TestServer::CreateDualKey(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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); + 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); plaintext_size_ = golden_data_.CBCCryptoKey().content->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 a8c7e38..3e0bd5b 100644 --- a/whitebox/api/license_whitebox_sign_benchmark.cc +++ b/whitebox/api/license_whitebox_sign_benchmark.cc @@ -34,14 +34,14 @@ class LicenseWhiteboxSignBenchmark : public LicenseWhiteboxBenchmark { ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); const auto license = CreateLicense(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + license.request.data(), license.request.size()), + WB_RESULT_OK); } void TearDown() override { WB_License_Delete(whitebox_); } diff --git a/whitebox/api/license_whitebox_sign_license_request_test.cc b/whitebox/api/license_whitebox_sign_license_request_test.cc index eb6c669..995f646 100644 --- a/whitebox/api/license_whitebox_sign_license_request_test.cc +++ b/whitebox/api/license_whitebox_sign_license_request_test.cc @@ -18,8 +18,10 @@ class LicenseWhiteboxSignLicenseRequestTest : public LicenseWhiteboxTestBase { void SetUp() override { LicenseWhiteboxTestBase::SetUp(); + server_ = TestServer::CreateDualKey(); + TestLicenseBuilder builder; - builder.Build(*public_key_, &license_); + builder.Build(*server_, &license_); // We must make the default size large to hold the signature returned by // WB_License_SignLicenseRequest(). @@ -35,6 +37,7 @@ class LicenseWhiteboxSignLicenseRequestTest : public LicenseWhiteboxTestBase { 0x18, 0xcc, 0xcb, 0x7e, 0x43, 0x23, 0x06, 0xe9, 0x8f, 0x8f, }; + std::unique_ptr server_; License license_; // These will be the output from each test case. @@ -51,10 +54,7 @@ TEST_F(LicenseWhiteboxSignLicenseRequestTest, SuccessForInvalidLicenseRequest) { signature_.resize(signature_size_); - ASSERT_TRUE(public_key_->VerifySignature( - std::string(invalid_license_request_.begin(), - invalid_license_request_.end()), - std::string(signature_.begin(), signature_.end()))); + ASSERT_TRUE(server_->Verify(invalid_license_request_, signature_)); } TEST_F(LicenseWhiteboxSignLicenseRequestTest, SuccessForValidLicenseRequest) { @@ -65,9 +65,7 @@ TEST_F(LicenseWhiteboxSignLicenseRequestTest, SuccessForValidLicenseRequest) { signature_.resize(signature_size_); - ASSERT_TRUE(public_key_->VerifySignature( - std::string(license_.request.begin(), license_.request.end()), - std::string(signature_.begin(), signature_.end()))); + ASSERT_TRUE(server_->Verify(license_.request, signature_)); } TEST_F(LicenseWhiteboxSignLicenseRequestTest, InvalidParameterForNullWhitebox) { diff --git a/whitebox/api/license_whitebox_sign_renewal_request_test.cc b/whitebox/api/license_whitebox_sign_renewal_request_test.cc index dd25a73..69bfae9 100644 --- a/whitebox/api/license_whitebox_sign_renewal_request_test.cc +++ b/whitebox/api/license_whitebox_sign_renewal_request_test.cc @@ -34,17 +34,19 @@ class LicenseWhiteboxSignRenewalRequestTest : public LicenseWhiteboxTestBase { // should always have a content key. builder.AddStubbedContentKey(); - License license; - builder.Build(*public_key_, &license); + auto server = TestServer::CreateDualKey(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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); + 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); } // Get the expected signature for |message|. By returning the message, this @@ -202,17 +204,19 @@ TEST_F(LicenseWhiteboxSignRenewalRequestTest, KeyUnavailableForNoSigningKey) { TestLicenseBuilder builder; builder.AddStubbedContentKey(); - License license; - builder.Build(*public_key_, &license); + auto server = TestServer::CreateDualKey(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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); + 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_SignRenewalRequest(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 bf47a86..46a3609 100644 --- a/whitebox/api/license_whitebox_test_base.cc +++ b/whitebox/api/license_whitebox_test_base.cc @@ -2,20 +2,12 @@ #include "api/license_whitebox_test_base.h" -#include - #include "api/test_license_whitebox_keys.h" namespace widevine { void LicenseWhiteboxTestBase::SetUp() { ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); - - const auto public_key_data = GetLicensePublicKey(); - public_key_.reset(RsaPublicKey::Create( - std::string(public_key_data.begin(), public_key_data.end()))); - - ASSERT_TRUE(public_key_); } void LicenseWhiteboxTestBase::TearDown() { diff --git a/whitebox/api/license_whitebox_test_base.h b/whitebox/api/license_whitebox_test_base.h index dc6ef14..6b96ae2 100644 --- a/whitebox/api/license_whitebox_test_base.h +++ b/whitebox/api/license_whitebox_test_base.h @@ -22,8 +22,6 @@ class LicenseWhiteboxTestBase : public ::testing::Test { // to make it easier to invalidate signatures. void Modify(std::vector* data) const; - std::unique_ptr public_key_; - GoldenData golden_data_; WB_License_Whitebox* whitebox_; diff --git a/whitebox/api/license_whitebox_uat_test.cc b/whitebox/api/license_whitebox_uat_test.cc index 880f419..e14e1f0 100644 --- a/whitebox/api/license_whitebox_uat_test.cc +++ b/whitebox/api/license_whitebox_uat_test.cc @@ -312,11 +312,12 @@ class LicenseWhiteboxDecryptUatTest : public ::testing::Test { TEST_F(LicenseWhiteboxDecryptUatTest, CryptoKeyWithCbcDataInCbcMode) { ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, 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, 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 3ed49e7..b992851 100644 --- a/whitebox/api/license_whitebox_verify_benchmark.cc +++ b/whitebox/api/license_whitebox_verify_benchmark.cc @@ -30,14 +30,14 @@ class LicenseWhiteboxVerifyBenchmark : public LicenseWhiteboxBenchmark { ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); const auto license = CreateLicense(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), + 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 c6baff3..587bbf6 100644 --- a/whitebox/api/license_whitebox_verify_renewal_response_test.cc +++ b/whitebox/api/license_whitebox_verify_renewal_response_test.cc @@ -34,17 +34,19 @@ class LicenseWhiteboxVerifyRenewalResponseTest builder.AddSigningKey(signing_key); builder.AddStubbedContentKey(); - License license; - builder.Build(*public_key_, &license); + auto server = TestServer::CreateDualKey(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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); + 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); } std::vector Sign(const std::vector& message) { @@ -229,17 +231,19 @@ TEST_F(LicenseWhiteboxVerifyRenewalResponseTest, widevine::TestLicenseBuilder builder; builder.AddStubbedContentKey(); - License license; - builder.Build(*public_key_, &license); + auto server = TestServer::CreateDualKey(); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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); + 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_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 1ae8b98..ebb7348 100644 --- a/whitebox/api/remote_attestation_and_verification_test.cc +++ b/whitebox/api/remote_attestation_and_verification_test.cc @@ -8,6 +8,7 @@ #include "api/license_whitebox_test_base.h" #include "api/result.h" #include "api/test_license_builder.h" +#include "base/check_op.h" #include "testing/gtest/include/gtest/gtest.h" namespace widevine { @@ -33,6 +34,63 @@ enum class Mode { kMaskedDecryptPass, kMaskedDecryptFail, }; + +// WV_ENABLE_HW_VERIFICATION = 0: prevent VMP/RA from overriding the key +// security level. +// +// WV_ENABLE_HW_VERIFICATION = 1: allow VMP/RA to override the key security +// level. +#if WV_ENABLE_HW_VERIFICATION == 0 +constexpr bool kEnableHwVerification = false; +#elif WV_ENABLE_HW_VERIFICATION == 1 +constexpr bool kEnableHwVerification = true; +#else +#error Undefined or unknown value for WV_ENABLE_HW_VERIFICATION +#endif // WV_ENABLE_HW_VERIFICATION + +// Even without RA, a crypto key can be used with either decrypt or masked +// decrypt. +Mode DisableOverrideForCrypto(Mode mode) { + return mode; +} + +// For decode keys, the only time we should need to override the mode is when +// it says that we could use it with decrypt. Remember, anything that works +// with decrypt can work with masked decrypt, but not the other way around. +Mode DisableOverrideForDecode(Mode mode) { + if (mode == Mode::kDecryptPass) { + return Mode::kDecryptFail; + } + + return mode; +} + +// Without RA, we should never be able to use the key. If the key should have +// worked, flip it to use the correct failure. +Mode DisableOverrideForHardware(Mode mode) { + if (mode == Mode::kDecryptPass) { + return Mode::kDecryptFail; + } + + if (mode == Mode::kMaskedDecryptPass) { + return Mode::kMaskedDecryptFail; + } + + return mode; +} + +Mode DisableOverride(Key key, Mode mode) { + switch (key) { + case Key::kCrypto: + return DisableOverrideForCrypto(mode); + case Key::kDecode: + return DisableOverrideForDecode(mode); + case Key::kHardware: + return DisableOverrideForHardware(mode); + } + + CHECK(false) << "Unhandled mode"; +} } // namespace class RemoteAttestationAndVerificationTest @@ -49,6 +107,15 @@ class RemoteAttestationAndVerificationTest padding_ = std::get<0>(params); std::tie(key, ra_, vmp_, mode_) = std::get<1>(params); + // These tests are written as "we are testing that VMP/RA can override the + // key's security level". However, when the white-box does not have that + // functionality, it should not be able to do that. As a simple way to test + // this, change the mode to disable overriding when we don't want to allow + // it. + if (!kEnableHwVerification) { + mode_ = DisableOverride(key, mode_); + } + switch (key) { case Key::kCrypto: key_ = golden_data_.CBCCryptoKey(); @@ -72,15 +139,18 @@ class RemoteAttestationAndVerificationTest builder.GetSettings().verification_status = verification_status; builder.GetSettings().padding = padding; + auto server = TestServer::CreateDualKey(); + License license; - builder.Build(*public_key_, &license); + builder.Build(*server, &license); return WB_License_ProcessLicenseResponse( - whitebox_, 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()); + 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 Decrypt(const GoldenData::Key& key) { @@ -192,293 +262,325 @@ TEST_P(RemoteAttestationAndVerificationTest, Decrypt) { // however, we have seen issues between VMP + RA + PADDING. INSTANTIATE_TEST_SUITE_P( - NoRemoteAttestationNoVerification, - RemoteAttestationAndVerificationTest, - ::testing::Combine(::testing::Values(Padding::kNone, Padding::kPKSC8), - ::testing::Values( - // Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnavailable, - VerificationStatus::kUnavailable, - Mode::kDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnavailable, - VerificationStatus::kUnavailable, - Mode::kDecryptFail), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnavailable, - VerificationStatus::kUnavailable, - Mode::kDecryptFail), - // Masked Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnavailable, - VerificationStatus::kUnavailable, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnavailable, - VerificationStatus::kUnavailable, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnavailable, - VerificationStatus::kUnavailable, - Mode::kMaskedDecryptFail)))); - -INSTANTIATE_TEST_SUITE_P( - UnverifiedRemoteAttestationNoVerification, - RemoteAttestationAndVerificationTest, - ::testing::Combine(::testing::Values(Padding::kNone, Padding::kPKSC8), - ::testing::Values( - // Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnverified, - VerificationStatus::kUnavailable, - Mode::kDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnverified, - VerificationStatus::kUnavailable, - Mode::kDecryptFail), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnverified, - VerificationStatus::kUnavailable, - Mode::kDecryptFail), - // Masked Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnverified, - VerificationStatus::kUnavailable, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnverified, - VerificationStatus::kUnavailable, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnverified, - VerificationStatus::kUnavailable, - Mode::kMaskedDecryptFail)))); - -INSTANTIATE_TEST_SUITE_P( - VerifiedRemoteAttestationNoVerification, - RemoteAttestationAndVerificationTest, - ::testing::Combine(::testing::Values(Padding::kNone, Padding::kPKSC8), - ::testing::Values( - // Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kVerified, - VerificationStatus::kUnavailable, - Mode::kDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kVerified, - VerificationStatus::kUnavailable, - Mode::kDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kVerified, - VerificationStatus::kUnavailable, - Mode::kDecryptPass), - // Masked Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kVerified, - VerificationStatus::kUnavailable, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kVerified, - VerificationStatus::kUnavailable, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kVerified, - VerificationStatus::kUnavailable, - Mode::kMaskedDecryptPass)))); - -INSTANTIATE_TEST_SUITE_P( - NoRemoteAttestationHardwareVerification, + NoRemoteAttestationNoVerificationDecrypt, RemoteAttestationAndVerificationTest, ::testing::Combine( ::testing::Values(Padding::kNone, Padding::kPKSC8), - ::testing::Values( - // Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnavailable, - VerificationStatus::kHardwareVerified, - Mode::kDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnavailable, - VerificationStatus::kHardwareVerified, - Mode::kDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnavailable, - VerificationStatus::kHardwareVerified, - Mode::kDecryptPass), - // Masked Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnavailable, - VerificationStatus::kHardwareVerified, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnavailable, - VerificationStatus::kHardwareVerified, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnavailable, - VerificationStatus::kHardwareVerified, - Mode::kMaskedDecryptPass)))); - + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnavailable, + VerificationStatus::kUnavailable, + Mode::kDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnavailable, + VerificationStatus::kUnavailable, + Mode::kDecryptFail), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnavailable, + VerificationStatus::kUnavailable, + Mode::kDecryptFail)))); INSTANTIATE_TEST_SUITE_P( - UnverifiedRemoteAttestationHardwareVerification, + NoRemoteAttestationNoVerificationMaskedDecrypt, RemoteAttestationAndVerificationTest, ::testing::Combine( ::testing::Values(Padding::kNone, Padding::kPKSC8), - ::testing::Values( - // Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnverified, - VerificationStatus::kHardwareVerified, - Mode::kDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnverified, - VerificationStatus::kHardwareVerified, - Mode::kDecryptFail), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnverified, - VerificationStatus::kHardwareVerified, - Mode::kDecryptFail), - // Masked Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnverified, - VerificationStatus::kHardwareVerified, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnverified, - VerificationStatus::kHardwareVerified, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnverified, - VerificationStatus::kHardwareVerified, - Mode::kMaskedDecryptFail)))); + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnavailable, + VerificationStatus::kUnavailable, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnavailable, + VerificationStatus::kUnavailable, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnavailable, + VerificationStatus::kUnavailable, + Mode::kMaskedDecryptFail)))); INSTANTIATE_TEST_SUITE_P( - VerifiedRemoteAttestationHardwareVerification, + UnverifiedRemoteAttestationNoVerificationDecrypt, RemoteAttestationAndVerificationTest, ::testing::Combine( ::testing::Values(Padding::kNone, Padding::kPKSC8), - ::testing::Values( - // Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kVerified, - VerificationStatus::kHardwareVerified, - Mode::kDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kVerified, - VerificationStatus::kHardwareVerified, - Mode::kDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kVerified, - VerificationStatus::kHardwareVerified, - Mode::kDecryptPass), - // Masked Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kVerified, - VerificationStatus::kHardwareVerified, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kVerified, - VerificationStatus::kHardwareVerified, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kVerified, - VerificationStatus::kHardwareVerified, - Mode::kMaskedDecryptPass)))); + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnverified, + VerificationStatus::kUnavailable, + Mode::kDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnverified, + VerificationStatus::kUnavailable, + Mode::kDecryptFail), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnverified, + VerificationStatus::kUnavailable, + Mode::kDecryptFail)))); INSTANTIATE_TEST_SUITE_P( - NoRemoteAttestationOtherVerification, + UnverifiedRemoteAttestationNoVerificationMaskedDecrypt, RemoteAttestationAndVerificationTest, - ::testing::Combine(::testing::Values(Padding::kNone, Padding::kPKSC8), - ::testing::Values( - // Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnavailable, - VerificationStatus::kOther, - Mode::kDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnavailable, - VerificationStatus::kOther, - Mode::kDecryptFail), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnavailable, - VerificationStatus::kOther, - Mode::kDecryptFail), - // Masked Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnavailable, - VerificationStatus::kOther, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnavailable, - VerificationStatus::kOther, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnavailable, - VerificationStatus::kOther, - Mode::kMaskedDecryptFail)))); + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnverified, + VerificationStatus::kUnavailable, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnverified, + VerificationStatus::kUnavailable, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnverified, + VerificationStatus::kUnavailable, + Mode::kMaskedDecryptFail)))); INSTANTIATE_TEST_SUITE_P( - UnverifiedRemoteAttestationOtherVerification, + VerifiedRemoteAttestationNoVerificationDecrypt, RemoteAttestationAndVerificationTest, - ::testing::Combine(::testing::Values(Padding::kNone, Padding::kPKSC8), - ::testing::Values( - // Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnverified, - VerificationStatus::kOther, - Mode::kDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnverified, - VerificationStatus::kOther, - Mode::kDecryptFail), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnverified, - VerificationStatus::kOther, - Mode::kDecryptFail), - // Masked Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kUnverified, - VerificationStatus::kOther, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kUnverified, - VerificationStatus::kOther, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kUnverified, - VerificationStatus::kOther, - Mode::kMaskedDecryptFail)))); + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kVerified, + VerificationStatus::kUnavailable, + Mode::kDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kVerified, + VerificationStatus::kUnavailable, + Mode::kDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kVerified, + VerificationStatus::kUnavailable, + Mode::kDecryptPass)))); INSTANTIATE_TEST_SUITE_P( - VerifiedRemoteAttestationOtherVerification, + VerifiedRemoteAttestationNoVerificationMaskedDecrypt, RemoteAttestationAndVerificationTest, - ::testing::Combine(::testing::Values(Padding::kNone, Padding::kPKSC8), - ::testing::Values( - // Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kVerified, - VerificationStatus::kOther, - Mode::kDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kVerified, - VerificationStatus::kOther, - Mode::kDecryptFail), - std::make_tuple(Key::kHardware, - RemoteAttestation::kVerified, - VerificationStatus::kOther, - Mode::kDecryptFail), - // Masked Decrypt - std::make_tuple(Key::kCrypto, - RemoteAttestation::kVerified, - VerificationStatus::kOther, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kDecode, - RemoteAttestation::kVerified, - VerificationStatus::kOther, - Mode::kMaskedDecryptPass), - std::make_tuple(Key::kHardware, - RemoteAttestation::kVerified, - VerificationStatus::kOther, - Mode::kMaskedDecryptFail)))); + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kVerified, + VerificationStatus::kUnavailable, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kVerified, + VerificationStatus::kUnavailable, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kVerified, + VerificationStatus::kUnavailable, + Mode::kMaskedDecryptPass)))); + +INSTANTIATE_TEST_SUITE_P( + NoRemoteAttestationHardwareVerificationDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnavailable, + VerificationStatus::kHardwareVerified, + Mode::kDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnavailable, + VerificationStatus::kHardwareVerified, + Mode::kDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnavailable, + VerificationStatus::kHardwareVerified, + Mode::kDecryptPass)))); + +INSTANTIATE_TEST_SUITE_P( + NoRemoteAttestationHardwareVerificationMaskedDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnavailable, + VerificationStatus::kHardwareVerified, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnavailable, + VerificationStatus::kHardwareVerified, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnavailable, + VerificationStatus::kHardwareVerified, + Mode::kMaskedDecryptPass)))); + +INSTANTIATE_TEST_SUITE_P( + UnverifiedRemoteAttestationHardwareVerificationDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnverified, + VerificationStatus::kHardwareVerified, + Mode::kDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnverified, + VerificationStatus::kHardwareVerified, + Mode::kDecryptFail), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnverified, + VerificationStatus::kHardwareVerified, + Mode::kDecryptFail)))); + +INSTANTIATE_TEST_SUITE_P( + UnverifiedRemoteAttestationHardwareVerificationMaskedDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnverified, + VerificationStatus::kHardwareVerified, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnverified, + VerificationStatus::kHardwareVerified, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnverified, + VerificationStatus::kHardwareVerified, + Mode::kMaskedDecryptFail)))); + +INSTANTIATE_TEST_SUITE_P( + VerifiedRemoteAttestationHardwareVerificationDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kVerified, + VerificationStatus::kHardwareVerified, + Mode::kDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kVerified, + VerificationStatus::kHardwareVerified, + Mode::kDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kVerified, + VerificationStatus::kHardwareVerified, + Mode::kDecryptPass)))); + +INSTANTIATE_TEST_SUITE_P( + VerifiedRemoteAttestationHardwareVerificationMaskedDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kVerified, + VerificationStatus::kHardwareVerified, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kVerified, + VerificationStatus::kHardwareVerified, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kVerified, + VerificationStatus::kHardwareVerified, + Mode::kMaskedDecryptPass)))); + +INSTANTIATE_TEST_SUITE_P( + NoRemoteAttestationOtherVerificationDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnavailable, + VerificationStatus::kOther, + Mode::kDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnavailable, + VerificationStatus::kOther, + Mode::kDecryptFail), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnavailable, + VerificationStatus::kOther, + Mode::kDecryptFail)))); + +INSTANTIATE_TEST_SUITE_P( + NoRemoteAttestationOtherVerificationMaskedDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnavailable, + VerificationStatus::kOther, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnavailable, + VerificationStatus::kOther, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnavailable, + VerificationStatus::kOther, + Mode::kMaskedDecryptFail)))); + +INSTANTIATE_TEST_SUITE_P( + UnverifiedRemoteAttestationOtherVerificationDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnverified, + VerificationStatus::kOther, + Mode::kDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnverified, + VerificationStatus::kOther, + Mode::kDecryptFail), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnverified, + VerificationStatus::kOther, + Mode::kDecryptFail)))); + +INSTANTIATE_TEST_SUITE_P( + UnverifiedRemoteAttestationOtherVerificationMaskedDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kUnverified, + VerificationStatus::kOther, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kUnverified, + VerificationStatus::kOther, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kUnverified, + VerificationStatus::kOther, + Mode::kMaskedDecryptFail)))); + +INSTANTIATE_TEST_SUITE_P( + VerifiedRemoteAttestationOtherVerificationDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kVerified, + VerificationStatus::kOther, + Mode::kDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kVerified, + VerificationStatus::kOther, + Mode::kDecryptFail), + std::make_tuple(Key::kHardware, + RemoteAttestation::kVerified, + VerificationStatus::kOther, + Mode::kDecryptFail)))); + +INSTANTIATE_TEST_SUITE_P( + VerifiedRemoteAttestationOtherVerificationMaskedDecrypt, + RemoteAttestationAndVerificationTest, + ::testing::Combine( + ::testing::Values(Padding::kNone, Padding::kPKSC8), + ::testing::Values(std::make_tuple(Key::kCrypto, + RemoteAttestation::kVerified, + VerificationStatus::kOther, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kDecode, + RemoteAttestation::kVerified, + VerificationStatus::kOther, + Mode::kMaskedDecryptPass), + std::make_tuple(Key::kHardware, + RemoteAttestation::kVerified, + VerificationStatus::kOther, + Mode::kMaskedDecryptFail)))); } // namespace widevine diff --git a/whitebox/api/test_license_builder.cc b/whitebox/api/test_license_builder.cc index 0d9d2de..768fa96 100644 --- a/whitebox/api/test_license_builder.cc +++ b/whitebox/api/test_license_builder.cc @@ -405,7 +405,8 @@ TestLicenseBuilder::TestLicenseBuilder() { serialized_request_ = request_.SerializeAsString(); container_key_ = crypto_util::DeriveKey( - session_key_, crypto_util::kWrappingKeyLabel, serialized_request_, + std::string(session_key_.begin(), session_key_.end()), + crypto_util::kWrappingKeyLabel, serialized_request_, crypto_util::kWrappingKeySizeBits); } @@ -435,7 +436,7 @@ void TestLicenseBuilder::AddOperatorSessionKey(const KeyId& id) { operator_session_keys_.push_back(id); } -void TestLicenseBuilder::Build(const RsaPublicKey& public_key, +void TestLicenseBuilder::Build(const TestServer& server, License* license) const { DCHECK(license); @@ -485,12 +486,14 @@ void TestLicenseBuilder::Build(const RsaPublicKey& public_key, const std::string message_str = response.SerializeAsString(); std::string signing_key = crypto_util::DeriveKey( - session_key_, crypto_util::kSigningKeyLabel, serialized_request_, + std::string(session_key_.begin(), session_key_.end()), + crypto_util::kSigningKeyLabel, serialized_request_, crypto_util::kSigningKeySizeBits * 2); signing_key.resize(crypto_util::kSigningKeySizeBytes); - std::string session_key_str; - CHECK(public_key.Encrypt(session_key_, &session_key_str)); + std::vector encrypted_session_key = server.Encrypt( + std::vector(session_key_.begin(), session_key_.end())); + CHECK_GT(encrypted_session_key.size(), 0u); std::string oemcrypto_core_message; if (settings_.odk_version != OdkVersion::kNone) { @@ -513,7 +516,7 @@ void TestLicenseBuilder::Build(const RsaPublicKey& public_key, } license->message.assign(message_str.begin(), message_str.end()); license->signature.assign(signature_str.begin(), signature_str.end()); - license->session_key.assign(session_key_str.begin(), session_key_str.end()); + license->session_key.assign(encrypted_session_key.begin(), + encrypted_session_key.end()); } - } // namespace widevine diff --git a/whitebox/api/test_license_builder.h b/whitebox/api/test_license_builder.h index 6757170..6628101 100644 --- a/whitebox/api/test_license_builder.h +++ b/whitebox/api/test_license_builder.h @@ -8,8 +8,8 @@ #include #include "api/test_key_types.h" +#include "api/test_server.h" #include "cdm/protos/license_protocol.pb.h" -#include "crypto_utils/rsa_key.h" namespace widevine { @@ -142,10 +142,12 @@ class TestLicenseBuilder { // Gets the serialized license request and response (in components) that would // have been used in the license exchange. - void Build(const RsaPublicKey& public_key, License* license) const; + void Build(const TestServer& server, License* license) const; private: - const std::string session_key_ = "0123456789ABCDEF"; + const std::array session_key_ = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; video_widevine::LicenseRequest request_; video_widevine::License response_; diff --git a/whitebox/api/test_license_whitebox_keys.h b/whitebox/api/test_license_whitebox_keys.h index 6cf3c1f..4394608 100644 --- a/whitebox/api/test_license_whitebox_keys.h +++ b/whitebox/api/test_license_whitebox_keys.h @@ -1,23 +1,24 @@ -// Copyright 2020 Google LLC. All Rights Reserved. +// Copyright 2021 Google LLC. All Rights Reserved. #ifndef WHITEBOX_API_TEST_LICENSE_WHITEBOX_KEYS_H_ #define WHITEBOX_API_TEST_LICENSE_WHITEBOX_KEYS_H_ -#include +#include #include namespace widevine { -// Returns the private key that the tests expect/require the white-box to use. -// This key can be considered a constant, so it can be used outside of the tests -// to generate the white-box init data needed to initialize the white-box. The -// key will be a DER encoded PKCS#1 RSAPrivateKey. -std::vector GetLicensePrivateKey(); +struct WhiteboxKey { + // DER encoded PKCS#1 public key. + std::vector public_key; -// Returns the public key that matches the private key returned by -// |GetLicensePrivateKey()|. The public key will be a DER encoded PKCS#1 -// RSAPublicKey. -std::vector GetLicensePublicKey(); + // DER encoded PKCS#1 private key. + std::vector private_key; +}; + +WhiteboxKey GetEncryptionKey(); + +WhiteboxKey GetSigningKey(); } // namespace widevine diff --git a/whitebox/api/test_license_whitebox_keys_general.cc b/whitebox/api/test_license_whitebox_keys_general.cc new file mode 100644 index 0000000..fc13788 --- /dev/null +++ b/whitebox/api/test_license_whitebox_keys_general.cc @@ -0,0 +1,291 @@ +// Copyright 2021 Google LLC. All Rights Reserved. + +#include "api/test_license_whitebox_keys.h" + +namespace widevine { +namespace { + +constexpr uint8_t kSigningPublicKey[] = { + 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xae, 0xa6, 0xa8, + 0xea, 0xdd, 0xac, 0x6f, 0xb4, 0x41, 0x47, 0xcb, 0x18, 0x81, 0xeb, 0xdf, + 0x4f, 0x17, 0xf7, 0x17, 0xc0, 0xab, 0x6f, 0x47, 0x50, 0xbf, 0xe4, 0x8c, + 0xc9, 0x45, 0x24, 0x5e, 0x1c, 0x2e, 0x86, 0x9f, 0xcb, 0x47, 0x05, 0xf9, + 0xfe, 0x91, 0x90, 0xaf, 0xbd, 0x22, 0x14, 0x47, 0xa7, 0x34, 0x39, 0x79, + 0x44, 0xe9, 0x92, 0x83, 0x4a, 0x80, 0xa8, 0x2a, 0xe6, 0x9f, 0x2b, 0xb7, + 0xda, 0x2a, 0xd2, 0xae, 0x57, 0x5b, 0xfa, 0xb6, 0xdf, 0xca, 0x3e, 0xb1, + 0xb8, 0x42, 0x0b, 0xde, 0x46, 0x36, 0xdb, 0x42, 0x33, 0x8b, 0xda, 0x5c, + 0x60, 0x44, 0x7c, 0x99, 0xb4, 0x98, 0xb4, 0x1e, 0xd8, 0x25, 0x6d, 0x67, + 0x84, 0xc9, 0x67, 0xde, 0x05, 0xe6, 0x06, 0xb5, 0xb5, 0xca, 0xbc, 0xfa, + 0xb0, 0xa7, 0x46, 0x29, 0x3f, 0x63, 0x47, 0x9d, 0x70, 0x8d, 0xa2, 0x8d, + 0x22, 0xc6, 0xeb, 0x06, 0xd4, 0x5c, 0x3b, 0x62, 0x98, 0xc7, 0xda, 0x16, + 0x8f, 0x17, 0x59, 0xd5, 0xcb, 0xd1, 0x5d, 0xe3, 0xe1, 0x07, 0xe6, 0x97, + 0x87, 0xf4, 0x22, 0x53, 0xfa, 0xf9, 0xa9, 0xf5, 0xeb, 0xd7, 0x55, 0xdf, + 0x32, 0x2d, 0x4e, 0x07, 0x86, 0x25, 0x44, 0x93, 0xd6, 0xf7, 0xc6, 0xf9, + 0x78, 0x91, 0x24, 0x1e, 0xd4, 0x6b, 0xe3, 0x4a, 0xff, 0x4a, 0x3a, 0xb9, + 0x89, 0x90, 0x61, 0x87, 0xb9, 0x41, 0x45, 0x02, 0xfd, 0xd0, 0xc5, 0x5a, + 0x98, 0x41, 0x88, 0xa4, 0xe3, 0xe2, 0xa2, 0x9d, 0x9a, 0x90, 0x3f, 0x44, + 0x8e, 0x3a, 0xe1, 0xd1, 0xe9, 0x79, 0x9a, 0xc6, 0xe2, 0x7c, 0x8e, 0x9c, + 0x3d, 0xb2, 0xe0, 0x26, 0x5a, 0x46, 0x13, 0xc8, 0x43, 0x9f, 0xf7, 0x51, + 0x7e, 0xbb, 0x55, 0x6d, 0xcc, 0x97, 0x38, 0xdb, 0xa4, 0x4b, 0x96, 0x40, + 0xe5, 0x2d, 0x8f, 0x43, 0xe3, 0x21, 0x15, 0xda, 0x34, 0x97, 0x7a, 0x9e, + 0xbb, 0x02, 0x03, 0x01, 0x00, 0x01, +}; + +constexpr uint8_t kSigningPrivateKey[] = { + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xae, 0xa6, 0xa8, 0xea, 0xdd, 0xac, 0x6f, 0xb4, 0x41, 0x47, 0xcb, 0x18, + 0x81, 0xeb, 0xdf, 0x4f, 0x17, 0xf7, 0x17, 0xc0, 0xab, 0x6f, 0x47, 0x50, + 0xbf, 0xe4, 0x8c, 0xc9, 0x45, 0x24, 0x5e, 0x1c, 0x2e, 0x86, 0x9f, 0xcb, + 0x47, 0x05, 0xf9, 0xfe, 0x91, 0x90, 0xaf, 0xbd, 0x22, 0x14, 0x47, 0xa7, + 0x34, 0x39, 0x79, 0x44, 0xe9, 0x92, 0x83, 0x4a, 0x80, 0xa8, 0x2a, 0xe6, + 0x9f, 0x2b, 0xb7, 0xda, 0x2a, 0xd2, 0xae, 0x57, 0x5b, 0xfa, 0xb6, 0xdf, + 0xca, 0x3e, 0xb1, 0xb8, 0x42, 0x0b, 0xde, 0x46, 0x36, 0xdb, 0x42, 0x33, + 0x8b, 0xda, 0x5c, 0x60, 0x44, 0x7c, 0x99, 0xb4, 0x98, 0xb4, 0x1e, 0xd8, + 0x25, 0x6d, 0x67, 0x84, 0xc9, 0x67, 0xde, 0x05, 0xe6, 0x06, 0xb5, 0xb5, + 0xca, 0xbc, 0xfa, 0xb0, 0xa7, 0x46, 0x29, 0x3f, 0x63, 0x47, 0x9d, 0x70, + 0x8d, 0xa2, 0x8d, 0x22, 0xc6, 0xeb, 0x06, 0xd4, 0x5c, 0x3b, 0x62, 0x98, + 0xc7, 0xda, 0x16, 0x8f, 0x17, 0x59, 0xd5, 0xcb, 0xd1, 0x5d, 0xe3, 0xe1, + 0x07, 0xe6, 0x97, 0x87, 0xf4, 0x22, 0x53, 0xfa, 0xf9, 0xa9, 0xf5, 0xeb, + 0xd7, 0x55, 0xdf, 0x32, 0x2d, 0x4e, 0x07, 0x86, 0x25, 0x44, 0x93, 0xd6, + 0xf7, 0xc6, 0xf9, 0x78, 0x91, 0x24, 0x1e, 0xd4, 0x6b, 0xe3, 0x4a, 0xff, + 0x4a, 0x3a, 0xb9, 0x89, 0x90, 0x61, 0x87, 0xb9, 0x41, 0x45, 0x02, 0xfd, + 0xd0, 0xc5, 0x5a, 0x98, 0x41, 0x88, 0xa4, 0xe3, 0xe2, 0xa2, 0x9d, 0x9a, + 0x90, 0x3f, 0x44, 0x8e, 0x3a, 0xe1, 0xd1, 0xe9, 0x79, 0x9a, 0xc6, 0xe2, + 0x7c, 0x8e, 0x9c, 0x3d, 0xb2, 0xe0, 0x26, 0x5a, 0x46, 0x13, 0xc8, 0x43, + 0x9f, 0xf7, 0x51, 0x7e, 0xbb, 0x55, 0x6d, 0xcc, 0x97, 0x38, 0xdb, 0xa4, + 0x4b, 0x96, 0x40, 0xe5, 0x2d, 0x8f, 0x43, 0xe3, 0x21, 0x15, 0xda, 0x34, + 0x97, 0x7a, 0x9e, 0xbb, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, + 0x00, 0x56, 0x73, 0xe7, 0x1f, 0xc3, 0xb5, 0x4c, 0xe2, 0x24, 0x82, 0x5e, + 0x55, 0x76, 0x52, 0x85, 0x0a, 0xc8, 0xe9, 0x26, 0x57, 0xd8, 0x44, 0xd0, + 0x3f, 0x77, 0x8d, 0xb1, 0xe7, 0x1b, 0x93, 0xc2, 0x06, 0x1f, 0x3d, 0xc2, + 0xb1, 0xc4, 0x29, 0x80, 0x33, 0x74, 0x68, 0xf3, 0xa5, 0x22, 0xce, 0x79, + 0x1d, 0x9a, 0x6b, 0x6c, 0xcd, 0x20, 0xf5, 0xc6, 0x89, 0xc5, 0x9f, 0xf9, + 0x04, 0x89, 0xfc, 0x01, 0x19, 0x3c, 0xa3, 0x67, 0x6b, 0x94, 0xfb, 0x49, + 0x35, 0x04, 0x0e, 0xfe, 0xb8, 0x1f, 0xf1, 0x72, 0x08, 0xbd, 0xb4, 0xd1, + 0x53, 0x64, 0xc2, 0x25, 0x81, 0xfd, 0xc4, 0xd3, 0xed, 0x22, 0xbd, 0xde, + 0x9a, 0xce, 0x04, 0x16, 0xff, 0x13, 0x17, 0x98, 0x3e, 0xc1, 0x3b, 0xc7, + 0x0d, 0x03, 0x1b, 0x82, 0xd8, 0x99, 0x24, 0xd0, 0xdc, 0x30, 0xcf, 0xcd, + 0x6e, 0x5e, 0x9d, 0xfd, 0x51, 0x1e, 0xb8, 0x4e, 0x7b, 0x54, 0x83, 0x9b, + 0x4f, 0xf8, 0xa6, 0x03, 0xc1, 0x96, 0xf1, 0x6d, 0xc0, 0xa7, 0x17, 0xbd, + 0xf1, 0x60, 0xcb, 0xe2, 0x05, 0xa5, 0x9b, 0x05, 0x2e, 0xaf, 0xdc, 0xa7, + 0x88, 0xde, 0x53, 0x42, 0xa9, 0xf4, 0x0f, 0xae, 0xf9, 0x96, 0xe9, 0x2c, + 0xa6, 0xe8, 0x9d, 0x2c, 0x6b, 0xbc, 0xd8, 0x0f, 0x09, 0x5f, 0x64, 0xb2, + 0x21, 0x6f, 0xc0, 0x79, 0x3d, 0x6e, 0xad, 0x93, 0x79, 0x35, 0x87, 0x9a, + 0x41, 0xcc, 0x06, 0x24, 0xf0, 0x62, 0x09, 0xfe, 0x46, 0x9a, 0x38, 0xee, + 0xc0, 0xc8, 0x08, 0xce, 0x65, 0xda, 0xe4, 0x89, 0x1a, 0xfb, 0xe9, 0x53, + 0x0c, 0xd1, 0x80, 0x40, 0xfd, 0xc4, 0x97, 0xf8, 0x19, 0x4e, 0x03, 0x90, + 0x4a, 0xda, 0xfd, 0x13, 0x27, 0x89, 0xde, 0x12, 0x8d, 0x52, 0x5a, 0x07, + 0xf1, 0x9a, 0xa4, 0x54, 0x98, 0x86, 0xb2, 0x78, 0x76, 0xbf, 0x3a, 0xa9, + 0x8b, 0xed, 0xc7, 0x8b, 0x31, 0x02, 0x81, 0x81, 0x00, 0xe2, 0xf3, 0xab, + 0x53, 0x7b, 0xee, 0x36, 0xdb, 0xca, 0xa8, 0x74, 0x03, 0xdd, 0xe2, 0xce, + 0x87, 0xe2, 0x8c, 0x55, 0x8e, 0xd4, 0x0f, 0x32, 0xec, 0xd2, 0xf9, 0x8b, + 0x1f, 0x93, 0xdb, 0x84, 0xd2, 0x42, 0xe1, 0xc7, 0x21, 0x24, 0x2e, 0x36, + 0x0c, 0x02, 0x5d, 0x49, 0xea, 0xe0, 0x42, 0xd7, 0x7a, 0x3e, 0xc8, 0x51, + 0x92, 0x39, 0x56, 0x10, 0xd7, 0x90, 0x67, 0xa3, 0x34, 0xd6, 0xc2, 0x4a, + 0x33, 0x74, 0xfd, 0xe2, 0x7e, 0xe1, 0x3e, 0x59, 0xd7, 0x36, 0x6d, 0x7d, + 0xd4, 0xd8, 0x82, 0xfb, 0x2f, 0x1e, 0x5e, 0x32, 0xcd, 0xc3, 0x0a, 0x7f, + 0xbd, 0xb0, 0xb3, 0xf9, 0x77, 0x75, 0xb9, 0x0c, 0x63, 0x54, 0xff, 0x25, + 0xa3, 0xaf, 0x4a, 0x70, 0x61, 0x32, 0x91, 0xde, 0xfb, 0x95, 0x25, 0xb4, + 0x06, 0x98, 0x9d, 0xeb, 0x49, 0xc8, 0xe0, 0xc0, 0x7e, 0x45, 0xfb, 0xe5, + 0xf8, 0x72, 0x5b, 0x6b, 0x19, 0x02, 0x81, 0x81, 0x00, 0xc5, 0x01, 0x4b, + 0xb7, 0x5f, 0x6d, 0xbc, 0xa6, 0x8c, 0xb8, 0xeb, 0xa5, 0xff, 0x0b, 0xd7, + 0x15, 0xd7, 0xef, 0xf6, 0xc9, 0xfe, 0x69, 0xcc, 0xe5, 0xbd, 0x5c, 0xa8, + 0x05, 0xa0, 0x4d, 0x3b, 0x1f, 0xa6, 0xcc, 0x37, 0x7b, 0xb1, 0x46, 0xf2, + 0xc7, 0x67, 0xcd, 0xc1, 0x20, 0xc4, 0x14, 0xbd, 0x0e, 0x01, 0xa7, 0xd6, + 0x3c, 0xe8, 0x18, 0x9d, 0x71, 0x71, 0x37, 0x2a, 0xc0, 0x45, 0x6a, 0x54, + 0xe8, 0x63, 0xf0, 0x6e, 0xd2, 0x9f, 0x95, 0x3b, 0xde, 0xb3, 0xc5, 0x60, + 0x57, 0x3d, 0xed, 0xef, 0x57, 0xcb, 0x3d, 0x35, 0x3a, 0x2e, 0x5d, 0xb8, + 0x0e, 0xf8, 0xff, 0xd2, 0xca, 0xdd, 0xce, 0x0b, 0x10, 0x53, 0xb4, 0xdb, + 0x53, 0xf6, 0x02, 0xa5, 0xf1, 0x23, 0x4d, 0x21, 0x6e, 0xc7, 0x52, 0x5a, + 0x7a, 0x5d, 0x88, 0x32, 0xa8, 0x65, 0x50, 0x21, 0xf5, 0x81, 0x3f, 0x96, + 0xd4, 0x57, 0x48, 0x66, 0xf3, 0x02, 0x81, 0x81, 0x00, 0xdd, 0x83, 0xd6, + 0x62, 0x9a, 0xe1, 0x0c, 0xfc, 0x84, 0x96, 0xdc, 0xfd, 0xf5, 0x31, 0xee, + 0x42, 0x25, 0x76, 0xb1, 0xff, 0xc1, 0xad, 0xc0, 0x17, 0xf5, 0x68, 0x8a, + 0x49, 0x5d, 0x08, 0xf3, 0x60, 0x42, 0xd5, 0x9a, 0x86, 0x17, 0x89, 0x5f, + 0x49, 0x63, 0x79, 0x68, 0xaf, 0x6f, 0x0a, 0xee, 0xc4, 0xab, 0xc8, 0xdc, + 0x0d, 0x6c, 0x17, 0x3c, 0x43, 0x1a, 0xf8, 0x7d, 0x0d, 0x12, 0xdc, 0xfa, + 0x8d, 0xb5, 0x10, 0x25, 0x65, 0x90, 0x36, 0x4a, 0x7c, 0x4b, 0xec, 0x9c, + 0xd8, 0x06, 0x27, 0xfa, 0x41, 0xa8, 0x53, 0x6b, 0x24, 0xf8, 0xcd, 0x23, + 0x97, 0xa3, 0x84, 0x56, 0xe7, 0x29, 0xa9, 0x5f, 0x95, 0x08, 0x9e, 0x2d, + 0x3f, 0xd1, 0xd5, 0x47, 0x51, 0x27, 0x89, 0xc7, 0x6a, 0x29, 0xce, 0x6e, + 0x23, 0xce, 0x0c, 0xbd, 0x5d, 0xfc, 0x4a, 0x9a, 0xb7, 0xe5, 0x59, 0x13, + 0xc2, 0xe6, 0xe3, 0xa1, 0xe9, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x6f, 0x98, + 0xa4, 0xae, 0x97, 0xd7, 0xb9, 0xc6, 0x0a, 0xc1, 0x43, 0xa8, 0xf4, 0x1f, + 0x08, 0xfd, 0x72, 0x81, 0xfa, 0x3b, 0x58, 0xcc, 0x3a, 0xf1, 0x93, 0x54, + 0xe0, 0x57, 0xf9, 0xa5, 0xf8, 0xad, 0x69, 0x14, 0x75, 0xb2, 0x15, 0x77, + 0x4d, 0xd8, 0xad, 0xa6, 0xb5, 0x11, 0xb0, 0x9d, 0x28, 0xa2, 0xfd, 0xd4, + 0xac, 0x11, 0x78, 0x31, 0xe0, 0xd3, 0x76, 0xee, 0x03, 0x56, 0x19, 0xb9, + 0x67, 0xdd, 0x95, 0x2c, 0xeb, 0xe8, 0x02, 0x8d, 0x25, 0x4e, 0x64, 0x35, + 0x41, 0xf7, 0x1e, 0xee, 0xfc, 0xc2, 0x93, 0xd3, 0x15, 0x07, 0xe0, 0x53, + 0x73, 0x0f, 0x14, 0x03, 0x12, 0xdb, 0xdd, 0xc6, 0xde, 0x08, 0x9c, 0x77, + 0xa5, 0x20, 0x7d, 0xda, 0x0f, 0x91, 0x7c, 0xb7, 0xf9, 0x04, 0xe5, 0xae, + 0xfa, 0x8b, 0x85, 0x4c, 0xf3, 0xff, 0xa5, 0xf2, 0x3a, 0x72, 0x61, 0x1a, + 0x09, 0x47, 0x19, 0x7d, 0x7f, 0x02, 0x81, 0x80, 0x65, 0xce, 0x33, 0x53, + 0xca, 0xfb, 0xe0, 0x29, 0x83, 0x12, 0x93, 0x6c, 0xd9, 0xeb, 0x3b, 0xaa, + 0xc5, 0xc4, 0xd1, 0xb0, 0x01, 0x85, 0xba, 0xc7, 0x6d, 0xdb, 0x3f, 0x86, + 0x06, 0x4c, 0x7e, 0xc4, 0x64, 0x65, 0x14, 0x5d, 0x9c, 0xe9, 0x54, 0x62, + 0x5c, 0xf2, 0x6e, 0xe3, 0x14, 0x80, 0x48, 0x0c, 0xbc, 0xb4, 0xa1, 0xb6, + 0x6d, 0x2f, 0xa3, 0x21, 0xc0, 0xfc, 0x45, 0xa9, 0x2e, 0x3d, 0x34, 0x2d, + 0x05, 0x39, 0x4f, 0x4b, 0xf1, 0x8c, 0xd3, 0x61, 0xbb, 0x80, 0x2d, 0xa3, + 0x50, 0x5c, 0xe0, 0xf4, 0xcd, 0xff, 0x95, 0xdc, 0xa8, 0x23, 0x8f, 0x92, + 0x69, 0xcd, 0x36, 0x8a, 0xba, 0xa5, 0xe3, 0xfe, 0xce, 0x8e, 0x67, 0xc5, + 0x54, 0x41, 0x8c, 0x44, 0xc5, 0x50, 0x55, 0x7a, 0x7c, 0x91, 0xc9, 0x2e, + 0x9e, 0x32, 0x63, 0x37, 0x42, 0x68, 0x29, 0x76, 0x41, 0xdb, 0x77, 0xfd, + 0xcb, 0x6a, 0x73, 0x10, +}; + +constexpr uint8_t kEncryptionPublicKey[] = { + 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe4, 0x74, 0x0f, + 0xf0, 0xa0, 0x45, 0x45, 0x61, 0x6b, 0x37, 0x97, 0x8a, 0x3a, 0x2a, 0xb0, + 0xd2, 0x86, 0xf7, 0x7f, 0x5a, 0x69, 0xe4, 0xaf, 0xaa, 0xf6, 0x3e, 0x8c, + 0x63, 0x47, 0xfd, 0xa4, 0xf2, 0x78, 0xc6, 0x88, 0x7a, 0x61, 0x14, 0xf5, + 0xc6, 0xe9, 0x04, 0xaf, 0x13, 0xf4, 0x6c, 0x77, 0x9a, 0x1b, 0x30, 0xe8, + 0xa4, 0xb9, 0x34, 0x71, 0xb0, 0x7d, 0x0b, 0xa9, 0x96, 0xd8, 0xc1, 0xe4, + 0x7b, 0xfb, 0x5e, 0x38, 0xc1, 0x77, 0xee, 0x63, 0xd0, 0xb0, 0xc9, 0x69, + 0x4c, 0xeb, 0x99, 0x45, 0x8b, 0xaf, 0xdb, 0xa7, 0x6f, 0x37, 0x7a, 0x63, + 0x98, 0x70, 0x27, 0x2d, 0x0c, 0xba, 0x5c, 0xf2, 0x63, 0x05, 0xbf, 0x2e, + 0x3f, 0xff, 0x44, 0x5c, 0x84, 0x20, 0x9d, 0x82, 0x78, 0x61, 0xd8, 0x9f, + 0x74, 0x0c, 0x5e, 0xa2, 0x16, 0x34, 0x5f, 0x79, 0xcf, 0x48, 0x4a, 0xee, + 0x8c, 0x82, 0x10, 0xcf, 0x7c, 0x01, 0xd9, 0x3d, 0x47, 0xb0, 0x14, 0xfb, + 0x52, 0xdb, 0xd0, 0x0c, 0xde, 0x9a, 0xf1, 0x3c, 0x53, 0x59, 0xc6, 0x0d, + 0xb6, 0xeb, 0x42, 0x25, 0xdc, 0x4c, 0x10, 0x7e, 0xaf, 0xbc, 0xb7, 0xfe, + 0x57, 0x64, 0xe2, 0x2b, 0xe3, 0x8f, 0xe9, 0xee, 0x8b, 0x05, 0x2a, 0x6e, + 0xf4, 0x9c, 0xa3, 0xb1, 0x8f, 0xda, 0x8c, 0x34, 0xb6, 0x91, 0xfa, 0x87, + 0x20, 0xab, 0x64, 0x2c, 0x71, 0xe3, 0x30, 0xfa, 0x92, 0xd8, 0x88, 0x7d, + 0xee, 0x03, 0xbd, 0x07, 0xe0, 0xbb, 0xe0, 0x4b, 0x26, 0xe0, 0xc6, 0x1d, + 0xa7, 0xc1, 0x0b, 0xc0, 0xc1, 0xeb, 0x3c, 0x20, 0xf8, 0xbd, 0x8b, 0x6b, + 0x40, 0xbb, 0x69, 0x89, 0xea, 0xf8, 0xd9, 0x49, 0x1c, 0xcc, 0xc7, 0xde, + 0x0f, 0x40, 0x97, 0x55, 0xd1, 0xa0, 0xdb, 0x8e, 0x50, 0xcd, 0x79, 0xb7, + 0xf7, 0x7c, 0xd5, 0x09, 0xb2, 0x48, 0x1f, 0xfe, 0xd7, 0x9e, 0x0e, 0x71, + 0xb7, 0x02, 0x03, 0x01, 0x00, 0x01, +}; + +constexpr uint8_t kEncryptionPrivateKey[] = { + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xe4, 0x74, 0x0f, 0xf0, 0xa0, 0x45, 0x45, 0x61, 0x6b, 0x37, 0x97, 0x8a, + 0x3a, 0x2a, 0xb0, 0xd2, 0x86, 0xf7, 0x7f, 0x5a, 0x69, 0xe4, 0xaf, 0xaa, + 0xf6, 0x3e, 0x8c, 0x63, 0x47, 0xfd, 0xa4, 0xf2, 0x78, 0xc6, 0x88, 0x7a, + 0x61, 0x14, 0xf5, 0xc6, 0xe9, 0x04, 0xaf, 0x13, 0xf4, 0x6c, 0x77, 0x9a, + 0x1b, 0x30, 0xe8, 0xa4, 0xb9, 0x34, 0x71, 0xb0, 0x7d, 0x0b, 0xa9, 0x96, + 0xd8, 0xc1, 0xe4, 0x7b, 0xfb, 0x5e, 0x38, 0xc1, 0x77, 0xee, 0x63, 0xd0, + 0xb0, 0xc9, 0x69, 0x4c, 0xeb, 0x99, 0x45, 0x8b, 0xaf, 0xdb, 0xa7, 0x6f, + 0x37, 0x7a, 0x63, 0x98, 0x70, 0x27, 0x2d, 0x0c, 0xba, 0x5c, 0xf2, 0x63, + 0x05, 0xbf, 0x2e, 0x3f, 0xff, 0x44, 0x5c, 0x84, 0x20, 0x9d, 0x82, 0x78, + 0x61, 0xd8, 0x9f, 0x74, 0x0c, 0x5e, 0xa2, 0x16, 0x34, 0x5f, 0x79, 0xcf, + 0x48, 0x4a, 0xee, 0x8c, 0x82, 0x10, 0xcf, 0x7c, 0x01, 0xd9, 0x3d, 0x47, + 0xb0, 0x14, 0xfb, 0x52, 0xdb, 0xd0, 0x0c, 0xde, 0x9a, 0xf1, 0x3c, 0x53, + 0x59, 0xc6, 0x0d, 0xb6, 0xeb, 0x42, 0x25, 0xdc, 0x4c, 0x10, 0x7e, 0xaf, + 0xbc, 0xb7, 0xfe, 0x57, 0x64, 0xe2, 0x2b, 0xe3, 0x8f, 0xe9, 0xee, 0x8b, + 0x05, 0x2a, 0x6e, 0xf4, 0x9c, 0xa3, 0xb1, 0x8f, 0xda, 0x8c, 0x34, 0xb6, + 0x91, 0xfa, 0x87, 0x20, 0xab, 0x64, 0x2c, 0x71, 0xe3, 0x30, 0xfa, 0x92, + 0xd8, 0x88, 0x7d, 0xee, 0x03, 0xbd, 0x07, 0xe0, 0xbb, 0xe0, 0x4b, 0x26, + 0xe0, 0xc6, 0x1d, 0xa7, 0xc1, 0x0b, 0xc0, 0xc1, 0xeb, 0x3c, 0x20, 0xf8, + 0xbd, 0x8b, 0x6b, 0x40, 0xbb, 0x69, 0x89, 0xea, 0xf8, 0xd9, 0x49, 0x1c, + 0xcc, 0xc7, 0xde, 0x0f, 0x40, 0x97, 0x55, 0xd1, 0xa0, 0xdb, 0x8e, 0x50, + 0xcd, 0x79, 0xb7, 0xf7, 0x7c, 0xd5, 0x09, 0xb2, 0x48, 0x1f, 0xfe, 0xd7, + 0x9e, 0x0e, 0x71, 0xb7, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, + 0x00, 0x3f, 0x6b, 0x1c, 0xb5, 0xae, 0xb8, 0x2c, 0x1f, 0x74, 0x15, 0x15, + 0xa3, 0x50, 0xac, 0x63, 0x33, 0xbe, 0x35, 0xdc, 0x8b, 0xab, 0xd3, 0xc9, + 0x14, 0x4b, 0x91, 0x67, 0x85, 0x74, 0x09, 0xac, 0x8d, 0x87, 0x0b, 0x8d, + 0xfd, 0x73, 0x0f, 0xcf, 0x7e, 0xad, 0x57, 0x18, 0x87, 0x10, 0x96, 0x3f, + 0xc9, 0x6e, 0xfc, 0xef, 0xc8, 0x32, 0x85, 0xa5, 0x7d, 0xd9, 0xe8, 0xaf, + 0xe6, 0x69, 0x3b, 0xc2, 0x02, 0xcc, 0xf0, 0x06, 0x0f, 0x67, 0x0c, 0xad, + 0x76, 0xd4, 0x6c, 0xc5, 0x27, 0x8e, 0x4b, 0x99, 0x2b, 0xc2, 0xe0, 0xd6, + 0x25, 0x20, 0xa0, 0x80, 0x1f, 0x64, 0x1a, 0xeb, 0xfd, 0x99, 0x8a, 0x8d, + 0xdb, 0x01, 0x50, 0x66, 0x35, 0x6b, 0xd6, 0x7d, 0x5c, 0x4c, 0x75, 0x8d, + 0x2f, 0x7f, 0xf2, 0x13, 0xa9, 0xb2, 0x79, 0x5e, 0xc3, 0x8d, 0x3c, 0x67, + 0xe3, 0x2b, 0xed, 0x69, 0x35, 0x66, 0x31, 0xe6, 0x76, 0xbe, 0xf6, 0xed, + 0x93, 0xf3, 0x68, 0x70, 0xaf, 0xc1, 0x1b, 0xbc, 0x37, 0x65, 0xa2, 0xbd, + 0xa1, 0x68, 0xea, 0x2c, 0xd5, 0xa3, 0x04, 0xea, 0xc4, 0x80, 0x42, 0xef, + 0x1c, 0x38, 0x7b, 0x96, 0x1d, 0x9a, 0x59, 0xd1, 0x4b, 0x07, 0x0c, 0xa5, + 0xa7, 0x9e, 0x65, 0xd7, 0x64, 0xa4, 0xa0, 0xbc, 0x2e, 0xdd, 0xf9, 0x99, + 0xd8, 0x9e, 0xe5, 0x68, 0xb8, 0xf9, 0x53, 0x31, 0x58, 0x6e, 0x6e, 0xcb, + 0x5f, 0xc1, 0x6e, 0xdb, 0xb4, 0x3d, 0x1b, 0x46, 0x45, 0xbd, 0x81, 0x5b, + 0x65, 0x9f, 0x28, 0xeb, 0x46, 0x96, 0x45, 0x24, 0xe8, 0x49, 0x0f, 0x8b, + 0x72, 0x49, 0x28, 0x25, 0xdf, 0xb3, 0x06, 0xe3, 0xb0, 0xf5, 0xde, 0x40, + 0x69, 0x2d, 0xf1, 0xe5, 0x9c, 0xee, 0xa7, 0xd4, 0x45, 0xc5, 0xc3, 0x88, + 0x27, 0xb9, 0x97, 0x76, 0x59, 0xdc, 0x15, 0x3c, 0x5f, 0x05, 0xd6, 0xbd, + 0x4b, 0xd3, 0xc5, 0x4d, 0x01, 0x02, 0x81, 0x81, 0x00, 0xf8, 0x96, 0xbb, + 0x7d, 0x3c, 0x0a, 0x15, 0x3d, 0x8b, 0x15, 0x74, 0x0e, 0x0e, 0xcc, 0x27, + 0xb3, 0x1a, 0xc7, 0x7a, 0xfa, 0xf7, 0x76, 0x41, 0xe7, 0x34, 0xc0, 0x37, + 0x2e, 0x1e, 0x39, 0x68, 0x41, 0xa7, 0x3e, 0x20, 0x3c, 0x66, 0xf6, 0x6c, + 0xb8, 0x6a, 0x97, 0x3a, 0xc2, 0x70, 0x3d, 0xc9, 0x62, 0xf8, 0x13, 0xc1, + 0xef, 0x32, 0xd9, 0xd5, 0x2e, 0x9e, 0x87, 0x5c, 0x85, 0xac, 0x46, 0x14, + 0xf2, 0x92, 0x63, 0xd1, 0x30, 0x4c, 0x79, 0xbe, 0x39, 0x7f, 0x6e, 0xdc, + 0xb1, 0x9e, 0xe6, 0xa1, 0x6c, 0x2d, 0x24, 0xba, 0xb9, 0xf8, 0xbf, 0x38, + 0x13, 0xcc, 0x3a, 0x41, 0x27, 0xb3, 0x9b, 0x6f, 0xd2, 0x4c, 0x4e, 0x13, + 0x79, 0x76, 0x10, 0xa2, 0x32, 0xbd, 0x32, 0x33, 0x47, 0x27, 0xfc, 0x8f, + 0x2c, 0x82, 0xe4, 0x84, 0x05, 0x4c, 0x3a, 0xce, 0xf8, 0x96, 0x4a, 0xac, + 0xb7, 0x48, 0xa4, 0xe3, 0x81, 0x02, 0x81, 0x81, 0x00, 0xeb, 0x43, 0xa7, + 0x38, 0xe9, 0xde, 0xda, 0xa7, 0x93, 0x67, 0xf7, 0x25, 0xa7, 0x2c, 0x88, + 0xde, 0x02, 0xf8, 0xce, 0xb5, 0x7b, 0x48, 0x19, 0xea, 0x45, 0x11, 0x46, + 0xd4, 0x27, 0x3e, 0x16, 0xc0, 0x2a, 0x96, 0xdd, 0x9d, 0x1b, 0xb3, 0x58, + 0x8f, 0xce, 0x6f, 0x7e, 0x66, 0xc5, 0x96, 0x66, 0x42, 0x9b, 0xcc, 0x30, + 0x7f, 0xe8, 0x27, 0x70, 0xcd, 0xc9, 0xa7, 0xcb, 0xc6, 0xe6, 0x82, 0xbe, + 0x5b, 0xf9, 0x72, 0x1f, 0x1c, 0x92, 0xcf, 0x92, 0xdd, 0xc4, 0x04, 0xe6, + 0x8b, 0x0f, 0x60, 0x9c, 0xa5, 0x5f, 0x5d, 0x22, 0xcd, 0x07, 0xeb, 0xc5, + 0x4f, 0x6d, 0x15, 0x1f, 0x1f, 0xd0, 0x74, 0x46, 0x41, 0x1f, 0x0a, 0x12, + 0xa6, 0x8e, 0x5a, 0x50, 0x19, 0x2f, 0x64, 0x79, 0x7e, 0x4c, 0xc8, 0x01, + 0x55, 0x51, 0xc8, 0xe3, 0x45, 0x3f, 0x35, 0x09, 0x34, 0x64, 0xd2, 0xfb, + 0xa9, 0xfa, 0x86, 0x11, 0x37, 0x02, 0x81, 0x80, 0x6e, 0xf5, 0xb1, 0x28, + 0x9c, 0x55, 0x0f, 0xd8, 0x11, 0xad, 0xf8, 0xc8, 0x91, 0x98, 0x55, 0x1c, + 0x20, 0x16, 0xec, 0x70, 0xfb, 0x66, 0x60, 0xd2, 0x57, 0xfc, 0x78, 0x64, + 0xf0, 0x7e, 0xc5, 0x67, 0x90, 0xc4, 0x2d, 0x55, 0x68, 0xcc, 0x14, 0x09, + 0x59, 0x22, 0xb9, 0xca, 0xb2, 0x99, 0x11, 0xbc, 0x48, 0x69, 0x61, 0x46, + 0x68, 0xd7, 0x4c, 0xcd, 0xeb, 0x5b, 0x16, 0x54, 0x60, 0x6a, 0x43, 0xcd, + 0x66, 0xc4, 0x81, 0x4a, 0x62, 0xc8, 0x70, 0xbd, 0x6f, 0x81, 0x47, 0xa7, + 0x4c, 0xfb, 0x3b, 0x10, 0x73, 0x32, 0x12, 0xdb, 0x12, 0x0a, 0x20, 0x78, + 0xcd, 0xcf, 0x2e, 0xe8, 0x0e, 0xc6, 0x91, 0xea, 0x37, 0xbf, 0x1d, 0xf8, + 0x38, 0x58, 0x02, 0x5e, 0x4d, 0x8f, 0x0b, 0xce, 0x76, 0x2d, 0xc8, 0xa6, + 0xa0, 0xa2, 0x69, 0xbf, 0x87, 0xa0, 0x34, 0x64, 0x47, 0x89, 0x7b, 0x80, + 0xb0, 0x3f, 0x51, 0x81, 0x02, 0x81, 0x81, 0x00, 0xde, 0x08, 0x44, 0x5a, + 0x8f, 0x45, 0xd6, 0x80, 0x4e, 0xba, 0xd0, 0xe2, 0x45, 0x4a, 0xdf, 0x84, + 0xff, 0xb3, 0x07, 0x8a, 0xf9, 0x65, 0x8b, 0xa7, 0xb0, 0x35, 0x64, 0xee, + 0x36, 0x76, 0xff, 0x8b, 0xae, 0xe6, 0x21, 0x12, 0xf4, 0x20, 0xa7, 0xd5, + 0x58, 0x93, 0x9a, 0xec, 0xad, 0x4f, 0x8b, 0x05, 0x13, 0xfa, 0x7a, 0x4f, + 0x4c, 0xaf, 0x64, 0x63, 0xa3, 0x0c, 0x6c, 0x62, 0x34, 0x0c, 0x72, 0x51, + 0x65, 0x33, 0x12, 0x2f, 0xaa, 0x52, 0xa2, 0x9e, 0x0f, 0x30, 0x3c, 0xd0, + 0x42, 0xdc, 0x00, 0x1a, 0x86, 0xcc, 0xe4, 0x5a, 0x32, 0x3e, 0x8e, 0x41, + 0xae, 0x86, 0x3f, 0x90, 0x8b, 0xf0, 0x20, 0x99, 0xb7, 0x0c, 0x8f, 0x9b, + 0x87, 0x3f, 0xae, 0xd6, 0x86, 0x06, 0xc2, 0x2e, 0xb3, 0x92, 0x12, 0xc8, + 0x0d, 0xde, 0x94, 0xb7, 0x36, 0xb6, 0xfc, 0x0f, 0xe9, 0x93, 0xc1, 0x15, + 0xa3, 0xad, 0x41, 0xb3, 0x02, 0x81, 0x81, 0x00, 0xe8, 0x03, 0x51, 0x12, + 0xba, 0x31, 0x93, 0x0e, 0x95, 0x6b, 0x83, 0x7c, 0xc7, 0x49, 0xd2, 0xa8, + 0xf6, 0xe5, 0x83, 0x8c, 0xc9, 0x96, 0x9c, 0xd2, 0x69, 0x9c, 0xa3, 0x86, + 0xa7, 0x23, 0x0e, 0x4b, 0x98, 0xe5, 0xa3, 0xca, 0x23, 0x22, 0x02, 0x0e, + 0x8a, 0x34, 0xb8, 0x20, 0x77, 0x2e, 0xb9, 0xc8, 0xce, 0xe8, 0x1b, 0x53, + 0xcc, 0x2b, 0x9e, 0xd4, 0x39, 0x6a, 0x28, 0x4c, 0x11, 0x18, 0xe4, 0x5a, + 0xcc, 0xe7, 0x0d, 0x74, 0xb3, 0x00, 0xde, 0xc2, 0x0b, 0x39, 0x98, 0x5e, + 0x69, 0x25, 0x1c, 0x59, 0xb5, 0x72, 0x25, 0x76, 0x4e, 0x36, 0x6f, 0xd6, + 0xec, 0xe0, 0x69, 0x22, 0xed, 0x0b, 0xb2, 0x62, 0xe8, 0x74, 0x3f, 0x66, + 0xc5, 0x52, 0xe3, 0xfe, 0xe2, 0xc6, 0x6e, 0xf9, 0xf5, 0xcb, 0xe9, 0x30, + 0xf8, 0x90, 0xfb, 0x60, 0x69, 0x31, 0x94, 0x9f, 0x01, 0x21, 0xfa, 0x7b, + 0x92, 0xae, 0x06, 0xfa, +}; + +std::vector AsVector(const uint8_t* data, size_t length) { + return std::vector(data, data + length); +} + +} // namespace + +WhiteboxKey GetEncryptionKey() { + WhiteboxKey key; + + key.private_key = + AsVector(kEncryptionPrivateKey, sizeof(kEncryptionPrivateKey)); + key.public_key = AsVector(kEncryptionPublicKey, sizeof(kEncryptionPublicKey)); + + return key; +} + +WhiteboxKey GetSigningKey() { + WhiteboxKey key; + + key.private_key = AsVector(kSigningPrivateKey, sizeof(kSigningPrivateKey)); + key.public_key = AsVector(kSigningPublicKey, sizeof(kSigningPublicKey)); + + return key; +} + +} // namespace widevine diff --git a/whitebox/api/test_license_whitebox_keys.cc b/whitebox/api/test_license_whitebox_keys_uat.cc similarity index 92% rename from whitebox/api/test_license_whitebox_keys.cc rename to whitebox/api/test_license_whitebox_keys_uat.cc index f4c34b9..008e580 100644 --- a/whitebox/api/test_license_whitebox_keys.cc +++ b/whitebox/api/test_license_whitebox_keys_uat.cc @@ -1,7 +1,10 @@ -// Copyright 2020 Google LLC. All Rights Reserved. +// Copyright 2021 Google LLC. All Rights Reserved. #include "api/test_license_whitebox_keys.h" +// When the license response was collected for the UAT tests, the license server +// only supported a single key. In order for the UAT tests to work, the +// encryption and signing keys must be the same key. namespace widevine { namespace { @@ -134,16 +137,29 @@ constexpr uint8_t kDevicePrivateKey[] = { 0xcb, 0x6a, 0x73, 0x10, }; -} // namespace - -std::vector GetLicensePrivateKey() { - return std::vector(kDevicePrivateKey, - kDevicePrivateKey + sizeof(kDevicePrivateKey)); +std::vector AsVector(const uint8_t* data, size_t length) { + return std::vector(data, data + length); } -std::vector GetLicensePublicKey() { - return std::vector(kDevicePublicKey, - kDevicePublicKey + sizeof(kDevicePublicKey)); +// Since we are going to return the same key for encryption and signing, create +// a common function for them to both call. +WhiteboxKey GetKey() { + WhiteboxKey key; + + key.private_key = AsVector(kDevicePrivateKey, sizeof(kDevicePrivateKey)); + key.public_key = AsVector(kDevicePublicKey, sizeof(kDevicePublicKey)); + + return key; +} + +} // namespace + +WhiteboxKey GetEncryptionKey() { + return GetKey(); +} + +WhiteboxKey GetSigningKey() { + return GetKey(); } } // namespace widevine diff --git a/whitebox/api/test_server.cc b/whitebox/api/test_server.cc new file mode 100644 index 0000000..8636e24 --- /dev/null +++ b/whitebox/api/test_server.cc @@ -0,0 +1,59 @@ +// Copyright 2021 Google LLC. All Rights Reserved. + +#include "api/test_server.h" + +#include "api/test_license_whitebox_keys.h" +#include "base/check.h" +#include "base/check_op.h" +#include "crypto_utils/rsa_key.h" + +namespace widevine { +TestServer::TestServer(const WhiteboxKey& encryption_key, + const WhiteboxKey& signing_key) + : encryption_key_(encryption_key.public_key), + signing_key_(signing_key.public_key) { + CHECK_GT(encryption_key_.size(), 0u); + CHECK_GT(signing_key_.size(), 0u); +} + +std::vector TestServer::Encrypt( + const std::vector& data) const { + CHECK_GT(encryption_key_.size(), 0u); + + const std::string key_str(encryption_key_.begin(), encryption_key_.end()); + const std::string data_str(data.begin(), data.end()); + + std::unique_ptr key(RsaPublicKey::Create(key_str)); + CHECK(key); + + std::string encrypted_data_str; + return key->Encrypt(data_str, &encrypted_data_str) + ? std::vector(encrypted_data_str.begin(), + encrypted_data_str.end()) + : std::vector(); +} + +bool TestServer::Verify(const std::vector& data, + const std::vector& signature) const { + CHECK_GT(signing_key_.size(), 0u); + + const std::string key_str(signing_key_.begin(), signing_key_.end()); + const std::string data_str(data.begin(), data.end()); + const std::string signature_str(signature.begin(), signature.end()); + + std::unique_ptr key(RsaPublicKey::Create(key_str)); + CHECK(key); + return key->VerifySignature(data_str, signature_str); +} + +std::unique_ptr TestServer::CreateSingleKey() { + return std::unique_ptr( + new TestServer(GetSigningKey(), GetSigningKey())); +} + +std::unique_ptr TestServer::CreateDualKey() { + return std::unique_ptr( + new TestServer(GetEncryptionKey(), GetSigningKey())); +} + +} // namespace widevine \ No newline at end of file diff --git a/whitebox/api/test_server.h b/whitebox/api/test_server.h new file mode 100644 index 0000000..92202d2 --- /dev/null +++ b/whitebox/api/test_server.h @@ -0,0 +1,40 @@ +// Copyright 2021 Google LLC. All Rights Reserved. + +#ifndef WHITEBOX_API_TEST_SERVER_H_ +#define WHITEBOX_API_TEST_SERVER_H_ + +#include + +#include "api/test_license_whitebox_keys.h" + +namespace widevine { + +class TestServer { + public: + TestServer(const WhiteboxKey& encryption_key, const WhiteboxKey& signing_key); + + std::vector Encrypt(const std::vector& data) const; + + bool Verify(const std::vector& data, + const std::vector& signature) const; + + // Create a single key server which uses `widevine::GetSigningKey()` for both + // encryption and signing. + static std::unique_ptr CreateSingleKey(); + + // Create a dual key server which uses `widevine::GetSigningKey()` for signing + // and `widevine::GetEncryptionKey()` for encryption. + static std::unique_ptr CreateDualKey(); + + private: + // The encryption and signing keys used to encrypt and sign the license + // response. When they are the same value, we are effectively using + // "single-key mode". When they differ, we are effectilvey using "dual-key + // mode". + std::vector encryption_key_; + std::vector signing_key_; +}; + +} // namespace widevine + +#endif // WHITEBOX_API_TEST_SERVER_H_ \ No newline at end of file diff --git a/whitebox/reference/impl/BUILD b/whitebox/reference/impl/BUILD index a0ec96b..26f02b9 100644 --- a/whitebox/reference/impl/BUILD +++ b/whitebox/reference/impl/BUILD @@ -13,9 +13,14 @@ package(default_visibility = [ # # test_aead_whitebox : The target for testing the AEAD white-box. # -# test_license_whitebox : The target for testing the license white-box. The -# white-box should use the private key provided in -# "//api/test_license_whitebox_keys.cc". +# general_license_whitebox_with_vmpra : The target for testing the license +# white-box against generated licenses with VMP/RA functionality. +# +# general_license_whitebox_without_vmpra : The target for testing the license +# white-box against generated licenses without VMP/RA functionality. +# +# uat_license_whitebox : The target for testing the license white-box against +# licenses from Widevine's UAT server. # ============================================================================== # Internal Targets @@ -44,7 +49,7 @@ cc_library( deps = [ "//api:license_whitebox", "//chromium_deps/cdm/protos:license_protocol_proto", - ] + ], ) cc_library( @@ -61,8 +66,8 @@ cc_library( hdrs = ["license_parser.h"], deps = [ ":content_key", - ":renewal_key", ":odk", + ":renewal_key", "//api:result", "//chromium_deps/cdm/protos:license_protocol_proto", "//crypto_utils:aes_cbc_decryptor", @@ -81,18 +86,64 @@ cc_library( ], ) +# For the protobuf license parser, we need to have three targets: +# 1. The header target +# 2. The VMP/RA enabled target +# 3. The VMP/RA disabled target +# +# The header target is needed so that we can defer which parser we are going to +# support until the top-level target. +# +# The two implementation targets are created (as near copies) to avoid issues +# around when the define is resolved. cc_library( name = "protobuf_license_parser", - srcs = ["protobuf_license_parser.cc"], hdrs = ["protobuf_license_parser.h"], deps = [ ":license_parser", + ], +) + +cc_library( + name = "protobuf_license_parser_with_vmpra", + srcs = ["protobuf_license_parser.cc"], + defines = ["WV_ENABLE_HW_VERIFICATION=1"], + deps = [ + ":license_parser", + ":protobuf_license_parser", "//chromium_deps/base:glog", "//chromium_deps/cdm/protos:license_protocol_proto", "//crypto_utils:crypto_util", ], ) +cc_library( + name = "protobuf_license_parser_without_vmpra", + srcs = ["protobuf_license_parser.cc"], + defines = ["WV_ENABLE_HW_VERIFICATION=0"], + deps = [ + ":license_parser", + ":protobuf_license_parser", + "//chromium_deps/base:glog", + "//chromium_deps/cdm/protos:license_protocol_proto", + "//crypto_utils:crypto_util", + ], +) + +# The "private_keys" target provides a wrapper around the private keys defined +# in "api/test_license_whitebox_keys.h". In order to use the keys, the correct +# implementation of "api/test_license_whitebox_keys.h" (e.g. +# "api/test_license_whitebox_keys_uat.cc") will need to be linked against the +# final binary. +cc_library( + name = "private_keys", + srcs = ["private_keys.cc"], + hdrs = ["private_keys.h"], + deps = [ + "//api:test_license_whitebox_keys", + ], +) + # ============================================================================== # AEAD White-box Targets # ============================================================================== @@ -118,23 +169,22 @@ cc_library( # License White-box Targets # ============================================================================== -# This target is shared between both license white-box targets. The only this -# target lacks is the actual key data. +# This target provided the license whitebox less the key init data. This will +# only be used by the other license whitebox targets. cc_library( - name = "test_license_whitebox", + name = "license_whitebox_core", srcs = [ "license_whitebox_impl.cc", ], - visibility = ["//visibility:public"], deps = [ ":license_parser", ":memory_util", ":odk", ":odk_license_parser", + ":private_keys", ":protobuf_license_parser", "//api:license_whitebox", "//api:result", - "//api:test_license_whitebox_keys", "//chromium_deps/cdm/keys:dev_certs", "//chromium_deps/cdm/protos:license_protocol_proto", "//crypto_utils:aes_cbc_decryptor", @@ -143,3 +193,36 @@ cc_library( "//crypto_utils:rsa_key", ], ) + +# These targets provid the license whitebox for all general tests. +cc_library( + name = "general_license_whitebox_with_vmpra", + visibility = ["//visibility:public"], + deps = [ + ":license_whitebox_core", + ":protobuf_license_parser_with_vmpra", + "//api:test_license_whitebox_keys_general", + ], +) + +cc_library( + name = "general_license_whitebox_without_vmpra", + visibility = ["//visibility:public"], + deps = [ + ":license_whitebox_core", + ":protobuf_license_parser_without_vmpra", + "//api:test_license_whitebox_keys_general", + ], +) + +# This target provided the license whitebox for the UAT tests. It will use the +# UAT keys. +cc_library( + name = "uat_license_whitebox", + visibility = ["//visibility:public"], + deps = [ + ":license_whitebox_core", + ":protobuf_license_parser_with_vmpra", + "//api:test_license_whitebox_keys_uat", + ], +) diff --git a/whitebox/reference/impl/license_whitebox_impl.cc b/whitebox/reference/impl/license_whitebox_impl.cc index 0a1ad6f..2df3604 100644 --- a/whitebox/reference/impl/license_whitebox_impl.cc +++ b/whitebox/reference/impl/license_whitebox_impl.cc @@ -9,7 +9,6 @@ #include #include -#include "api/test_license_whitebox_keys.h" #include "base/check.h" #include "base/check_op.h" #include "base/logging.h" @@ -28,6 +27,7 @@ #include "reference/impl/memory_util.h" #include "reference/impl/odk.h" #include "reference/impl/odk_license_parser.h" +#include "reference/impl/private_keys.h" #include "reference/impl/protobuf_license_parser.h" #include "reference/impl/renewal_key.h" #include "third_party/boringssl/src/include/openssl/aes.h" @@ -90,8 +90,10 @@ struct WB_License_Whitebox { // license. bool initialized = false; - // CDM key, used for license requests. - std::unique_ptr key; + // CDM key, used for signing license requests. + std::unique_ptr signing_key; + // CDM key, used for decrypting the license response. + std::unique_ptr encryption_key; std::unique_ptr renewal_key; @@ -129,9 +131,9 @@ std::vector GetSecretStringFor(WB_CipherMode mode) { const widevine::ContentKey* FindKey(const WB_License_Whitebox* whitebox, const uint8_t* id, size_t id_size) { - DCHECK(whitebox); - DCHECK(id); - DCHECK_GT(id_size, 0u); + CHECK(whitebox); + CHECK(id); + CHECK_GT(id_size, 0u); const std::string key_id(id, id + id_size); const auto found = whitebox->content_keys.find(key_id); return found == whitebox->content_keys.end() ? nullptr : &found->second; @@ -207,6 +209,13 @@ WB_Result DecryptBuffer(WB_CipherMode mode, return WB_RESULT_OK; } + +std::unique_ptr LoadPrivateKey( + const std::vector& key_data) { + std::string key_string(key_data.begin(), key_data.end()); + return std::unique_ptr(RsaPrivateKey::Create(key_string)); +} + } // namespace WB_Result WB_License_Create(WB_License_Whitebox** whitebox) { @@ -215,15 +224,17 @@ WB_Result WB_License_Create(WB_License_Whitebox** whitebox) { return WB_RESULT_INVALID_PARAMETER; } - const auto init_data = widevine::GetLicensePrivateKey(); - std::unique_ptr key( - RsaPrivateKey::Create(std::string(init_data.begin(), init_data.end()))); - DCHECK(key) << "Failed to load (internal) private key."; + auto signing_key = LoadPrivateKey(widevine::GetSigningPrivateKey()); + CHECK(signing_key) << "Failed to load (internal) signing private key."; + + auto encryption_key = LoadPrivateKey(widevine::GetEncryptionPrivateKey()); + CHECK(encryption_key) << "Failed to load (internal) encryption private key."; // Should always be non-null on modern compilers // (https://isocpp.org/wiki/faq/freestore-mgmt). *whitebox = new WB_License_Whitebox(); - (*whitebox)->key.swap(key); + (*whitebox)->signing_key.swap(signing_key); + (*whitebox)->encryption_key.swap(encryption_key); return WB_RESULT_OK; } @@ -249,7 +260,10 @@ WB_Result WB_License_SignLicenseRequest(const WB_License_Whitebox* whitebox, } std::string result; - CHECK(whitebox->key->GenerateSignature( + + // Regardless of single-key or dual-key, we always use the signing key when + // signing the license request. + CHECK(whitebox->signing_key->GenerateSignature( std::string(license_request, license_request + license_request_size), &result)); @@ -265,6 +279,7 @@ WB_Result WB_License_SignLicenseRequest(const WB_License_Whitebox* whitebox, } WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox, + WB_LicenseKeyMode license_key_mode, const uint8_t* core_message, size_t core_message_size, const uint8_t* message, @@ -314,12 +329,32 @@ WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox, return WB_RESULT_INVALID_PARAMETER; } + const RsaPrivateKey* private_key = nullptr; + + switch (license_key_mode) { + case WB_LICENSE_KEY_MODE_SINGLE_KEY: + // When in single-key mode, we assume that the signing key is our only + // key. + private_key = whitebox->signing_key.get(); + break; + + case WB_LICENSE_KEY_MODE_DUAL_KEY: + private_key = whitebox->encryption_key.get(); + break; + + default: + CHECK(false) << "Unknown license key mode " << license_key_mode; + break; + } + + CHECK(private_key); + // From talking with Intertrust, they suggested allowing an invalid session // key to propogate through the system, leading to the message verification // failing. While we could do that, in the reference, we opt to just return // the signature error now. std::string decrypted_session_key; - if (!whitebox->key->Decrypt( + if (!private_key->Decrypt( std::string(session_key, session_key + session_key_size), &decrypted_session_key)) { DVLOG(1) << "Invalid parameter: invalid session key."; @@ -741,9 +776,9 @@ void WB_License_Unmask(const uint8_t* masked_data, size_t secret_string_size, uint8_t* unmasked_data) { // No return code, so only check if parameters are valid. - DCHECK(masked_data); - DCHECK(secret_string); - DCHECK(unmasked_data); + CHECK(masked_data); + CHECK(secret_string); + CHECK(unmasked_data); for (size_t local_i = 0; local_i < size; local_i++) { const size_t global_i = offset + local_i; diff --git a/whitebox/reference/impl/odk_license_parser.cc b/whitebox/reference/impl/odk_license_parser.cc index aa9f7cd..afe8b51 100644 --- a/whitebox/reference/impl/odk_license_parser.cc +++ b/whitebox/reference/impl/odk_license_parser.cc @@ -2,6 +2,7 @@ #include "reference/impl/odk_license_parser.h" +#include "base/check_op.h" #include "base/logging.h" #include "crypto_utils/crypto_util.h" @@ -99,7 +100,7 @@ WB_Result OdkLicenseParser::Parse(const std::string& decryption_key, } const RenewalKey* OdkLicenseParser::GetRenewalKey() const { - DCHECK_LE(renewal_keys_.size(), 1u); + CHECK_LE(renewal_keys_.size(), 1u); return renewal_keys_.empty() ? nullptr : &renewal_keys_[0]; } @@ -188,4 +189,4 @@ ContentKey OdkLicenseParser::ParseContentKey( return CreateContentKey(security_level, is_hw_verified, unwrapped_key); } -} // namespace widevine \ No newline at end of file +} // namespace widevine diff --git a/whitebox/reference/impl/private_keys.cc b/whitebox/reference/impl/private_keys.cc new file mode 100644 index 0000000..bc1d93e --- /dev/null +++ b/whitebox/reference/impl/private_keys.cc @@ -0,0 +1,24 @@ +// Copyright 2021 Google LLC. All Rights Reserved. + +// For our default implementation of these functions, just use the functions +// in "api/test_license_private_keys.h" so that we only need to change which +// implementation of "api/test_license_private_keys.h" to change which keys +// we actually use. We do this so that the tests can still use +// "api/test_license_private_keys.h" without needing to worry about how the +// implementation is getting its keys. + +#include "reference/impl/private_keys.h" + +#include "api/test_license_whitebox_keys.h" + +namespace widevine { + +std::vector GetEncryptionPrivateKey() { + return GetEncryptionKey().private_key; +} + +std::vector GetSigningPrivateKey() { + return GetSigningKey().private_key; +} + +} // namespace widevine \ No newline at end of file diff --git a/whitebox/reference/impl/private_keys.h b/whitebox/reference/impl/private_keys.h new file mode 100644 index 0000000..a9e54c4 --- /dev/null +++ b/whitebox/reference/impl/private_keys.h @@ -0,0 +1,29 @@ +// Copyright 2021 Google LLC. All Rights Reserved. + +// These functions are used as an abstraction layer between +// "api/test_license_private_keys.h" and the reference white-box implementation +// so that integrators can more easily replace the private keys used by the +// reference white-box when used in their code base (e.g. creating a debug +// build). +// +// When using the reference implementation with different keys than the ones +// defined in the "//api", replace the implementation of these functions +// instead of the replacing the implementation of the functions in "//api". + +#ifndef WHITEBOX_REFERENCE_IMPL_PRIVATE_KEYS_H_ +#define WHITEBOX_REFERENCE_IMPL_PRIVATE_KEYS_H_ + +#include +#include + +namespace widevine { + +// Returns the private encryption key as a DER encoded PKCS#1 key. +std::vector GetEncryptionPrivateKey(); + +// Returns the private signing key as a DER encoded PKCS#1 key. +std::vector GetSigningPrivateKey(); + +} // namespace widevine + +#endif // WHITEBOX_REFERENCE_IMPL_PRIVATE_KEYS_H_ \ No newline at end of file diff --git a/whitebox/reference/impl/protobuf_license_parser.cc b/whitebox/reference/impl/protobuf_license_parser.cc index 72710a8..523680c 100644 --- a/whitebox/reference/impl/protobuf_license_parser.cc +++ b/whitebox/reference/impl/protobuf_license_parser.cc @@ -2,11 +2,26 @@ #include "reference/impl/protobuf_license_parser.h" +#include "base/check_op.h" #include "base/logging.h" #include "crypto_utils/crypto_util.h" namespace widevine { namespace { + +// WV_ENABLE_HW_VERIFICATION = 0: prevent VMP/RA from overriding the key +// security level. +// +// WV_ENABLE_HW_VERIFICATION = 1: allow VMP/RA to override the key security +// level. +#if WV_ENABLE_HW_VERIFICATION == 0 +constexpr bool kEnableHwVerification = false; +#elif WV_ENABLE_HW_VERIFICATION == 1 +constexpr bool kEnableHwVerification = true; +#else +#error Undefined or unknown value for WV_ENABLE_HW_VERIFICATION +#endif // WV_ENABLE_HW_VERIFICATION + // We use "remote_attestation_verified" and "platform_verification_status" to // determine whether the platform is hardware verified. // @@ -64,7 +79,8 @@ WB_Result ProtobufLicenseParser::Parse(const std::string& decryption_key, // available to be used with either decrypt function. Use this flag to // overwrite the calculated values for the internal policies to enable // this behaviour. - const bool is_verified = IsPlatformHardwareVerified(license); + const bool is_verified = + kEnableHwVerification && IsPlatformHardwareVerified(license); for (const auto& key : license.key()) { // The default `type()` value will be SIGNING when not present in the @@ -188,4 +204,4 @@ ContentKey ProtobufLicenseParser::ParseContentKey( return CreateContentKey(key.level(), is_verified, unwrapped_key); } -} // namespace widevine \ No newline at end of file +} // namespace widevine diff --git a/whitebox/reference/tests/BUILD b/whitebox/reference/tests/BUILD index 79fb56e..fe2cda1 100644 --- a/whitebox/reference/tests/BUILD +++ b/whitebox/reference/tests/BUILD @@ -13,9 +13,14 @@ package(default_visibility = [ # # test_aead_whitebox : The target for testing the AEAD white-box. # -# test_license_whitebox : The target for testing the license white-box. The -# white-box should use the private key provided in -# "//api/test_license_whitebox_keys.cc". +# general_license_whitebox_with_vmpra : The target for testing the license +# white-box against generated licenses with VMP/RA functionality. +# +# general_license_whitebox_without_vmpra : The target for testing the license +# white-box against generated licenses without VMP/RA functionality. +# +# uat_license_whitebox : The target for testing the license white-box against +# licenses from Widevine's UAT server. # ============================================================================== # AEAD Test Targets @@ -48,16 +53,25 @@ cc_test( size = "small", deps = [ "//api:license_whitebox_test", - "//reference/impl:test_license_whitebox", + "//reference/impl:general_license_whitebox_without_vmpra", ], ) cc_test( - name = "remote_attestation_and_verification_test", + name = "remote_attestation_and_verification_with_vmpra_test", size = "small", deps = [ - "//api:remote_attestation_and_verification_test", - "//reference/impl:test_license_whitebox", + "//api:remote_attestation_and_verification_with_vmpra_test", + "//reference/impl:general_license_whitebox_with_vmpra", + ], +) + +cc_test( + name = "remote_attestation_and_verification_without_vmpra_test", + size = "small", + deps = [ + "//api:remote_attestation_and_verification_without_vmpra_test", + "//reference/impl:general_license_whitebox_without_vmpra", ], ) @@ -66,7 +80,7 @@ cc_test( size = "small", deps = [ "//api:license_whitebox_benchmark", - "//reference/impl:test_license_whitebox", + "//reference/impl:general_license_whitebox_without_vmpra", ], ) @@ -75,6 +89,6 @@ cc_test( size = "small", deps = [ "//api:license_whitebox_uat_test", - "//reference/impl:test_license_whitebox", + "//reference/impl:uat_license_whitebox", ], )