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.
This commit is contained in:
Aaron Vaage
2021-04-05 12:05:15 -07:00
parent 3c513cc46c
commit f936dd2983
41 changed files with 1803 additions and 809 deletions

View File

@@ -7,20 +7,35 @@
# #
# test_aead_whitebox : The target for testing the AEAD white-box. # test_aead_whitebox : The target for testing the AEAD white-box.
# #
# test_license_whitebox : The target for testing the license white-box. The # general_license_whitebox_with_vmpra : The target for testing the license
# white-box should use the private key provided in # white-box against generated licenses with VMP/RA functionality.
# "//api/test_license_whitebox_keys.cc". #
# 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 = [ package(default_visibility = [
"//visibility:private", "//visibility:private",
]) ])
cc_library( cc_library(
name = "test_aead_whitebox", name = "test_aead_whitebox",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
cc_library( cc_library(
name = "test_license_whitebox", name = "general_license_whitebox_with_vmpra",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
cc_library(
name = "general_license_whitebox_without_vmpra",
visibility = ["//visibility:public"],
)
cc_library(
name = "uat_license_whitebox",
visibility = ["//visibility:public"],
)

View File

@@ -13,9 +13,14 @@ package(default_visibility = [
# #
# test_aead_whitebox : The target for testing the AEAD white-box. # test_aead_whitebox : The target for testing the AEAD white-box.
# #
# test_license_whitebox : The target for testing the license white-box. The # general_license_whitebox_with_vmpra : The target for testing the license
# white-box should use the private key provided in # white-box against generated licenses with VMP/RA functionality.
# "//api/test_license_whitebox_keys.cc". #
# 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 # AEAD Test Targets
@@ -48,16 +53,25 @@ cc_test(
size = "small", size = "small",
deps = [ deps = [
"@whitebox_api//api:license_whitebox_test", "@whitebox_api//api:license_whitebox_test",
"//impl:test_license_whitebox", "//impl:general_license_whitebox_without_vmpra",
], ],
) )
cc_test( cc_test(
name = "remote_attestation_and_verification_test", name = "remote_attestation_and_verification_with_vmpra_test",
size = "small", size = "small",
deps = [ deps = [
"@whitebox_api//api:remote_attestation_and_verification_test", "@whitebox_api//api:remote_attestation_and_verification_with_vmpra_test",
"//impl:test_license_whitebox", "//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", size = "small",
deps = [ deps = [
"@whitebox_api//api:license_whitebox_benchmark", "@whitebox_api//api:license_whitebox_benchmark",
"//impl:test_license_whitebox", "//impl:general_license_whitebox_without_vmpra",
], ],
) )
@@ -75,6 +89,6 @@ cc_test(
size = "small", size = "small",
deps = [ deps = [
"@whitebox_api//api:license_whitebox_uat_test", "@whitebox_api//api:license_whitebox_uat_test",
"//impl:test_license_whitebox", "//impl:uat_license_whitebox",
], ],
) )

View File

@@ -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( cc_library(
name = "test_license_whitebox_keys", name = "test_license_whitebox_keys",
srcs = [
"test_license_whitebox_keys.cc",
],
hdrs = [ hdrs = [
"test_license_whitebox_keys.h", "test_license_whitebox_keys.h",
], ],
visibility = ["//visibility:public"], 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( cc_library(
name = "aead_test_data", name = "aead_test_data",
hdrs = [ 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( cc_library(
name = "test_license_builder", name = "test_license_builder",
srcs = ["test_license_builder.cc"], srcs = ["test_license_builder.cc"],
@@ -79,11 +109,11 @@ cc_library(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
":test_key_types", ":test_key_types",
":test_server",
"//chromium_deps/cdm/keys:dev_certs", "//chromium_deps/cdm/keys:dev_certs",
"//chromium_deps/cdm/protos:license_protocol_proto", "//chromium_deps/cdm/protos:license_protocol_proto",
"//crypto_utils:aes_cbc_encryptor", "//crypto_utils:aes_cbc_encryptor",
"//crypto_utils:crypto_util", "//crypto_utils:crypto_util",
"//crypto_utils:rsa_key",
"//external:odk", "//external:odk",
], ],
) )
@@ -146,6 +176,7 @@ cc_library(
"license_whitebox_decrypt_test.cc", "license_whitebox_decrypt_test.cc",
"license_whitebox_get_secret_string_test.cc", "license_whitebox_get_secret_string_test.cc",
"license_whitebox_key_control_block_test.cc", "license_whitebox_key_control_block_test.cc",
"license_whitebox_license_key_mode.cc",
"license_whitebox_masked_decrypt_test.cc", "license_whitebox_masked_decrypt_test.cc",
"license_whitebox_process_license_response_core_message_test.cc", "license_whitebox_process_license_response_core_message_test.cc",
"license_whitebox_process_license_response_test.cc", "license_whitebox_process_license_response_test.cc",
@@ -167,17 +198,28 @@ cc_library(
alwayslink = True, 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( cc_library(
name = "remote_attestation_and_verification_test", name = "remote_attestation_and_verification_with_vmpra_test",
srcs = [ srcs = [
"remote_attestation_and_verification_test.cc", "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"], visibility = ["//visibility:public"],
deps = [ deps = [
":license_whitebox", ":license_whitebox",

View File

@@ -48,6 +48,16 @@ typedef enum {
WB_KEY_STATUS_CONTENT_KEY_DECRYPT, WB_KEY_STATUS_CONTENT_KEY_DECRYPT,
} WB_KeyStatus; } 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 // 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|. // 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: // Args:
// whitebox (in/out) : The white-box instance that will load the keys. // 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 // core_message (in) : Serialized information communicating the structure of
// |message|. Signature verification should be done on |core_message| + // |message|. Signature verification should be done on |core_message| +
// |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. // 1. The key is considered value and is loaded.
// 2. The key is considered invalid and is not loaded. // 2. The key is considered invalid and is not loaded.
WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox, WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox,
WB_LicenseKeyMode license_key_mode,
const uint8_t* core_message, const uint8_t* core_message,
size_t core_message_size, size_t core_message_size,
const uint8_t* message, const uint8_t* message,

View File

@@ -24,10 +24,10 @@ void LicenseWhiteboxBenchmark::SetUp() {
key_ = data_source_.Get<kBlockSize>(); key_ = data_source_.Get<kBlockSize>();
iv_ = data_source_.Get<kBlockSize>(); iv_ = data_source_.Get<kBlockSize>();
const auto public_key_data = GetLicensePublicKey(); const auto public_key_data = GetEncryptionKey().public_key;
public_key_.reset(RsaPublicKey::Create( encryption_public_key_.reset(RsaPublicKey::Create(
std::string(public_key_data.begin(), public_key_data.end()))); std::string(public_key_data.begin(), public_key_data.end())));
ASSERT_TRUE(public_key_); ASSERT_TRUE(encryption_public_key_);
} }
License LicenseWhiteboxBenchmark::CreateLicense() const { License LicenseWhiteboxBenchmark::CreateLicense() const {
@@ -38,8 +38,10 @@ License LicenseWhiteboxBenchmark::CreateLicense() const {
license_builder.AddContentKey(SecurityLevel::kSoftwareSecureCrypto, key_id_, license_builder.AddContentKey(SecurityLevel::kSoftwareSecureCrypto, key_id_,
key_); key_);
auto server = TestServer::CreateDualKey();
License license; License license;
license_builder.Build(*public_key_, &license); license_builder.Build(*server, &license);
return license; return license;
} }

View File

@@ -26,8 +26,6 @@ class LicenseWhiteboxBenchmark : public ::testing::Test {
DataSource& Data() { return data_source_; } DataSource& Data() { return data_source_; }
const RsaPublicKey* PublicKey() const { return public_key_.get(); }
const KeyId& ContentKeyId() const { return key_id_; } const KeyId& ContentKeyId() const { return key_id_; }
const AesKey& ContentKey() const { return key_; } const AesKey& ContentKey() const { return key_; }
@@ -36,7 +34,7 @@ class LicenseWhiteboxBenchmark : public ::testing::Test {
private: private:
DataSource data_source_; DataSource data_source_;
std::unique_ptr<RsaPublicKey> public_key_; std::unique_ptr<RsaPublicKey> encryption_public_key_;
KeyId key_id_; KeyId key_id_;
AesKey key_; AesKey key_;

View File

@@ -46,14 +46,14 @@ class LicenseWhiteboxDecryptBenchmark
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
const auto license = CreateLicense(); const auto license = CreateLicense();
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license.core_message.data(), license.core_message.size(), license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(), license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(), license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()), license.request.data(), license.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
void TearDown() override { WB_License_Delete(whitebox_); } void TearDown() override { WB_License_Delete(whitebox_); }

View File

@@ -60,17 +60,19 @@ class LicenseWhiteboxDecryptTest : public LicenseWhiteboxTestBase,
builder.AddOperatorSessionKey(non_content_key_id_); builder.AddOperatorSessionKey(non_content_key_id_);
License license; auto server = TestServer::CreateDualKey();
builder.Build(*public_key_, &license);
ASSERT_EQ( License license;
WB_License_ProcessLicenseResponse( builder.Build(*server, &license);
whitebox_, license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), ASSERT_EQ(WB_License_ProcessLicenseResponse(
license.signature.data(), license.signature.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.session_key.data(), license.session_key.size(), license.core_message.data(), license.core_message.size(),
license.request.data(), license.request.size()), license.message.data(), license.message.size(),
WB_RESULT_OK); 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 // We need two special keys for this test, one that will be used for a

View File

@@ -45,17 +45,19 @@ class LicenseWhiteboxGetSecretStringTest : public LicenseWhiteboxTestBase {
builder.AddOperatorSessionKey(non_content_key_id_); builder.AddOperatorSessionKey(non_content_key_id_);
License license; auto server = TestServer::CreateDualKey();
builder.Build(*public_key_, &license);
ASSERT_EQ( License license;
WB_License_ProcessLicenseResponse( builder.Build(*server, &license);
whitebox_, license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), ASSERT_EQ(WB_License_ProcessLicenseResponse(
license.signature.data(), license.signature.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.session_key.data(), license.session_key.size(), license.core_message.data(), license.core_message.size(),
license.request.data(), license.request.size()), license.message.data(), license.message.size(),
WB_RESULT_OK); 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 // We need two special keys for this test, one that will be used for a

View File

@@ -17,6 +17,8 @@ class LicenseWhiteboxKeyControlBlockTest
void SetUp() override { void SetUp() override {
LicenseWhiteboxTestBase::SetUp(); LicenseWhiteboxTestBase::SetUp();
std::tie(kcb_, odk_) = GetParam(); std::tie(kcb_, odk_) = GetParam();
server_ = TestServer::CreateDualKey();
} }
void AddKeyToLicense(const GoldenData::Key& key, void AddKeyToLicense(const GoldenData::Key& key,
@@ -26,6 +28,8 @@ class LicenseWhiteboxKeyControlBlockTest
TestLicenseBuilder::KeyControlBlock kcb_; TestLicenseBuilder::KeyControlBlock kcb_;
TestLicenseBuilder::OdkVersion odk_; TestLicenseBuilder::OdkVersion odk_;
std::unique_ptr<TestServer> server_;
}; };
// Even though we are saying to use the ODK, since the key control block is // 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); AddKeyToLicense(cbc_test_data, &builder);
License license; License license;
builder.Build(*public_key_, &license); builder.Build(*server_, &license);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license.core_message.data(), license.core_message.size(), license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(), license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(), license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()), license.request.data(), license.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
std::vector<uint8_t> plaintext(cbc_test_data.content->ciphertext.size()); std::vector<uint8_t> plaintext(cbc_test_data.content->ciphertext.size());
size_t plaintext_size = plaintext.size(); size_t plaintext_size = plaintext.size();
@@ -77,16 +81,16 @@ TEST_P(LicenseWhiteboxKeyControlBlockTest, MaskedDecrypt) {
AddKeyToLicense(cbc_test_data, &builder); AddKeyToLicense(cbc_test_data, &builder);
License license; License license;
builder.Build(*public_key_, &license); builder.Build(*server_, &license);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license.core_message.data(), license.core_message.size(), license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(), license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(), license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()), license.request.data(), license.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
std::vector<uint8_t> plaintext(cbc_test_data.content->ciphertext.size()); std::vector<uint8_t> plaintext(cbc_test_data.content->ciphertext.size());
size_t plaintext_size = plaintext.size(); size_t plaintext_size = plaintext.size();

View File

@@ -0,0 +1,157 @@
// Copyright 2020 Google LLC. All Rights Reserved.
#include "api/license_whitebox.h"
#include <memory>
#include <string>
#include <vector>
#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<WB_LicenseKeyMode, WB_LicenseKeyMode, bool>> {
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<uint8_t> 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<uint8_t> 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<uint8_t> 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<TestServer> server_;
WB_LicenseKeyMode server_mode_;
WB_LicenseKeyMode client_mode_;
bool should_pass_;
};
TEST_P(LicenseWhiteboxLicenseKeyMode, SignAndProcessLicense) {
std::unique_ptr<TestServer> 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

View File

@@ -72,17 +72,19 @@ class LicenseWhiteboxMaskedDecryptTest
builder.AddOperatorSessionKey(non_content_key_id_); builder.AddOperatorSessionKey(non_content_key_id_);
License license; const auto server = TestServer::CreateDualKey();
builder.Build(*public_key_, &license);
ASSERT_EQ( License license;
WB_License_ProcessLicenseResponse( builder.Build(*server, &license);
whitebox_, license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), ASSERT_EQ(WB_License_ProcessLicenseResponse(
license.signature.data(), license.signature.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.session_key.data(), license.session_key.size(), license.core_message.data(), license.core_message.size(),
license.request.data(), license.request.size()), license.message.data(), license.message.size(),
WB_RESULT_OK); 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 // We need two special keys for this test, one that will be used for a

View File

@@ -45,12 +45,12 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark,
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, license_.core_message.data(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.size(), license_.message.data(), license_.core_message.data(), license_.core_message.size(),
license_.message.size(), license_.signature.data(), license_.message.data(), license_.message.size(),
license_.signature.size(), license_.session_key.data(), license_.signature.data(), license_.signature.size(),
license_.session_key.size(), license_.request.data(), license_.session_key.data(), license_.session_key.size(),
license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
WB_License_Delete(whitebox_); WB_License_Delete(whitebox_);
@@ -78,12 +78,12 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark,
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, license_.core_message.data(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.size(), license_.message.data(), license_.core_message.data(), license_.core_message.size(),
license_.message.size(), license_.signature.data(), license_.message.data(), license_.message.size(),
license_.signature.size(), license_.session_key.data(), license_.signature.data(), license_.signature.size(),
license_.session_key.size(), license_.request.data(), license_.session_key.data(), license_.session_key.size(),
license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
sampler.Push(timer.Get()); sampler.Push(timer.Get());
@@ -109,12 +109,12 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark, ProcessLicenseResponse) {
timer.Reset(); timer.Reset();
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, license_.core_message.data(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.size(), license_.message.data(), license_.core_message.data(), license_.core_message.size(),
license_.message.size(), license_.signature.data(), license_.message.data(), license_.message.size(),
license_.signature.size(), license_.session_key.data(), license_.signature.data(), license_.signature.size(),
license_.session_key.size(), license_.request.data(), license_.session_key.data(), license_.session_key.size(),
license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
sampler.Push(timer.Get()); sampler.Push(timer.Get());

View File

@@ -18,9 +18,10 @@ class LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest
void UseLicenseWithoutSigningKey(OdkVersion odk_version) { void UseLicenseWithoutSigningKey(OdkVersion odk_version) {
TestLicenseBuilder builder; TestLicenseBuilder builder;
builder.GetSettings().odk_version = odk_version; builder.GetSettings().odk_version = odk_version;
builder.AddStubbedContentKey(); builder.AddStubbedContentKey();
builder.Build(*public_key_, &license_);
const auto server = TestServer::CreateDualKey();
builder.Build(*server, &license_);
} }
void UseLicenseWithSigningKey(TestLicenseBuilder::Padding padding, void UseLicenseWithSigningKey(TestLicenseBuilder::Padding padding,
@@ -32,7 +33,8 @@ class LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest
builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey()); builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey());
builder.AddStubbedContentKey(); builder.AddStubbedContentKey();
builder.Build(*public_key_, &license_); auto server = TestServer::CreateDualKey();
builder.Build(*server, &license_);
} }
License license_; License license_;
@@ -43,137 +45,137 @@ class LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithoutOdkAndWithoutSigningKey) { SuccessWithoutOdkAndWithoutSigningKey) {
UseLicenseWithoutSigningKey(OdkVersion::kNone); UseLicenseWithoutSigningKey(OdkVersion::kNone);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_3AndWithoutSigningKey) { SuccessWithOdk16_3AndWithoutSigningKey) {
UseLicenseWithoutSigningKey(OdkVersion::k16_3); UseLicenseWithoutSigningKey(OdkVersion::k16_3);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_5AndWithoutSigningKey) { SuccessWithOdk16_5AndWithoutSigningKey) {
UseLicenseWithoutSigningKey(OdkVersion::k16_5); UseLicenseWithoutSigningKey(OdkVersion::k16_5);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithoutOdkAndWithSigningKeyNoPadding) { SuccessWithoutOdkAndWithSigningKeyNoPadding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone, UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone,
OdkVersion::kNone); OdkVersion::kNone);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_3AndWithSigningKeyNoPadding) { SuccessWithOdk16_3AndWithSigningKeyNoPadding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone, UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone,
OdkVersion::k16_3); OdkVersion::k16_3);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_5AndWithSigningKeyNoPadding) { SuccessWithOdk16_5AndWithSigningKeyNoPadding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone, UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone,
OdkVersion::k16_5); OdkVersion::k16_5);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithoutOdkAndWithSigningKeyPKSC8Padding) { SuccessWithoutOdkAndWithSigningKeyPKSC8Padding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8, UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8,
OdkVersion::kNone); OdkVersion::kNone);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_3AndWithSigningKeyPKSC8Padding) { SuccessWithOdk16_3AndWithSigningKeyPKSC8Padding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8, UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8,
OdkVersion::k16_3); OdkVersion::k16_3);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_5AndWithSigningKeyPKSC8Padding) { SuccessWithOdk16_5AndWithSigningKeyPKSC8Padding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8, UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8,
OdkVersion::k16_5); OdkVersion::k16_5);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
InvalidParameterForNullCoreMessage) { InvalidParameterForNullCoreMessage) {
UseLicenseWithoutSigningKey(OdkVersion::k16_5); UseLicenseWithoutSigningKey(OdkVersion::k16_5);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, /*core_message=*/nullptr, license_.core_message.size(), /*core_message=*/nullptr, license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER); WB_RESULT_INVALID_PARAMETER);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest, TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
@@ -184,14 +186,14 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
// no parameter check will be done. However, since the license was created // no parameter check will be done. However, since the license was created
// with one, signature checking will fail as there is no core message // with one, signature checking will fail as there is no core message
// to be included when checking the signature. // to be included when checking the signature.
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), /*core_message_size=*/0, license_.core_message.data(), /*core_message_size=*/0,
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE); WB_RESULT_INVALID_SIGNATURE);
} }
} // namespace widevine } // namespace widevine

View File

@@ -17,16 +17,21 @@ namespace widevine {
class LicenseWhiteboxProcessLicenseResponseTest class LicenseWhiteboxProcessLicenseResponseTest
: public LicenseWhiteboxTestBase { : public LicenseWhiteboxTestBase {
protected: protected:
void SetUp() {
LicenseWhiteboxTestBase::SetUp();
server_ = TestServer::CreateDualKey();
}
// No content keys. No signing keys. // No content keys. No signing keys.
void UseLicenseWithNoKeys() { void UseLicenseWithNoKeys() {
TestLicenseBuilder builder; TestLicenseBuilder builder;
builder.Build(*public_key_, &license_); builder.Build(*server_, &license_);
} }
void UseLicenseWithoutSigningKey() { void UseLicenseWithoutSigningKey() {
TestLicenseBuilder builder; TestLicenseBuilder builder;
builder.AddStubbedContentKey(); builder.AddStubbedContentKey();
builder.Build(*public_key_, &license_); builder.Build(*server_, &license_);
} }
void UseLicenseWithSigningKey(TestLicenseBuilder::Padding padding) { void UseLicenseWithSigningKey(TestLicenseBuilder::Padding padding) {
@@ -35,51 +40,52 @@ class LicenseWhiteboxProcessLicenseResponseTest
builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey()); builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey());
builder.AddStubbedContentKey(); builder.AddStubbedContentKey();
builder.Build(*public_key_, &license_); builder.Build(*server_, &license_);
} }
std::unique_ptr<TestServer> server_;
License license_; License license_;
}; };
TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithoutSigningKey) { TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithoutSigningKey) {
UseLicenseWithoutSigningKey(); UseLicenseWithoutSigningKey();
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseTest, TEST_F(LicenseWhiteboxProcessLicenseResponseTest,
SuccessWithSigningKeyNoPadding) { SuccessWithSigningKeyNoPadding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone); UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseTest, TEST_F(LicenseWhiteboxProcessLicenseResponseTest,
SuccessWithSigningKeyPKSC8Padding) { SuccessWithSigningKeyPKSC8Padding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8); UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
// If there were multiple signing keys (this can only happen if a license server // 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.AddSigningKey(TestLicenseBuilder::DefaultSigningKey()); builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey());
builder.AddStubbedContentKey(); builder.AddStubbedContentKey();
builder.Build(*public_key_, &license_); builder.Build(*server_, &license_);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseTest, InvalidParameterWithNoKeys) { TEST_F(LicenseWhiteboxProcessLicenseResponseTest, InvalidParameterWithNoKeys) {
UseLicenseWithNoKeys(); UseLicenseWithNoKeys();
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
class LicenseWhiteboxProcessLicenseResponseErrorTest class LicenseWhiteboxProcessLicenseResponseErrorTest
@@ -135,11 +141,12 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
Modify(&license_.message); Modify(&license_.message);
WB_Result result = WB_License_ProcessLicenseResponse( WB_Result result = WB_License_ProcessLicenseResponse(
whitebox_, license_.core_message.data(), license_.core_message.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.message.data(), license_.message.size(), license_.core_message.size(), license_.message.data(),
license_.signature.data(), license_.signature.size(), license_.message.size(), license_.signature.data(),
license_.session_key.data(), license_.session_key.size(), license_.signature.size(), license_.session_key.data(),
license_.request.data(), license_.request.size()); license_.session_key.size(), license_.request.data(),
license_.request.size());
// Depending on where/how the message is verified, an implementation can // Depending on where/how the message is verified, an implementation can
// return invalid parameter or invalid signature. Preferably it would be // return invalid parameter or invalid signature. Preferably it would be
@@ -152,14 +159,14 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidSignatureForModifedSignature) { InvalidSignatureForModifedSignature) {
Modify(&license_.signature); Modify(&license_.signature);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE); WB_RESULT_INVALID_SIGNATURE);
} }
// The license request is used to derive the signing key. If the request was // The license request is used to derive the signing key. If the request was
@@ -168,14 +175,14 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidSignatureForModifedLicenseRequest) { InvalidSignatureForModifedLicenseRequest) {
Modify(&license_.request); Modify(&license_.request);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE); WB_RESULT_INVALID_SIGNATURE);
} }
// If the session key is modified, unwrapping it will fail. Therefore, we will // If the session key is modified, unwrapping it will fail. Therefore, we will
@@ -186,114 +193,122 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidSignatureForModifedSessionKey) { InvalidSignatureForModifedSessionKey) {
Modify(&license_.session_key); Modify(&license_.session_key);
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE); WB_RESULT_INVALID_SIGNATURE);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForNullWhitebox) { 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( ASSERT_EQ(
WB_License_ProcessLicenseResponse( WB_License_ProcessLicenseResponse(
nullptr, license_.core_message.data(), license_.core_message.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.message.data(), license_.message.size(), license_.core_message.size(), nullptr, license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER); 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, TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForZeroMessageSize) { InvalidParameterForZeroMessageSize) {
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(
whitebox_, license_.core_message.data(), WB_License_ProcessLicenseResponse(
license_.core_message.size(), license_.message.data(), 0, whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.signature.data(), license_.signature.size(), license_.core_message.size(), license_.message.data(), 0,
license_.session_key.data(), license_.session_key.size(), license_.signature.data(), license_.signature.size(),
license_.request.data(), license_.request.size()), license_.session_key.data(), license_.session_key.size(),
WB_RESULT_INVALID_PARAMETER); license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForNullSignature) { InvalidParameterForNullSignature) {
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(
whitebox_, license_.core_message.data(), WB_License_ProcessLicenseResponse(
license_.core_message.size(), license_.message.data(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.message.size(), nullptr, license_.signature.size(), license_.core_message.size(), license_.message.data(),
license_.session_key.data(), license_.session_key.size(), license_.message.size(), nullptr, license_.signature.size(),
license_.request.data(), license_.request.size()), license_.session_key.data(), license_.session_key.size(),
WB_RESULT_INVALID_PARAMETER); license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForInvalidSignatureSize) { InvalidParameterForInvalidSignatureSize) {
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(
whitebox_, license_.core_message.data(), WB_License_ProcessLicenseResponse(
license_.core_message.size(), license_.message.data(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.message.size(), license_.signature.data(), 5, license_.core_message.size(), license_.message.data(),
license_.session_key.data(), license_.session_key.size(), license_.message.size(), license_.signature.data(), 5,
license_.request.data(), license_.request.size()), license_.session_key.data(), license_.session_key.size(),
WB_RESULT_INVALID_PARAMETER); license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForNullSessionKey) { InvalidParameterForNullSessionKey) {
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(
whitebox_, license_.core_message.data(), WB_License_ProcessLicenseResponse(
license_.core_message.size(), license_.message.data(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.message.size(), license_.signature.data(), license_.core_message.size(), license_.message.data(),
license_.signature.size(), nullptr, license_.session_key.size(), license_.message.size(), license_.signature.data(),
license_.request.data(), license_.request.size()), license_.signature.size(), nullptr, license_.session_key.size(),
WB_RESULT_INVALID_PARAMETER); license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForInvalidSessionKeySize) { InvalidParameterForInvalidSessionKeySize) {
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(
whitebox_, license_.core_message.data(), WB_License_ProcessLicenseResponse(
license_.core_message.size(), license_.message.data(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.message.size(), license_.signature.data(), license_.core_message.size(), license_.message.data(),
license_.signature.size(), license_.session_key.data(), 5, license_.message.size(), license_.signature.data(),
license_.request.data(), license_.request.size()), license_.signature.size(), license_.session_key.data(), 5,
WB_RESULT_INVALID_PARAMETER); license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForNullLicenseRequest) { InvalidParameterForNullLicenseRequest) {
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(
whitebox_, license_.core_message.data(), WB_License_ProcessLicenseResponse(
license_.core_message.size(), license_.message.data(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.message.size(), license_.signature.data(), license_.core_message.size(), license_.message.data(),
license_.signature.size(), license_.session_key.data(), license_.message.size(), license_.signature.data(),
license_.session_key.size(), nullptr, license_.request.size()), license_.signature.size(), license_.session_key.data(),
WB_RESULT_INVALID_PARAMETER); license_.session_key.size(), nullptr, license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
} }
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest, TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForZeroLienseRequestSize) { InvalidParameterForZeroLienseRequestSize) {
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(
whitebox_, license_.core_message.data(), WB_License_ProcessLicenseResponse(
license_.core_message.size(), license_.message.data(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.message.size(), license_.signature.data(), license_.core_message.size(), license_.message.data(),
license_.signature.size(), license_.session_key.data(), license_.message.size(), license_.signature.data(),
license_.session_key.size(), license_.request.data(), 0), license_.signature.size(), license_.session_key.data(),
WB_RESULT_INVALID_PARAMETER); license_.session_key.size(), license_.request.data(), 0),
WB_RESULT_INVALID_PARAMETER);
} }
class LicenseWhiteboxMultiLicenseTest class LicenseWhiteboxMultiLicenseTest
@@ -313,25 +328,25 @@ class LicenseWhiteboxMultiLicenseTest
TEST_F(LicenseWhiteboxMultiLicenseTest, InvalidState) { TEST_F(LicenseWhiteboxMultiLicenseTest, InvalidState) {
// Load the first license. This one is expected to succeed as the whitebox has // Load the first license. This one is expected to succeed as the whitebox has
// not loaded a license yet. // not loaded a license yet.
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
// Attempt to load the same license again. This should fail as it already has // Attempt to load the same license again. This should fail as it already has
// a license (even though it is the same license). // a license (even though it is the same license).
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_STATE); WB_RESULT_INVALID_STATE);
} }
// Even though a whitebox can only load a license once, if it fails to load a // 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); Modify(&bad_request);
ASSERT_NE( ASSERT_NE(
WB_License_ProcessLicenseResponse( WB_License_ProcessLicenseResponse(
whitebox_, license_.core_message.data(), license_.core_message.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.message.data(), license_.message.size(), license_.core_message.size(), license_.message.data(),
license_.signature.data(), license_.signature.size(), license_.message.size(), license_.signature.data(),
license_.session_key.data(), license_.session_key.size(), license_.signature.size(), license_.session_key.data(),
bad_request.data(), bad_request.size()), license_.session_key.size(), bad_request.data(), bad_request.size()),
WB_RESULT_OK); WB_RESULT_OK);
// Attempt to load the license again, but use the correct (unmodified) // Attempt to load the license again, but use the correct (unmodified)
// request. // request.
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license_.core_message.data(), license_.core_message.size(), license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(), license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(), license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(), license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()), license_.request.data(), license_.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
} // namespace widevine } // namespace widevine

View File

@@ -32,6 +32,8 @@ class LicenseWhiteboxQueryContentKeyStatus
masked_decrypt_key_ = &golden_data_.CBCDecodeKey(); masked_decrypt_key_ = &golden_data_.CBCDecodeKey();
std::tie(license_parsing_, padding_) = GetParam(); std::tie(license_parsing_, padding_) = GetParam();
server_ = TestServer::CreateDualKey();
} }
void SetSettings(const TestLicenseBuilder::Settings& settings) { void SetSettings(const TestLicenseBuilder::Settings& settings) {
@@ -69,20 +71,22 @@ class LicenseWhiteboxQueryContentKeyStatus
builder_.SetSettings(settings); builder_.SetSettings(settings);
License license; License license;
builder_.Build(*public_key_, &license); builder_.Build(*server_, &license);
return WB_License_ProcessLicenseResponse( return WB_License_ProcessLicenseResponse(
whitebox_, license.core_message.data(), license.core_message.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(),
license.message.data(), license.message.size(), license.core_message.size(), license.message.data(),
license.signature.data(), license.signature.size(), license.message.size(), license.signature.data(),
license.session_key.data(), license.session_key.size(), license.signature.size(), license.session_key.data(),
license.request.data(), license.request.size()); license.session_key.size(), license.request.data(),
license.request.size());
} }
const GoldenData::Key* decrypt_key_; const GoldenData::Key* decrypt_key_;
const GoldenData::Key* masked_decrypt_key_; const GoldenData::Key* masked_decrypt_key_;
private: private:
std::unique_ptr<TestServer> server_;
TestLicenseBuilder builder_; TestLicenseBuilder builder_;
LicenseParsing license_parsing_; LicenseParsing license_parsing_;
Padding padding_; Padding padding_;

View File

@@ -65,15 +65,18 @@ class LicenseWhiteboxQuerySigningKeyStatus
builder_.AddContentKey(content_key->level, content_key->id, builder_.AddContentKey(content_key->level, content_key->id,
content_key->content->key); content_key->content->key);
auto server = TestServer::CreateDualKey();
License license; License license;
builder_.Build(*public_key_, &license); builder_.Build(*server, &license);
return WB_License_ProcessLicenseResponse( return WB_License_ProcessLicenseResponse(
whitebox_, license.core_message.data(), license.core_message.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(),
license.message.data(), license.message.size(), license.core_message.size(), license.message.data(),
license.signature.data(), license.signature.size(), license.message.size(), license.signature.data(),
license.session_key.data(), license.session_key.size(), license.signature.size(), license.session_key.data(),
license.request.data(), license.request.size()); license.session_key.size(), license.request.data(),
license.request.size());
} }
private: private:

View File

@@ -40,17 +40,19 @@ TEST_P(LicenseWhiteboxSecurityLevelTest, CanLoadAndUseKey) {
builder.AddContentKey(security_level_, golden_data_.CBCCryptoKey().id, builder.AddContentKey(security_level_, golden_data_.CBCCryptoKey().id,
golden_data_.CBCCryptoKey().content->key); golden_data_.CBCCryptoKey().content->key);
License license; auto server = TestServer::CreateDualKey();
builder.Build(*public_key_, &license);
ASSERT_EQ( License license;
WB_License_ProcessLicenseResponse( builder.Build(*server, &license);
whitebox_, license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), ASSERT_EQ(WB_License_ProcessLicenseResponse(
license.signature.data(), license.signature.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.session_key.data(), license.session_key.size(), license.core_message.data(), license.core_message.size(),
license.request.data(), license.request.size()), license.message.data(), license.message.size(),
WB_RESULT_OK); 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_size_ = golden_data_.CBCCryptoKey().content->ciphertext.size();
plaintext_.resize(plaintext_size_); plaintext_.resize(plaintext_size_);

View File

@@ -34,14 +34,14 @@ class LicenseWhiteboxSignBenchmark : public LicenseWhiteboxBenchmark {
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
const auto license = CreateLicense(); const auto license = CreateLicense();
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license.core_message.data(), license.core_message.size(), license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(), license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(), license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()), license.request.data(), license.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
void TearDown() override { WB_License_Delete(whitebox_); } void TearDown() override { WB_License_Delete(whitebox_); }

View File

@@ -18,8 +18,10 @@ class LicenseWhiteboxSignLicenseRequestTest : public LicenseWhiteboxTestBase {
void SetUp() override { void SetUp() override {
LicenseWhiteboxTestBase::SetUp(); LicenseWhiteboxTestBase::SetUp();
server_ = TestServer::CreateDualKey();
TestLicenseBuilder builder; TestLicenseBuilder builder;
builder.Build(*public_key_, &license_); builder.Build(*server_, &license_);
// We must make the default size large to hold the signature returned by // We must make the default size large to hold the signature returned by
// WB_License_SignLicenseRequest(). // WB_License_SignLicenseRequest().
@@ -35,6 +37,7 @@ class LicenseWhiteboxSignLicenseRequestTest : public LicenseWhiteboxTestBase {
0x18, 0xcc, 0xcb, 0x7e, 0x43, 0x23, 0x06, 0xe9, 0x8f, 0x8f, 0x18, 0xcc, 0xcb, 0x7e, 0x43, 0x23, 0x06, 0xe9, 0x8f, 0x8f,
}; };
std::unique_ptr<TestServer> server_;
License license_; License license_;
// These will be the output from each test case. // These will be the output from each test case.
@@ -51,10 +54,7 @@ TEST_F(LicenseWhiteboxSignLicenseRequestTest, SuccessForInvalidLicenseRequest) {
signature_.resize(signature_size_); signature_.resize(signature_size_);
ASSERT_TRUE(public_key_->VerifySignature( ASSERT_TRUE(server_->Verify(invalid_license_request_, signature_));
std::string(invalid_license_request_.begin(),
invalid_license_request_.end()),
std::string(signature_.begin(), signature_.end())));
} }
TEST_F(LicenseWhiteboxSignLicenseRequestTest, SuccessForValidLicenseRequest) { TEST_F(LicenseWhiteboxSignLicenseRequestTest, SuccessForValidLicenseRequest) {
@@ -65,9 +65,7 @@ TEST_F(LicenseWhiteboxSignLicenseRequestTest, SuccessForValidLicenseRequest) {
signature_.resize(signature_size_); signature_.resize(signature_size_);
ASSERT_TRUE(public_key_->VerifySignature( ASSERT_TRUE(server_->Verify(license_.request, signature_));
std::string(license_.request.begin(), license_.request.end()),
std::string(signature_.begin(), signature_.end())));
} }
TEST_F(LicenseWhiteboxSignLicenseRequestTest, InvalidParameterForNullWhitebox) { TEST_F(LicenseWhiteboxSignLicenseRequestTest, InvalidParameterForNullWhitebox) {

View File

@@ -34,17 +34,19 @@ class LicenseWhiteboxSignRenewalRequestTest : public LicenseWhiteboxTestBase {
// should always have a content key. // should always have a content key.
builder.AddStubbedContentKey(); builder.AddStubbedContentKey();
License license; auto server = TestServer::CreateDualKey();
builder.Build(*public_key_, &license);
ASSERT_EQ( License license;
WB_License_ProcessLicenseResponse( builder.Build(*server, &license);
whitebox_, license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), ASSERT_EQ(WB_License_ProcessLicenseResponse(
license.signature.data(), license.signature.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.session_key.data(), license.session_key.size(), license.core_message.data(), license.core_message.size(),
license.request.data(), license.request.size()), license.message.data(), license.message.size(),
WB_RESULT_OK); 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 // Get the expected signature for |message|. By returning the message, this
@@ -202,17 +204,19 @@ TEST_F(LicenseWhiteboxSignRenewalRequestTest, KeyUnavailableForNoSigningKey) {
TestLicenseBuilder builder; TestLicenseBuilder builder;
builder.AddStubbedContentKey(); builder.AddStubbedContentKey();
License license; auto server = TestServer::CreateDualKey();
builder.Build(*public_key_, &license);
ASSERT_EQ( License license;
WB_License_ProcessLicenseResponse( builder.Build(*server, &license);
whitebox_, license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), ASSERT_EQ(WB_License_ProcessLicenseResponse(
license.signature.data(), license.signature.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.session_key.data(), license.session_key.size(), license.core_message.data(), license.core_message.size(),
license.request.data(), license.request.size()), license.message.data(), license.message.size(),
WB_RESULT_OK); 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(), ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(),
garbage_request_.size(), garbage_request_.size(),

View File

@@ -2,20 +2,12 @@
#include "api/license_whitebox_test_base.h" #include "api/license_whitebox_test_base.h"
#include <string>
#include "api/test_license_whitebox_keys.h" #include "api/test_license_whitebox_keys.h"
namespace widevine { namespace widevine {
void LicenseWhiteboxTestBase::SetUp() { void LicenseWhiteboxTestBase::SetUp() {
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); 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() { void LicenseWhiteboxTestBase::TearDown() {

View File

@@ -22,8 +22,6 @@ class LicenseWhiteboxTestBase : public ::testing::Test {
// to make it easier to invalidate signatures. // to make it easier to invalidate signatures.
void Modify(std::vector<uint8_t>* data) const; void Modify(std::vector<uint8_t>* data) const;
std::unique_ptr<RsaPublicKey> public_key_;
GoldenData golden_data_; GoldenData golden_data_;
WB_License_Whitebox* whitebox_; WB_License_Whitebox* whitebox_;

View File

@@ -312,11 +312,12 @@ class LicenseWhiteboxDecryptUatTest : public ::testing::Test {
TEST_F(LicenseWhiteboxDecryptUatTest, CryptoKeyWithCbcDataInCbcMode) { TEST_F(LicenseWhiteboxDecryptUatTest, CryptoKeyWithCbcDataInCbcMode) {
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(WB_License_ProcessLicenseResponse( ASSERT_EQ(
whitebox_, kCoreMessage, kCoreMessageSize, kMessage, WB_License_ProcessLicenseResponse(
kMessageSize, kSignature, kSignatureSize, kSessionKey, whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, kCoreMessage,
kSessionKeySize, kLicenseRequest, kLicenseRequestSize), kCoreMessageSize, kMessage, kMessageSize, kSignature, kSignatureSize,
WB_RESULT_OK); kSessionKey, kSessionKeySize, kLicenseRequest, kLicenseRequestSize),
WB_RESULT_OK);
size_t plaintext_size = kCiphertextSize; size_t plaintext_size = kCiphertextSize;
std::vector<uint8_t> plaintext(plaintext_size); std::vector<uint8_t> plaintext(plaintext_size);

View File

@@ -30,14 +30,14 @@ class LicenseWhiteboxVerifyBenchmark : public LicenseWhiteboxBenchmark {
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK); ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
const auto license = CreateLicense(); const auto license = CreateLicense();
ASSERT_EQ( ASSERT_EQ(WB_License_ProcessLicenseResponse(
WB_License_ProcessLicenseResponse( whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
whitebox_, license.core_message.data(), license.core_message.size(), license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(), license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(), license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()), license.request.data(), license.request.size()),
WB_RESULT_OK); WB_RESULT_OK);
} }
void TearDown() override { WB_License_Delete(whitebox_); } void TearDown() override { WB_License_Delete(whitebox_); }

View File

@@ -34,17 +34,19 @@ class LicenseWhiteboxVerifyRenewalResponseTest
builder.AddSigningKey(signing_key); builder.AddSigningKey(signing_key);
builder.AddStubbedContentKey(); builder.AddStubbedContentKey();
License license; auto server = TestServer::CreateDualKey();
builder.Build(*public_key_, &license);
ASSERT_EQ( License license;
WB_License_ProcessLicenseResponse( builder.Build(*server, &license);
whitebox_, license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), ASSERT_EQ(WB_License_ProcessLicenseResponse(
license.signature.data(), license.signature.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.session_key.data(), license.session_key.size(), license.core_message.data(), license.core_message.size(),
license.request.data(), license.request.size()), license.message.data(), license.message.size(),
WB_RESULT_OK); 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<uint8_t> Sign(const std::vector<uint8_t>& message) { std::vector<uint8_t> Sign(const std::vector<uint8_t>& message) {
@@ -229,17 +231,19 @@ TEST_F(LicenseWhiteboxVerifyRenewalResponseTest,
widevine::TestLicenseBuilder builder; widevine::TestLicenseBuilder builder;
builder.AddStubbedContentKey(); builder.AddStubbedContentKey();
License license; auto server = TestServer::CreateDualKey();
builder.Build(*public_key_, &license);
ASSERT_EQ( License license;
WB_License_ProcessLicenseResponse( builder.Build(*server, &license);
whitebox_, license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(), ASSERT_EQ(WB_License_ProcessLicenseResponse(
license.signature.data(), license.signature.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.session_key.data(), license.session_key.size(), license.core_message.data(), license.core_message.size(),
license.request.data(), license.request.size()), license.message.data(), license.message.size(),
WB_RESULT_OK); 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_, ASSERT_EQ(WB_License_VerifyRenewalResponse(whitebox_,
garbage_renewal_message_.data(), garbage_renewal_message_.data(),

View File

@@ -8,6 +8,7 @@
#include "api/license_whitebox_test_base.h" #include "api/license_whitebox_test_base.h"
#include "api/result.h" #include "api/result.h"
#include "api/test_license_builder.h" #include "api/test_license_builder.h"
#include "base/check_op.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace widevine { namespace widevine {
@@ -33,6 +34,63 @@ enum class Mode {
kMaskedDecryptPass, kMaskedDecryptPass,
kMaskedDecryptFail, 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 } // namespace
class RemoteAttestationAndVerificationTest class RemoteAttestationAndVerificationTest
@@ -49,6 +107,15 @@ class RemoteAttestationAndVerificationTest
padding_ = std::get<0>(params); padding_ = std::get<0>(params);
std::tie(key, ra_, vmp_, mode_) = std::get<1>(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) { switch (key) {
case Key::kCrypto: case Key::kCrypto:
key_ = golden_data_.CBCCryptoKey(); key_ = golden_data_.CBCCryptoKey();
@@ -72,15 +139,18 @@ class RemoteAttestationAndVerificationTest
builder.GetSettings().verification_status = verification_status; builder.GetSettings().verification_status = verification_status;
builder.GetSettings().padding = padding; builder.GetSettings().padding = padding;
auto server = TestServer::CreateDualKey();
License license; License license;
builder.Build(*public_key_, &license); builder.Build(*server, &license);
return WB_License_ProcessLicenseResponse( return WB_License_ProcessLicenseResponse(
whitebox_, license.core_message.data(), license.core_message.size(), whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(),
license.message.data(), license.message.size(), license.core_message.size(), license.message.data(),
license.signature.data(), license.signature.size(), license.message.size(), license.signature.data(),
license.session_key.data(), license.session_key.size(), license.signature.size(), license.session_key.data(),
license.request.data(), license.request.size()); license.session_key.size(), license.request.data(),
license.request.size());
} }
WB_Result Decrypt(const GoldenData::Key& key) { WB_Result Decrypt(const GoldenData::Key& key) {
@@ -192,293 +262,325 @@ TEST_P(RemoteAttestationAndVerificationTest, Decrypt) {
// however, we have seen issues between VMP + RA + PADDING. // however, we have seen issues between VMP + RA + PADDING.
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
NoRemoteAttestationNoVerification, NoRemoteAttestationNoVerificationDecrypt,
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,
RemoteAttestationAndVerificationTest, RemoteAttestationAndVerificationTest,
::testing::Combine( ::testing::Combine(
::testing::Values(Padding::kNone, Padding::kPKSC8), ::testing::Values(Padding::kNone, Padding::kPKSC8),
::testing::Values( ::testing::Values(std::make_tuple(Key::kCrypto,
// Decrypt RemoteAttestation::kUnavailable,
std::make_tuple(Key::kCrypto, VerificationStatus::kUnavailable,
RemoteAttestation::kUnavailable, Mode::kDecryptPass),
VerificationStatus::kHardwareVerified, std::make_tuple(Key::kDecode,
Mode::kDecryptPass), RemoteAttestation::kUnavailable,
std::make_tuple(Key::kDecode, VerificationStatus::kUnavailable,
RemoteAttestation::kUnavailable, Mode::kDecryptFail),
VerificationStatus::kHardwareVerified, std::make_tuple(Key::kHardware,
Mode::kDecryptPass), RemoteAttestation::kUnavailable,
std::make_tuple(Key::kHardware, VerificationStatus::kUnavailable,
RemoteAttestation::kUnavailable, Mode::kDecryptFail))));
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))));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
UnverifiedRemoteAttestationHardwareVerification, NoRemoteAttestationNoVerificationMaskedDecrypt,
RemoteAttestationAndVerificationTest, RemoteAttestationAndVerificationTest,
::testing::Combine( ::testing::Combine(
::testing::Values(Padding::kNone, Padding::kPKSC8), ::testing::Values(Padding::kNone, Padding::kPKSC8),
::testing::Values( ::testing::Values(std::make_tuple(Key::kCrypto,
// Decrypt RemoteAttestation::kUnavailable,
std::make_tuple(Key::kCrypto, VerificationStatus::kUnavailable,
RemoteAttestation::kUnverified, Mode::kMaskedDecryptPass),
VerificationStatus::kHardwareVerified, std::make_tuple(Key::kDecode,
Mode::kDecryptPass), RemoteAttestation::kUnavailable,
std::make_tuple(Key::kDecode, VerificationStatus::kUnavailable,
RemoteAttestation::kUnverified, Mode::kMaskedDecryptPass),
VerificationStatus::kHardwareVerified, std::make_tuple(Key::kHardware,
Mode::kDecryptFail), RemoteAttestation::kUnavailable,
std::make_tuple(Key::kHardware, VerificationStatus::kUnavailable,
RemoteAttestation::kUnverified, Mode::kMaskedDecryptFail))));
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))));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
VerifiedRemoteAttestationHardwareVerification, UnverifiedRemoteAttestationNoVerificationDecrypt,
RemoteAttestationAndVerificationTest, RemoteAttestationAndVerificationTest,
::testing::Combine( ::testing::Combine(
::testing::Values(Padding::kNone, Padding::kPKSC8), ::testing::Values(Padding::kNone, Padding::kPKSC8),
::testing::Values( ::testing::Values(std::make_tuple(Key::kCrypto,
// Decrypt RemoteAttestation::kUnverified,
std::make_tuple(Key::kCrypto, VerificationStatus::kUnavailable,
RemoteAttestation::kVerified, Mode::kDecryptPass),
VerificationStatus::kHardwareVerified, std::make_tuple(Key::kDecode,
Mode::kDecryptPass), RemoteAttestation::kUnverified,
std::make_tuple(Key::kDecode, VerificationStatus::kUnavailable,
RemoteAttestation::kVerified, Mode::kDecryptFail),
VerificationStatus::kHardwareVerified, std::make_tuple(Key::kHardware,
Mode::kDecryptPass), RemoteAttestation::kUnverified,
std::make_tuple(Key::kHardware, VerificationStatus::kUnavailable,
RemoteAttestation::kVerified, Mode::kDecryptFail))));
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))));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
NoRemoteAttestationOtherVerification, UnverifiedRemoteAttestationNoVerificationMaskedDecrypt,
RemoteAttestationAndVerificationTest, RemoteAttestationAndVerificationTest,
::testing::Combine(::testing::Values(Padding::kNone, Padding::kPKSC8), ::testing::Combine(
::testing::Values( ::testing::Values(Padding::kNone, Padding::kPKSC8),
// Decrypt ::testing::Values(std::make_tuple(Key::kCrypto,
std::make_tuple(Key::kCrypto, RemoteAttestation::kUnverified,
RemoteAttestation::kUnavailable, VerificationStatus::kUnavailable,
VerificationStatus::kOther, Mode::kMaskedDecryptPass),
Mode::kDecryptPass), std::make_tuple(Key::kDecode,
std::make_tuple(Key::kDecode, RemoteAttestation::kUnverified,
RemoteAttestation::kUnavailable, VerificationStatus::kUnavailable,
VerificationStatus::kOther, Mode::kMaskedDecryptPass),
Mode::kDecryptFail), std::make_tuple(Key::kHardware,
std::make_tuple(Key::kHardware, RemoteAttestation::kUnverified,
RemoteAttestation::kUnavailable, VerificationStatus::kUnavailable,
VerificationStatus::kOther, Mode::kMaskedDecryptFail))));
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))));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
UnverifiedRemoteAttestationOtherVerification, VerifiedRemoteAttestationNoVerificationDecrypt,
RemoteAttestationAndVerificationTest, RemoteAttestationAndVerificationTest,
::testing::Combine(::testing::Values(Padding::kNone, Padding::kPKSC8), ::testing::Combine(
::testing::Values( ::testing::Values(Padding::kNone, Padding::kPKSC8),
// Decrypt ::testing::Values(std::make_tuple(Key::kCrypto,
std::make_tuple(Key::kCrypto, RemoteAttestation::kVerified,
RemoteAttestation::kUnverified, VerificationStatus::kUnavailable,
VerificationStatus::kOther, Mode::kDecryptPass),
Mode::kDecryptPass), std::make_tuple(Key::kDecode,
std::make_tuple(Key::kDecode, RemoteAttestation::kVerified,
RemoteAttestation::kUnverified, VerificationStatus::kUnavailable,
VerificationStatus::kOther, Mode::kDecryptPass),
Mode::kDecryptFail), std::make_tuple(Key::kHardware,
std::make_tuple(Key::kHardware, RemoteAttestation::kVerified,
RemoteAttestation::kUnverified, VerificationStatus::kUnavailable,
VerificationStatus::kOther, Mode::kDecryptPass))));
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))));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
VerifiedRemoteAttestationOtherVerification, VerifiedRemoteAttestationNoVerificationMaskedDecrypt,
RemoteAttestationAndVerificationTest, RemoteAttestationAndVerificationTest,
::testing::Combine(::testing::Values(Padding::kNone, Padding::kPKSC8), ::testing::Combine(
::testing::Values( ::testing::Values(Padding::kNone, Padding::kPKSC8),
// Decrypt ::testing::Values(std::make_tuple(Key::kCrypto,
std::make_tuple(Key::kCrypto, RemoteAttestation::kVerified,
RemoteAttestation::kVerified, VerificationStatus::kUnavailable,
VerificationStatus::kOther, Mode::kMaskedDecryptPass),
Mode::kDecryptPass), std::make_tuple(Key::kDecode,
std::make_tuple(Key::kDecode, RemoteAttestation::kVerified,
RemoteAttestation::kVerified, VerificationStatus::kUnavailable,
VerificationStatus::kOther, Mode::kMaskedDecryptPass),
Mode::kDecryptFail), std::make_tuple(Key::kHardware,
std::make_tuple(Key::kHardware, RemoteAttestation::kVerified,
RemoteAttestation::kVerified, VerificationStatus::kUnavailable,
VerificationStatus::kOther, Mode::kMaskedDecryptPass))));
Mode::kDecryptFail),
// Masked Decrypt INSTANTIATE_TEST_SUITE_P(
std::make_tuple(Key::kCrypto, NoRemoteAttestationHardwareVerificationDecrypt,
RemoteAttestation::kVerified, RemoteAttestationAndVerificationTest,
VerificationStatus::kOther, ::testing::Combine(
Mode::kMaskedDecryptPass), ::testing::Values(Padding::kNone, Padding::kPKSC8),
std::make_tuple(Key::kDecode, ::testing::Values(std::make_tuple(Key::kCrypto,
RemoteAttestation::kVerified, RemoteAttestation::kUnavailable,
VerificationStatus::kOther, VerificationStatus::kHardwareVerified,
Mode::kMaskedDecryptPass), Mode::kDecryptPass),
std::make_tuple(Key::kHardware, std::make_tuple(Key::kDecode,
RemoteAttestation::kVerified, RemoteAttestation::kUnavailable,
VerificationStatus::kOther, VerificationStatus::kHardwareVerified,
Mode::kMaskedDecryptFail)))); 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 } // namespace widevine

View File

@@ -405,7 +405,8 @@ TestLicenseBuilder::TestLicenseBuilder() {
serialized_request_ = request_.SerializeAsString(); serialized_request_ = request_.SerializeAsString();
container_key_ = crypto_util::DeriveKey( 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); crypto_util::kWrappingKeySizeBits);
} }
@@ -435,7 +436,7 @@ void TestLicenseBuilder::AddOperatorSessionKey(const KeyId& id) {
operator_session_keys_.push_back(id); operator_session_keys_.push_back(id);
} }
void TestLicenseBuilder::Build(const RsaPublicKey& public_key, void TestLicenseBuilder::Build(const TestServer& server,
License* license) const { License* license) const {
DCHECK(license); DCHECK(license);
@@ -485,12 +486,14 @@ void TestLicenseBuilder::Build(const RsaPublicKey& public_key,
const std::string message_str = response.SerializeAsString(); const std::string message_str = response.SerializeAsString();
std::string signing_key = crypto_util::DeriveKey( 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); crypto_util::kSigningKeySizeBits * 2);
signing_key.resize(crypto_util::kSigningKeySizeBytes); signing_key.resize(crypto_util::kSigningKeySizeBytes);
std::string session_key_str; std::vector<uint8_t> encrypted_session_key = server.Encrypt(
CHECK(public_key.Encrypt(session_key_, &session_key_str)); std::vector<uint8_t>(session_key_.begin(), session_key_.end()));
CHECK_GT(encrypted_session_key.size(), 0u);
std::string oemcrypto_core_message; std::string oemcrypto_core_message;
if (settings_.odk_version != OdkVersion::kNone) { 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->message.assign(message_str.begin(), message_str.end());
license->signature.assign(signature_str.begin(), signature_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 } // namespace widevine

View File

@@ -8,8 +8,8 @@
#include <vector> #include <vector>
#include "api/test_key_types.h" #include "api/test_key_types.h"
#include "api/test_server.h"
#include "cdm/protos/license_protocol.pb.h" #include "cdm/protos/license_protocol.pb.h"
#include "crypto_utils/rsa_key.h"
namespace widevine { namespace widevine {
@@ -142,10 +142,12 @@ class TestLicenseBuilder {
// Gets the serialized license request and response (in components) that would // Gets the serialized license request and response (in components) that would
// have been used in the license exchange. // 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: private:
const std::string session_key_ = "0123456789ABCDEF"; const std::array<uint8_t, 16> session_key_ = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
video_widevine::LicenseRequest request_; video_widevine::LicenseRequest request_;
video_widevine::License response_; video_widevine::License response_;

View File

@@ -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_ #ifndef WHITEBOX_API_TEST_LICENSE_WHITEBOX_KEYS_H_
#define WHITEBOX_API_TEST_LICENSE_WHITEBOX_KEYS_H_ #define WHITEBOX_API_TEST_LICENSE_WHITEBOX_KEYS_H_
#include <stdint.h> #include <cstdint>
#include <vector> #include <vector>
namespace widevine { namespace widevine {
// Returns the private key that the tests expect/require the white-box to use. struct WhiteboxKey {
// This key can be considered a constant, so it can be used outside of the tests // DER encoded PKCS#1 public key.
// to generate the white-box init data needed to initialize the white-box. The std::vector<uint8_t> public_key;
// key will be a DER encoded PKCS#1 RSAPrivateKey.
std::vector<uint8_t> GetLicensePrivateKey();
// Returns the public key that matches the private key returned by // DER encoded PKCS#1 private key.
// |GetLicensePrivateKey()|. The public key will be a DER encoded PKCS#1 std::vector<uint8_t> private_key;
// RSAPublicKey. };
std::vector<uint8_t> GetLicensePublicKey();
WhiteboxKey GetEncryptionKey();
WhiteboxKey GetSigningKey();
} // namespace widevine } // namespace widevine

View File

@@ -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<uint8_t> AsVector(const uint8_t* data, size_t length) {
return std::vector<uint8_t>(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

View File

@@ -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" #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 widevine {
namespace { namespace {
@@ -134,16 +137,29 @@ constexpr uint8_t kDevicePrivateKey[] = {
0xcb, 0x6a, 0x73, 0x10, 0xcb, 0x6a, 0x73, 0x10,
}; };
} // namespace std::vector<uint8_t> AsVector(const uint8_t* data, size_t length) {
return std::vector<uint8_t>(data, data + length);
std::vector<uint8_t> GetLicensePrivateKey() {
return std::vector<uint8_t>(kDevicePrivateKey,
kDevicePrivateKey + sizeof(kDevicePrivateKey));
} }
std::vector<uint8_t> GetLicensePublicKey() { // Since we are going to return the same key for encryption and signing, create
return std::vector<uint8_t>(kDevicePublicKey, // a common function for them to both call.
kDevicePublicKey + sizeof(kDevicePublicKey)); 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 } // namespace widevine

View File

@@ -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<uint8_t> TestServer::Encrypt(
const std::vector<uint8_t>& 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<RsaPublicKey> key(RsaPublicKey::Create(key_str));
CHECK(key);
std::string encrypted_data_str;
return key->Encrypt(data_str, &encrypted_data_str)
? std::vector<uint8_t>(encrypted_data_str.begin(),
encrypted_data_str.end())
: std::vector<uint8_t>();
}
bool TestServer::Verify(const std::vector<uint8_t>& data,
const std::vector<uint8_t>& 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<RsaPublicKey> key(RsaPublicKey::Create(key_str));
CHECK(key);
return key->VerifySignature(data_str, signature_str);
}
std::unique_ptr<TestServer> TestServer::CreateSingleKey() {
return std::unique_ptr<TestServer>(
new TestServer(GetSigningKey(), GetSigningKey()));
}
std::unique_ptr<TestServer> TestServer::CreateDualKey() {
return std::unique_ptr<TestServer>(
new TestServer(GetEncryptionKey(), GetSigningKey()));
}
} // namespace widevine

View File

@@ -0,0 +1,40 @@
// Copyright 2021 Google LLC. All Rights Reserved.
#ifndef WHITEBOX_API_TEST_SERVER_H_
#define WHITEBOX_API_TEST_SERVER_H_
#include <memory>
#include "api/test_license_whitebox_keys.h"
namespace widevine {
class TestServer {
public:
TestServer(const WhiteboxKey& encryption_key, const WhiteboxKey& signing_key);
std::vector<uint8_t> Encrypt(const std::vector<uint8_t>& data) const;
bool Verify(const std::vector<uint8_t>& data,
const std::vector<uint8_t>& signature) const;
// Create a single key server which uses `widevine::GetSigningKey()` for both
// encryption and signing.
static std::unique_ptr<TestServer> CreateSingleKey();
// Create a dual key server which uses `widevine::GetSigningKey()` for signing
// and `widevine::GetEncryptionKey()` for encryption.
static std::unique_ptr<TestServer> 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<uint8_t> encryption_key_;
std::vector<uint8_t> signing_key_;
};
} // namespace widevine
#endif // WHITEBOX_API_TEST_SERVER_H_

View File

@@ -13,9 +13,14 @@ package(default_visibility = [
# #
# test_aead_whitebox : The target for testing the AEAD white-box. # test_aead_whitebox : The target for testing the AEAD white-box.
# #
# test_license_whitebox : The target for testing the license white-box. The # general_license_whitebox_with_vmpra : The target for testing the license
# white-box should use the private key provided in # white-box against generated licenses with VMP/RA functionality.
# "//api/test_license_whitebox_keys.cc". #
# 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 # Internal Targets
@@ -44,7 +49,7 @@ cc_library(
deps = [ deps = [
"//api:license_whitebox", "//api:license_whitebox",
"//chromium_deps/cdm/protos:license_protocol_proto", "//chromium_deps/cdm/protos:license_protocol_proto",
] ],
) )
cc_library( cc_library(
@@ -61,8 +66,8 @@ cc_library(
hdrs = ["license_parser.h"], hdrs = ["license_parser.h"],
deps = [ deps = [
":content_key", ":content_key",
":renewal_key",
":odk", ":odk",
":renewal_key",
"//api:result", "//api:result",
"//chromium_deps/cdm/protos:license_protocol_proto", "//chromium_deps/cdm/protos:license_protocol_proto",
"//crypto_utils:aes_cbc_decryptor", "//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( cc_library(
name = "protobuf_license_parser", name = "protobuf_license_parser",
srcs = ["protobuf_license_parser.cc"],
hdrs = ["protobuf_license_parser.h"], hdrs = ["protobuf_license_parser.h"],
deps = [ deps = [
":license_parser", ":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/base:glog",
"//chromium_deps/cdm/protos:license_protocol_proto", "//chromium_deps/cdm/protos:license_protocol_proto",
"//crypto_utils:crypto_util", "//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 # AEAD White-box Targets
# ============================================================================== # ==============================================================================
@@ -118,23 +169,22 @@ cc_library(
# License White-box Targets # License White-box Targets
# ============================================================================== # ==============================================================================
# This target is shared between both license white-box targets. The only this # This target provided the license whitebox less the key init data. This will
# target lacks is the actual key data. # only be used by the other license whitebox targets.
cc_library( cc_library(
name = "test_license_whitebox", name = "license_whitebox_core",
srcs = [ srcs = [
"license_whitebox_impl.cc", "license_whitebox_impl.cc",
], ],
visibility = ["//visibility:public"],
deps = [ deps = [
":license_parser", ":license_parser",
":memory_util", ":memory_util",
":odk", ":odk",
":odk_license_parser", ":odk_license_parser",
":private_keys",
":protobuf_license_parser", ":protobuf_license_parser",
"//api:license_whitebox", "//api:license_whitebox",
"//api:result", "//api:result",
"//api:test_license_whitebox_keys",
"//chromium_deps/cdm/keys:dev_certs", "//chromium_deps/cdm/keys:dev_certs",
"//chromium_deps/cdm/protos:license_protocol_proto", "//chromium_deps/cdm/protos:license_protocol_proto",
"//crypto_utils:aes_cbc_decryptor", "//crypto_utils:aes_cbc_decryptor",
@@ -143,3 +193,36 @@ cc_library(
"//crypto_utils:rsa_key", "//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",
],
)

View File

@@ -9,7 +9,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "api/test_license_whitebox_keys.h"
#include "base/check.h" #include "base/check.h"
#include "base/check_op.h" #include "base/check_op.h"
#include "base/logging.h" #include "base/logging.h"
@@ -28,6 +27,7 @@
#include "reference/impl/memory_util.h" #include "reference/impl/memory_util.h"
#include "reference/impl/odk.h" #include "reference/impl/odk.h"
#include "reference/impl/odk_license_parser.h" #include "reference/impl/odk_license_parser.h"
#include "reference/impl/private_keys.h"
#include "reference/impl/protobuf_license_parser.h" #include "reference/impl/protobuf_license_parser.h"
#include "reference/impl/renewal_key.h" #include "reference/impl/renewal_key.h"
#include "third_party/boringssl/src/include/openssl/aes.h" #include "third_party/boringssl/src/include/openssl/aes.h"
@@ -90,8 +90,10 @@ struct WB_License_Whitebox {
// license. // license.
bool initialized = false; bool initialized = false;
// CDM key, used for license requests. // CDM key, used for signing license requests.
std::unique_ptr<RsaPrivateKey> key; std::unique_ptr<RsaPrivateKey> signing_key;
// CDM key, used for decrypting the license response.
std::unique_ptr<RsaPrivateKey> encryption_key;
std::unique_ptr<widevine::RenewalKey> renewal_key; std::unique_ptr<widevine::RenewalKey> renewal_key;
@@ -129,9 +131,9 @@ std::vector<uint8_t> GetSecretStringFor(WB_CipherMode mode) {
const widevine::ContentKey* FindKey(const WB_License_Whitebox* whitebox, const widevine::ContentKey* FindKey(const WB_License_Whitebox* whitebox,
const uint8_t* id, const uint8_t* id,
size_t id_size) { size_t id_size) {
DCHECK(whitebox); CHECK(whitebox);
DCHECK(id); CHECK(id);
DCHECK_GT(id_size, 0u); CHECK_GT(id_size, 0u);
const std::string key_id(id, id + id_size); const std::string key_id(id, id + id_size);
const auto found = whitebox->content_keys.find(key_id); const auto found = whitebox->content_keys.find(key_id);
return found == whitebox->content_keys.end() ? nullptr : &found->second; return found == whitebox->content_keys.end() ? nullptr : &found->second;
@@ -207,6 +209,13 @@ WB_Result DecryptBuffer(WB_CipherMode mode,
return WB_RESULT_OK; return WB_RESULT_OK;
} }
std::unique_ptr<RsaPrivateKey> LoadPrivateKey(
const std::vector<uint8_t>& key_data) {
std::string key_string(key_data.begin(), key_data.end());
return std::unique_ptr<RsaPrivateKey>(RsaPrivateKey::Create(key_string));
}
} // namespace } // namespace
WB_Result WB_License_Create(WB_License_Whitebox** whitebox) { 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; return WB_RESULT_INVALID_PARAMETER;
} }
const auto init_data = widevine::GetLicensePrivateKey(); auto signing_key = LoadPrivateKey(widevine::GetSigningPrivateKey());
std::unique_ptr<RsaPrivateKey> key( CHECK(signing_key) << "Failed to load (internal) signing private key.";
RsaPrivateKey::Create(std::string(init_data.begin(), init_data.end())));
DCHECK(key) << "Failed to load (internal) 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 // Should always be non-null on modern compilers
// (https://isocpp.org/wiki/faq/freestore-mgmt). // (https://isocpp.org/wiki/faq/freestore-mgmt).
*whitebox = new WB_License_Whitebox(); *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; return WB_RESULT_OK;
} }
@@ -249,7 +260,10 @@ WB_Result WB_License_SignLicenseRequest(const WB_License_Whitebox* whitebox,
} }
std::string result; 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), std::string(license_request, license_request + license_request_size),
&result)); &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_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox,
WB_LicenseKeyMode license_key_mode,
const uint8_t* core_message, const uint8_t* core_message,
size_t core_message_size, size_t core_message_size,
const uint8_t* message, const uint8_t* message,
@@ -314,12 +329,32 @@ WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox,
return WB_RESULT_INVALID_PARAMETER; 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 // From talking with Intertrust, they suggested allowing an invalid session
// key to propogate through the system, leading to the message verification // 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 // failing. While we could do that, in the reference, we opt to just return
// the signature error now. // the signature error now.
std::string decrypted_session_key; std::string decrypted_session_key;
if (!whitebox->key->Decrypt( if (!private_key->Decrypt(
std::string(session_key, session_key + session_key_size), std::string(session_key, session_key + session_key_size),
&decrypted_session_key)) { &decrypted_session_key)) {
DVLOG(1) << "Invalid parameter: invalid 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, size_t secret_string_size,
uint8_t* unmasked_data) { uint8_t* unmasked_data) {
// No return code, so only check if parameters are valid. // No return code, so only check if parameters are valid.
DCHECK(masked_data); CHECK(masked_data);
DCHECK(secret_string); CHECK(secret_string);
DCHECK(unmasked_data); CHECK(unmasked_data);
for (size_t local_i = 0; local_i < size; local_i++) { for (size_t local_i = 0; local_i < size; local_i++) {
const size_t global_i = offset + local_i; const size_t global_i = offset + local_i;

View File

@@ -2,6 +2,7 @@
#include "reference/impl/odk_license_parser.h" #include "reference/impl/odk_license_parser.h"
#include "base/check_op.h"
#include "base/logging.h" #include "base/logging.h"
#include "crypto_utils/crypto_util.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 { 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]; return renewal_keys_.empty() ? nullptr : &renewal_keys_[0];
} }
@@ -188,4 +189,4 @@ ContentKey OdkLicenseParser::ParseContentKey(
return CreateContentKey(security_level, is_hw_verified, unwrapped_key); return CreateContentKey(security_level, is_hw_verified, unwrapped_key);
} }
} // namespace widevine } // namespace widevine

View File

@@ -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<uint8_t> GetEncryptionPrivateKey() {
return GetEncryptionKey().private_key;
}
std::vector<uint8_t> GetSigningPrivateKey() {
return GetSigningKey().private_key;
}
} // namespace widevine

View File

@@ -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 <cstdint>
#include <vector>
namespace widevine {
// Returns the private encryption key as a DER encoded PKCS#1 key.
std::vector<uint8_t> GetEncryptionPrivateKey();
// Returns the private signing key as a DER encoded PKCS#1 key.
std::vector<uint8_t> GetSigningPrivateKey();
} // namespace widevine
#endif // WHITEBOX_REFERENCE_IMPL_PRIVATE_KEYS_H_

View File

@@ -2,11 +2,26 @@
#include "reference/impl/protobuf_license_parser.h" #include "reference/impl/protobuf_license_parser.h"
#include "base/check_op.h"
#include "base/logging.h" #include "base/logging.h"
#include "crypto_utils/crypto_util.h" #include "crypto_utils/crypto_util.h"
namespace widevine { namespace widevine {
namespace { 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 // We use "remote_attestation_verified" and "platform_verification_status" to
// determine whether the platform is hardware verified. // 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 // available to be used with either decrypt function. Use this flag to
// overwrite the calculated values for the internal policies to enable // overwrite the calculated values for the internal policies to enable
// this behaviour. // this behaviour.
const bool is_verified = IsPlatformHardwareVerified(license); const bool is_verified =
kEnableHwVerification && IsPlatformHardwareVerified(license);
for (const auto& key : license.key()) { for (const auto& key : license.key()) {
// The default `type()` value will be SIGNING when not present in the // 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); return CreateContentKey(key.level(), is_verified, unwrapped_key);
} }
} // namespace widevine } // namespace widevine

View File

@@ -13,9 +13,14 @@ package(default_visibility = [
# #
# test_aead_whitebox : The target for testing the AEAD white-box. # test_aead_whitebox : The target for testing the AEAD white-box.
# #
# test_license_whitebox : The target for testing the license white-box. The # general_license_whitebox_with_vmpra : The target for testing the license
# white-box should use the private key provided in # white-box against generated licenses with VMP/RA functionality.
# "//api/test_license_whitebox_keys.cc". #
# 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 # AEAD Test Targets
@@ -48,16 +53,25 @@ cc_test(
size = "small", size = "small",
deps = [ deps = [
"//api:license_whitebox_test", "//api:license_whitebox_test",
"//reference/impl:test_license_whitebox", "//reference/impl:general_license_whitebox_without_vmpra",
], ],
) )
cc_test( cc_test(
name = "remote_attestation_and_verification_test", name = "remote_attestation_and_verification_with_vmpra_test",
size = "small", size = "small",
deps = [ deps = [
"//api:remote_attestation_and_verification_test", "//api:remote_attestation_and_verification_with_vmpra_test",
"//reference/impl:test_license_whitebox", "//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", size = "small",
deps = [ deps = [
"//api:license_whitebox_benchmark", "//api:license_whitebox_benchmark",
"//reference/impl:test_license_whitebox", "//reference/impl:general_license_whitebox_without_vmpra",
], ],
) )
@@ -75,6 +89,6 @@ cc_test(
size = "small", size = "small",
deps = [ deps = [
"//api:license_whitebox_uat_test", "//api:license_whitebox_uat_test",
"//reference/impl:test_license_whitebox", "//reference/impl:uat_license_whitebox",
], ],
) )