Update to latest version including support for Partner Keys

Includes change to WB_License_Create() so that it includes a separate
parameter that specifies the init data used for Provider Keys.

This updates the repo to match the internal repo at commit:
8c1c4338906a32eed83eb63702690d1f02ff7cd0
This commit is contained in:
John Rummell
2021-12-13 16:40:24 -08:00
parent 3535007a69
commit adb98d80d3
51 changed files with 1104 additions and 474 deletions

View File

@@ -26,7 +26,7 @@ git_repository(
git_repository(
name = "boringssl_repo",
commit = "14164f6fef47b7ebd97cdb0cea1624eabd6fe6b8", # 2018-11-26
commit = "4fb158925f7753d80fb858cb0239dff893ef9f15", # 2021-11-01
remote = "https://github.com/google/boringssl.git",
)

View File

@@ -77,6 +77,25 @@ cc_library(
visibility = ["//visibility:public"],
)
cc_library(
name = "test_license_provider_keys",
srcs = [
"test_license_provider_keys.cc",
],
hdrs = [
"test_license_provider_keys.h",
],
visibility = ["//visibility:public"],
)
cc_library(
name = "license_whitebox_provider_keys_test_data",
hdrs = [
"license_whitebox_provider_keys_test_data.h",
],
visibility = ["//visibility:public"],
)
cc_library(
name = "golden_data",
srcs = [
@@ -109,6 +128,7 @@ cc_library(
visibility = ["//visibility:public"],
deps = [
":test_key_types",
":test_license_provider_keys",
":test_server",
"//chromium_deps/cdm/keys:dev_certs",
"//chromium_deps/cdm/protos:license_protocol_proto",
@@ -163,6 +183,7 @@ cc_library(
deps = [
":golden_data",
":license_whitebox",
":license_whitebox_provider_keys_test_data",
":test_license_whitebox_keys",
"//chromium_deps/testing",
"//crypto_utils:rsa_key",
@@ -191,6 +212,7 @@ cc_library(
deps = [
":golden_data",
":license_whitebox",
":license_whitebox_provider_keys_test_data",
":license_whitebox_test_base",
":test_license_builder",
"//chromium_deps/testing",
@@ -245,6 +267,7 @@ cc_library(
visibility = ["//visibility:public"],
deps = [
":license_whitebox",
":license_whitebox_provider_keys_test_data",
":test_key_types",
":test_license_builder",
":test_license_whitebox_keys",
@@ -265,6 +288,7 @@ cc_library(
visibility = ["//visibility:public"],
deps = [
":license_whitebox",
":license_whitebox_provider_keys_test_data",
"//chromium_deps/testing",
],
alwayslink = True,

View File

@@ -62,6 +62,11 @@ typedef enum {
// key|. A pointer to the white-box instance will be returned via |whitebox|.
//
// Args:
// whitebox_init_data (in): The white-box initialization data for Provider
// Keys.
//
// whitebox_init_data_size (in): The number of bytes in whitebox_init_data.
//
// whitebox (out) : The output parameter used to return the new white-box
// instance.
//
@@ -71,7 +76,9 @@ typedef enum {
// WB_RESULT_INVALID_PARAMETER if |whitebox| was null.
//
// WB_RESULT_OUT_OF_MEMORY if the necessary memory could not be allocated.
WB_Result WB_License_Create(WB_License_Whitebox** whitebox);
WB_Result WB_License_Create(const uint8_t* whitebox_init_data,
size_t whitebox_init_data_size,
WB_License_Whitebox** whitebox);
// Releases all resources used by the white-box instance pointed to by
// |whitebox|.
@@ -151,6 +158,10 @@ WB_Result WB_License_SignLicenseRequest(const WB_License_Whitebox* whitebox,
//
// session_key_size (in) : The number of bytes in |session_key|.
//
// provider_key_id (in) : The Provider Key Id. If it is 0 or invalid, it falls
// back to no Provider Key; otherwise, the indexed Provider Key is used to
// decrypt the Content Key after it is decrypted by Key Encryption Key.
//
// license_request (in) : The license request that was sent in order to get the
// license response.
//
@@ -193,6 +204,7 @@ WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox,
size_t signature_size,
const uint8_t* session_key,
size_t session_key_size,
size_t provider_key_id,
const uint8_t* license_request,
size_t license_request_size);

View File

@@ -37,8 +37,13 @@ void LicenseWhiteboxBenchmark::SetUp() {
License LicenseWhiteboxBenchmark::CreateLicense(WB_LicenseKeyMode key_mode,
int number_of_content_keys,
SecurityLevel security_level) {
SecurityLevel security_level,
size_t provider_key_id) {
TestLicenseBuilder::Settings settings;
settings.provider_key_id = provider_key_id;
TestLicenseBuilder license_builder;
license_builder.SetSettings(settings);
license_builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey());
// Update the first key to match the security level.

View File

@@ -21,14 +21,15 @@ class LicenseWhiteboxBenchmark : public ::testing::Test {
virtual void SetUp() override;
// Create a new license with the specified number of content keys using the
// security_level provided. The first content key will use
// kSoftwareSecureCrypto, while the remainder will be specified by
// security_level and provider key id provided. The first content key will
// use kSoftwareSecureCrypto, while the remainder will be specified by
// |security_level|. The given key mode will change how the license is
// encrypted and signed. The white-box instance is expected to use the
// correct key mode in order to process the license response.
License CreateLicense(WB_LicenseKeyMode key_mode,
int number_of_content_keys,
SecurityLevel security_level);
SecurityLevel security_level,
size_t provider_key_id);
// Sign the message using the default HMAC signing key.
std::vector<uint8_t> SignAsServer(const std::vector<uint8_t>& message) const;

View File

@@ -2,6 +2,7 @@
#include "api/license_whitebox.h"
#include "api/license_whitebox_provider_keys_test_data.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -15,12 +16,30 @@ class LicenseWhiteboxCreateTest : public ::testing::Test {
};
TEST_F(LicenseWhiteboxCreateTest, Succeeds) {
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(WB_License_Create(nullptr, 0, &whitebox_), WB_RESULT_OK);
ASSERT_TRUE(whitebox_);
}
TEST_F(LicenseWhiteboxCreateTest, InvalidParameterForNullWhitebox) {
ASSERT_EQ(WB_License_Create(nullptr), WB_RESULT_INVALID_PARAMETER);
ASSERT_EQ(WB_License_Create(nullptr, 0, nullptr),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxCreateTest, ValidParameterForInitData) {
auto init_data = widevine::GetLicenseWhiteboxProviderKeysInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxCreateTest, InvalidParameterForInitData) {
auto init_data = widevine::GetLicenseWhiteboxProviderKeysInitData();
ASSERT_EQ(WB_License_Create(nullptr, init_data.size(), &whitebox_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxCreateTest, ValidParameterForInitDataSize) {
auto init_data = widevine::GetLicenseWhiteboxProviderKeysInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), 0, &whitebox_), WB_RESULT_OK);
}
} // namespace

View File

@@ -8,6 +8,7 @@
#include "api/license_whitebox.h"
#include "api/license_whitebox_benchmark.h"
#include "api/license_whitebox_provider_keys_test_data.h"
#include "api/result.h"
#include "api/test_license_builder.h"
#include "benchmarking/data_source.h"
@@ -43,18 +44,22 @@ class LicenseWhiteboxDecryptBenchmark
masked_text_.resize(bytes_per_call);
plaintext_.resize(bytes_per_call);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
const auto license = CreateLicense(WB_LICENSE_KEY_MODE_DUAL_KEY, 1,
SecurityLevel::kSoftwareSecureCrypto);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
auto init_data = GetLicenseWhiteboxProviderKeysInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
const auto license =
CreateLicense(WB_LICENSE_KEY_MODE_DUAL_KEY, 1,
SecurityLevel::kSoftwareSecureCrypto, kNoProviderKeyId);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
kNoProviderKeyId, license.request.data(), license.request.size()),
WB_RESULT_OK);
}
void TearDown() override { WB_License_Delete(whitebox_); }

View File

@@ -17,10 +17,16 @@ namespace {
using Padding = TestLicenseBuilder::Padding;
const size_t kValidProviderKeyId1 = 1;
const size_t kValidProviderKeyId2 = 2;
const size_t kInvalidProviderKeyId = 0xfff;
// There is also kNoProviderKeyId specified in test_license_builder.
} // namespace
class LicenseWhiteboxDecryptTest : public LicenseWhiteboxTestBase,
public testing::WithParamInterface<Padding> {
class LicenseWhiteboxDecryptTest
: public LicenseWhiteboxTestBase,
public ::testing::WithParamInterface<std::tuple<Padding, size_t>> {
protected:
void SetUp() override {
LicenseWhiteboxTestBase::SetUp();
@@ -34,13 +40,21 @@ class LicenseWhiteboxDecryptTest : public LicenseWhiteboxTestBase,
non_content_key_id_ = golden_data_.GetFreeId();
missing_key_id_ = golden_data_.GetFreeId();
padding_ = GetParam();
padding_ = std::get<0>(GetParam());
provider_key_id_ = std::get<1>(GetParam());
}
void LoadLicense(const TestLicenseBuilder::Settings& settings) {
// Creates and loads a license. The license is created using |settings|
// updated to include the test parameters. The license is loaded using
// |provider_key_id|.
void LoadLicense(const TestLicenseBuilder::Settings& settings,
size_t provider_key_id) {
TestLicenseBuilder builder;
builder.SetSettings(settings);
// Update settings with the test specified parameters.
builder.GetSettings().padding = padding_;
builder.GetSettings().provider_key_id = provider_key_id_;
builder.AddContentKey(golden_data_.CBCContent().software_crypto_key);
builder.AddContentKey(golden_data_.CBCContent().software_decode_key);
@@ -55,14 +69,15 @@ class LicenseWhiteboxDecryptTest : public LicenseWhiteboxTestBase,
License license;
builder.Build(*server, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
provider_key_id, license.request.data(), license.request.size()),
WB_RESULT_OK);
}
// We need two special keys for this test, one that will be used for a
@@ -75,11 +90,12 @@ class LicenseWhiteboxDecryptTest : public LicenseWhiteboxTestBase,
std::vector<uint8_t> plaintext_;
Padding padding_;
size_t provider_key_id_;
};
TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -97,7 +113,7 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCbc) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
memcpy(plaintext_.data(), golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size());
@@ -117,7 +133,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCbc) {
TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCtrMode) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CTR,
@@ -135,7 +151,7 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCtrMode) {
TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCtr) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
memcpy(plaintext_.data(), golden_data_.CTRContent().ciphertext.data(),
golden_data_.CTRContent().ciphertext.size());
@@ -157,7 +173,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCtr) {
// successful, but the resulting plaintext should not match.
TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCtrMode) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CTR,
@@ -177,7 +193,7 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCtrMode) {
// successful, but the resulting plaintext should not match.
TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCbcMode) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -197,7 +213,7 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCbcMode) {
// different keys can be used at the same time.
TEST_P(LicenseWhiteboxDecryptTest, SuccessWithMultipleKeys) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -234,7 +250,7 @@ TEST_P(LicenseWhiteboxDecryptTest, SuccessWithMultipleKeys) {
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullWhitebox) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
nullptr, WB_CIPHER_MODE_CBC,
@@ -250,7 +266,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullWhitebox) {
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCipherMode) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
// In order to trick the compiler into letting us pass an invalid enum value
// to WB__License_Decrypt(), we need to cast it. If we don't do this, the
@@ -271,7 +287,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCipherMode) {
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullKeyId) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC, nullptr,
@@ -286,7 +302,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullKeyId) {
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroKeyIdSize) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -301,7 +317,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroKeyIdSize) {
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullInputData) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -318,7 +334,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullInputData) {
// not care.
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCBCInputDataSize) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -334,7 +350,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCBCInputDataSize) {
// The white-box (using any cipher mode) should reject input with size zero.
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroInputDataSize) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -349,7 +365,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroInputDataSize) {
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullIV) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -365,7 +381,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullIV) {
// IV size should be 16. Any number other than 16 should fail.
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidIVSize) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -380,7 +396,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidIVSize) {
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutput) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -395,7 +411,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutput) {
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutputSize) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(
WB_License_Decrypt(
@@ -414,7 +430,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutputSize) {
// and "dropped content key", as those keys were in the license but ignored.
TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForMissingKeyId) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC,
missing_key_id_.data(), missing_key_id_.size(),
@@ -428,7 +444,7 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForMissingKeyId) {
TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForNonContentKey) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(
WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC,
@@ -446,7 +462,7 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForNonContentKey) {
TEST_P(LicenseWhiteboxDecryptTest,
InsufficientSecurityLevelForHardwareContentKey) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().hardware_key.id.data(),
@@ -461,7 +477,7 @@ TEST_P(LicenseWhiteboxDecryptTest,
TEST_P(LicenseWhiteboxDecryptTest, InsufficientSecurityLevelForDecodeKey) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
// Use the software decode key as they are limited to
// WB_License_Decrypt().
@@ -479,7 +495,7 @@ TEST_P(LicenseWhiteboxDecryptTest, InsufficientSecurityLevelForDecodeKey) {
TEST_P(LicenseWhiteboxDecryptTest, BufferTooSmall) {
TestLicenseBuilder::Settings settings;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
// Our ciphertext will be large enough that we should not need to worry about
// using a constant here.
@@ -524,7 +540,7 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForInvalidKey) {
// we just need an invalid key, so we use one way of invalidating the key.
TestLicenseBuilder::Settings settings;
settings.include_content_key_iv = false;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -538,11 +554,61 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForInvalidKey) {
WB_RESULT_KEY_UNAVAILABLE);
}
INSTANTIATE_TEST_SUITE_P(NoPadding,
LicenseWhiteboxDecryptTest,
::testing::Values(Padding::kNone));
// For this test, we create a license using the test specified Provider Key
// Id, then load the license using a different Provider Key Id.
TEST_P(LicenseWhiteboxDecryptTest, MismatchProviderKeyId) {
// These tests use 2 valid provider key IDs, so try loading the license
// with a different key. Not all possible combinations are tested.
size_t other_provider_key_id = kInvalidProviderKeyId;
switch (provider_key_id_) {
case kNoProviderKeyId:
other_provider_key_id = kValidProviderKeyId1;
break;
case kValidProviderKeyId1:
other_provider_key_id = kValidProviderKeyId2;
break;
case kValidProviderKeyId2:
other_provider_key_id = kNoProviderKeyId;
break;
case kInvalidProviderKeyId:
// This is the same as kNoProviderKeyId, so use one of the valid ids.
other_provider_key_id = kValidProviderKeyId2;
break;
}
INSTANTIATE_TEST_SUITE_P(PKSC8,
LicenseWhiteboxDecryptTest,
::testing::Values(Padding::kPKSC8));
TestLicenseBuilder::Settings settings;
LoadLicense(settings, other_provider_key_id);
// Decryption should succeed, but the plaintext should be incorrect.
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_OK);
plaintext_.resize(plaintext_size_);
ASSERT_NE(plaintext_, golden_data_.CBCContent().plaintext);
}
INSTANTIATE_TEST_SUITE_P(
NoPadding,
LicenseWhiteboxDecryptTest,
::testing::Combine(::testing::Values(Padding::kNone),
::testing::Values(kNoProviderKeyId,
kValidProviderKeyId1,
kValidProviderKeyId2,
kInvalidProviderKeyId)));
INSTANTIATE_TEST_SUITE_P(
PKSC8,
LicenseWhiteboxDecryptTest,
::testing::Combine(::testing::Values(Padding::kPKSC8),
::testing::Values(kNoProviderKeyId,
kValidProviderKeyId1,
kValidProviderKeyId2,
kInvalidProviderKeyId)));
} // namespace widevine

View File

@@ -45,14 +45,15 @@ class LicenseWhiteboxGetSecretStringTest : public LicenseWhiteboxTestBase {
License license;
builder.Build(*server, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
kNoProviderKeyId, license.request.data(), license.request.size()),
WB_RESULT_OK);
}
// We need two special keys for this test, one that will be used for a

View File

@@ -44,14 +44,15 @@ TEST_P(LicenseWhiteboxKeyControlBlockTest, Decrypt) {
License license;
builder.Build(*server_, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(),
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), kNoProviderKeyId, license.request.data(),
license.request.size()),
WB_RESULT_OK);
std::vector<uint8_t> plaintext(content.ciphertext.size());
size_t plaintext_size = plaintext.size();
@@ -78,14 +79,15 @@ TEST_P(LicenseWhiteboxKeyControlBlockTest, MaskedDecrypt) {
License license;
builder.Build(*server_, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(),
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), kNoProviderKeyId, license.request.data(),
license.request.size()),
WB_RESULT_OK);
std::vector<uint8_t> plaintext(content.ciphertext.size());
size_t plaintext_size = plaintext.size();

View File

@@ -70,7 +70,7 @@ class LicenseWhiteboxLicenseKeyMode
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), license.request.data(),
license.session_key.size(), kNoProviderKeyId, license.request.data(),
license.request.size());
}

View File

@@ -19,11 +19,16 @@ namespace {
using Padding = TestLicenseBuilder::Padding;
const size_t kValidProviderKeyId1 = 1;
const size_t kValidProviderKeyId2 = 2;
const size_t kInvalidProviderKeyId = 0xfff;
// There is also kNoProviderKeyId specified in test_license_builder.
} // namespace
class LicenseWhiteboxMaskedDecryptTest
: public LicenseWhiteboxTestBase,
public testing::WithParamInterface<Padding> {
public ::testing::WithParamInterface<std::tuple<Padding, size_t>> {
protected:
void SetUp() override {
LicenseWhiteboxTestBase::SetUp();
@@ -42,13 +47,19 @@ class LicenseWhiteboxMaskedDecryptTest
non_content_key_id_ = golden_data_.GetFreeId();
missing_key_id_ = golden_data_.GetFreeId();
padding_ = GetParam();
padding_ = std::get<0>(GetParam());
provider_key_id_ = std::get<1>(GetParam());
}
void LoadLicense(const TestLicenseBuilder::Settings& settings) {
// Creates and loads a license. The license is created using |settings|
// updated to include the test parameters. The license is loaded using
// |provider_key_id|.
void LoadLicense(const TestLicenseBuilder::Settings& settings,
size_t provider_key_id) {
TestLicenseBuilder builder;
builder.SetSettings(settings);
builder.GetSettings().padding = padding_;
builder.GetSettings().provider_key_id = provider_key_id_;
builder.AddContentKey(golden_data_.CBCContent().software_crypto_key);
builder.AddContentKey(golden_data_.CBCContent().software_decode_key);
@@ -64,14 +75,15 @@ class LicenseWhiteboxMaskedDecryptTest
License license;
builder.Build(*server, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
provider_key_id, license.request.data(), license.request.size()),
WB_RESULT_OK);
}
// We need two special keys for this test, one that will be used for a
@@ -88,12 +100,13 @@ class LicenseWhiteboxMaskedDecryptTest
std::vector<uint8_t> plaintext_;
Padding padding_;
size_t provider_key_id_;
};
TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCbcMode) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -132,7 +145,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCbcMode) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCbc) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
memcpy(masked_text_.data(), golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size());
@@ -173,7 +186,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCbc) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCtrMode) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CTR,
@@ -212,7 +225,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCtrMode) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCtr) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
memcpy(masked_text_.data(), golden_data_.CTRContent().ciphertext.data(),
golden_data_.CTRContent().ciphertext.size());
@@ -255,7 +268,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCtr) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCtrMode) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CTR,
@@ -295,7 +308,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCtrMode) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCbcMode) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -333,7 +346,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCbcMode) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -372,7 +385,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCtrMode) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CTR,
@@ -413,7 +426,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCtrMode) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCtrMode) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CTR,
@@ -453,7 +466,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCtrMode) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCbcMode) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -491,7 +504,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCbcMode) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kPKSC8;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -530,7 +543,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataAndPKCS8Padding) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kPKSC8;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CTR,
@@ -574,7 +587,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataAndPKCS8Padding) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -654,7 +667,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullWhitebox) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
nullptr, WB_CIPHER_MODE_CBC,
@@ -671,7 +684,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullWhitebox) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidCipherMode) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
// In order to trick the compiler into letting us pass an invalid enum value
// to WB__License_MaskedDecrypt(), we need to cast it. If we don't do this,
@@ -693,7 +706,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidCipherMode) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullKeyId) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC, nullptr,
@@ -709,7 +722,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullKeyId) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullZeroKeyIdSize) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -725,7 +738,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullZeroKeyIdSize) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullInputData) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -744,7 +757,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest,
InvalidParameterForInvalidCBCInputDataSize) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -761,7 +774,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest,
TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForZeroInputDataSize) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -777,7 +790,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForZeroInputDataSize) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullIV) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -794,7 +807,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullIV) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidIVSize) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -810,7 +823,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidIVSize) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutput) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(
WB_License_MaskedDecrypt(
@@ -827,7 +840,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutput) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutputSize) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(
WB_License_MaskedDecrypt(
@@ -847,7 +860,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutputSize) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForMissingKeyId) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(
WB_License_MaskedDecrypt(whitebox_, WB_CIPHER_MODE_CBC,
@@ -863,7 +876,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForMissingKeyId) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForNonContentKey) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC, non_content_key_id_.data(),
@@ -882,7 +895,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest,
InsufficientSecurityLevelForHardwareContentKey) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(
WB_License_MaskedDecrypt(whitebox_, WB_CIPHER_MODE_CBC,
@@ -915,7 +928,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidState) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, BufferTooSmall) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
// Our ciphertext will be large enough that we should not need to worry about
// using a constant here.
@@ -942,7 +955,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, BufferTooSmall) {
TEST_P(LicenseWhiteboxMaskedDecryptTest, SuccessForSubRangeUnmask) {
TestLicenseBuilder::Settings settings;
settings.padding = TestLicenseBuilder::Padding::kNone;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -984,7 +997,7 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForInvalidKey) {
// we just need an invalid key, so we use one way of invalidating the key.
TestLicenseBuilder::Settings settings;
settings.include_content_key_iv = false;
LoadLicense(settings);
LoadLicense(settings, provider_key_id_);
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
@@ -998,11 +1011,82 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForInvalidKey) {
WB_RESULT_KEY_UNAVAILABLE);
}
INSTANTIATE_TEST_SUITE_P(NoPadding,
LicenseWhiteboxMaskedDecryptTest,
::testing::Values(Padding::kNone));
// For this test, we create a license using the test specified Provider Key
// Id, then load the license using a different Provider Key Id.
TEST_P(LicenseWhiteboxMaskedDecryptTest, MismatchProviderKeyId) {
// These tests use 2 valid provider key IDs, so try loading the license
// with a different key. Not all possible combinations are tested.
size_t alternate_provider_key_id = kInvalidProviderKeyId;
switch (provider_key_id_) {
case kNoProviderKeyId:
alternate_provider_key_id = kValidProviderKeyId2;
break;
case kValidProviderKeyId1:
alternate_provider_key_id = kNoProviderKeyId;
break;
case kValidProviderKeyId2:
alternate_provider_key_id = kValidProviderKeyId1;
break;
case kInvalidProviderKeyId:
// This is the same as kNoProviderKeyId, so use one of the valid ids.
alternate_provider_key_id = kValidProviderKeyId1;
break;
}
INSTANTIATE_TEST_SUITE_P(PKSC8,
LicenseWhiteboxMaskedDecryptTest,
::testing::Values(Padding::kPKSC8));
TestLicenseBuilder::Settings settings;
LoadLicense(settings, alternate_provider_key_id);
// Decryption should succeed, but the plaintext should be incorrect.
ASSERT_EQ(WB_License_MaskedDecrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_decode_key.id.data(),
golden_data_.CBCContent().software_decode_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), masked_text_.data(),
&masked_text_size_),
WB_RESULT_OK);
masked_text_.resize(masked_text_size_);
// Returned data is masked, so it should be the correct size but not
// match the original text.
ASSERT_EQ(masked_text_.size(), golden_data_.CBCContent().plaintext.size());
ASSERT_NE(masked_text_, golden_data_.CBCContent().plaintext);
// Now unmask the data. It should successfully unmask, but be incorrect as
// a different provider key ID was used.
ASSERT_EQ(WB_License_GetSecretString(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_decode_key.id.data(),
golden_data_.CBCContent().software_decode_key.id.size(),
secret_string_.data(), &secret_string_size_),
WB_RESULT_OK);
secret_string_.resize(secret_string_size_);
plaintext_.resize(masked_text_size_);
WB_License_Unmask(masked_text_.data(), 0, masked_text_size_,
secret_string_.data(), secret_string_.size(),
plaintext_.data());
ASSERT_NE(plaintext_, golden_data_.CBCContent().plaintext);
}
INSTANTIATE_TEST_SUITE_P(
NoPadding,
LicenseWhiteboxMaskedDecryptTest,
::testing::Combine(::testing::Values(Padding::kNone),
::testing::Values(kNoProviderKeyId,
kValidProviderKeyId1,
kValidProviderKeyId2,
kInvalidProviderKeyId)));
INSTANTIATE_TEST_SUITE_P(
PKSC8,
LicenseWhiteboxMaskedDecryptTest,
::testing::Combine(::testing::Values(Padding::kNone),
::testing::Values(kNoProviderKeyId,
kValidProviderKeyId1,
kValidProviderKeyId2,
kInvalidProviderKeyId)));
} // namespace widevine

View File

@@ -6,6 +6,7 @@
#include "api/license_whitebox.h"
#include "api/license_whitebox_benchmark.h"
#include "api/license_whitebox_provider_keys_test_data.h"
#include "api/result.h"
#include "api/test_license_builder.h"
#include "benchmarking/measurements.h"
@@ -16,26 +17,32 @@ namespace {
// The white-box implementation is slow, so the build bots keep timing out. To
// work around this, use a fixed number of iterations.
constexpr size_t kIterations = 10;
const size_t kValidProviderKeyId = 1;
} // namespace
// This test takes 3 parameters. The first (key mode) will change how the
// This test takes 4 parameters. The first (key mode) will change how the
// license is encrypted and signed. The second (int) determines the number of
// content keys in the license. The third (security level) determines the
// security level of the content keys other than the first one (which is
// always kSoftwareSecureCrypto so that it works with both Decrypt() and
// MaskedDecrypt()).
// MaskedDecrypt()). The fourth (provider key id) specifies the provider key
// id to be used (can be kNoProviderKeyId).
class LicenseWhiteboxProcessLicenseResponseBenchmark
: public LicenseWhiteboxBenchmark,
public ::testing::WithParamInterface<
std::tuple<WB_LicenseKeyMode, int, SecurityLevel>> {
std::tuple<WB_LicenseKeyMode, int, SecurityLevel, size_t>> {
protected:
void SetUp() override {
LicenseWhiteboxBenchmark::SetUp();
key_mode_ = ::testing::get<0>(GetParam());
provider_key_id_ = ::testing::get<3>(GetParam());
init_data_ = GetLicenseWhiteboxProviderKeysInitData();
license_ = CreateLicense(key_mode_, ::testing::get<1>(GetParam()),
::testing::get<2>(GetParam()));
::testing::get<2>(GetParam()), provider_key_id_);
}
void TearDown() override { WB_License_Delete(whitebox_); }
@@ -44,6 +51,11 @@ class LicenseWhiteboxProcessLicenseResponseBenchmark
// with both single-key and dual-key.
WB_LicenseKeyMode key_mode_;
// Specifies which provider key id should be used.
size_t provider_key_id_;
std::vector<uint8_t> init_data_;
WB_License_Whitebox* whitebox_;
License license_;
};
@@ -54,7 +66,9 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, ProcessLicenseCreate) {
for (size_t i = 0; i < kIterations; i++) {
timer.Reset();
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(
WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_),
WB_RESULT_OK);
sampler.Push(timer.Get());
WB_License_Delete(whitebox_);
@@ -77,15 +91,17 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark,
// license.
timer.Reset();
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(
WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, key_mode_, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), license_.request.data(),
license_.request.size()),
license_.session_key.size(), provider_key_id_,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
WB_License_Delete(whitebox_);
@@ -110,15 +126,17 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark,
// process license so that we know the true start-up cost.
timer.Reset();
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(
WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, key_mode_, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), license_.request.data(),
license_.request.size()),
license_.session_key.size(), provider_key_id_,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
sampler.Push(timer.Get());
@@ -139,7 +157,9 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, ProcessLicenseResponse) {
// We can only call ProcessLicenseResponse() once per whitebox instance. So
// we need to create a new instance each time. Do this before we reset the
// timer so that we are not counting it in the execution time.
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(
WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_),
WB_RESULT_OK);
timer.Reset();
@@ -148,8 +168,8 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, ProcessLicenseResponse) {
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), license_.request.data(),
license_.request.size()),
license_.session_key.size(), provider_key_id_,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
sampler.Push(timer.Get());
@@ -167,41 +187,63 @@ INSTANTIATE_TEST_SUITE_P(
LicenseWhiteboxProcessLicenseResponseBenchmark,
::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_SINGLE_KEY,
1,
SecurityLevel::kSoftwareSecureCrypto)));
SecurityLevel::kSoftwareSecureCrypto,
kNoProviderKeyId)));
INSTANTIATE_TEST_SUITE_P(
FiveCryptoKeysWithSingleKeyServer,
LicenseWhiteboxProcessLicenseResponseBenchmark,
::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_SINGLE_KEY,
5,
SecurityLevel::kSoftwareSecureCrypto)));
SecurityLevel::kSoftwareSecureCrypto,
kNoProviderKeyId)));
INSTANTIATE_TEST_SUITE_P(
FiveDecodeKeysWithSingleKeyServer,
LicenseWhiteboxProcessLicenseResponseBenchmark,
::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_SINGLE_KEY,
5,
SecurityLevel::kSoftwareSecureDecode)));
SecurityLevel::kSoftwareSecureDecode,
kNoProviderKeyId)));
INSTANTIATE_TEST_SUITE_P(
SingleKeyWithDualKeyServer,
LicenseWhiteboxProcessLicenseResponseBenchmark,
::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_DUAL_KEY,
1,
SecurityLevel::kSoftwareSecureCrypto)));
SecurityLevel::kSoftwareSecureCrypto,
kNoProviderKeyId)));
INSTANTIATE_TEST_SUITE_P(
FiveCryptoKeysWithDualKeyServer,
LicenseWhiteboxProcessLicenseResponseBenchmark,
::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_DUAL_KEY,
5,
SecurityLevel::kSoftwareSecureCrypto)));
SecurityLevel::kSoftwareSecureCrypto,
kNoProviderKeyId)));
INSTANTIATE_TEST_SUITE_P(
FiveDecodeKeysWithDualKeyServer,
LicenseWhiteboxProcessLicenseResponseBenchmark,
::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_DUAL_KEY,
5,
SecurityLevel::kSoftwareSecureDecode)));
SecurityLevel::kSoftwareSecureDecode,
kNoProviderKeyId)));
INSTANTIATE_TEST_SUITE_P(
SingleKeyWithSingleKeyServerAndProviderKeyId,
LicenseWhiteboxProcessLicenseResponseBenchmark,
::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_SINGLE_KEY,
1,
SecurityLevel::kSoftwareSecureCrypto,
kValidProviderKeyId)));
INSTANTIATE_TEST_SUITE_P(
SingleKeyWithDualKeyServerAndProviderKeyId,
LicenseWhiteboxProcessLicenseResponseBenchmark,
::testing::Values(std::make_tuple(WB_LICENSE_KEY_MODE_DUAL_KEY,
1,
SecurityLevel::kSoftwareSecureCrypto,
kValidProviderKeyId)));
} // namespace widevine

View File

@@ -45,137 +45,147 @@ class LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithoutOdkAndWithoutSigningKey) {
UseLicenseWithoutSigningKey(OdkVersion::kNone);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_3AndWithoutSigningKey) {
UseLicenseWithoutSigningKey(OdkVersion::k16_3);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_5AndWithoutSigningKey) {
UseLicenseWithoutSigningKey(OdkVersion::k16_5);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithoutOdkAndWithSigningKeyNoPadding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone,
OdkVersion::kNone);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_3AndWithSigningKeyNoPadding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone,
OdkVersion::k16_3);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_5AndWithSigningKeyNoPadding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone,
OdkVersion::k16_5);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithoutOdkAndWithSigningKeyPKSC8Padding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8,
OdkVersion::kNone);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_3AndWithSigningKeyPKSC8Padding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8,
OdkVersion::k16_3);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
SuccessWithOdk16_5AndWithSigningKeyPKSC8Padding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8,
OdkVersion::k16_5);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
InvalidParameterForNullCoreMessage) {
UseLicenseWithoutSigningKey(OdkVersion::k16_5);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
/*core_message=*/nullptr, license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
/*core_message=*/nullptr, license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
kNoProviderKeyId, license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
@@ -186,14 +196,15 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseWithCoreMessageTest,
// no parameter check will be done. However, since the license was created
// with one, signature checking will fail as there is no core message
// to be included when checking the signature.
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), /*core_message_size=*/0,
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
/*core_message_size=*/0, license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE);
}
} // namespace widevine

View File

@@ -50,42 +50,45 @@ class LicenseWhiteboxProcessLicenseResponseTest
TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithoutSigningKey) {
UseLicenseWithoutSigningKey();
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseTest,
SuccessWithSigningKeyNoPadding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseTest,
SuccessWithSigningKeyPKSC8Padding) {
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kPKSC8);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
// If there were multiple signing keys (this can only happen if a license server
@@ -101,27 +104,69 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseTest,
builder.AddContentKey(golden_data_.CBCContent().software_crypto_key);
builder.Build(*server_, &license_);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseTest, InvalidParameterWithNoKeys) {
UseLicenseWithNoKeys();
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithProviderKey) {
const size_t kProviderKeyId = 1;
TestLicenseBuilder builder;
builder.GetSettings().padding = TestLicenseBuilder::Padding::kPKSC8;
builder.GetSettings().provider_key_id = kProviderKeyId;
builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey());
builder.AddContentKey(golden_data_.CBCContent().software_crypto_key);
builder.Build(*server_, &license_);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kProviderKeyId, license_.request.data(),
license_.request.size()),
WB_RESULT_OK);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseTest, InvalidProviderKey) {
// Other tests pass in kNoProviderKeyId (0). However, invalid keys should also
// be treated as if no key is provided. It is expected to only have a small
// number of provider keys (starting at index 1), so pick a large number.
const size_t kInvalidProviderKey = 0xfff;
UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kInvalidProviderKey,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
class LicenseWhiteboxProcessLicenseResponseErrorTest
@@ -145,7 +190,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), license_.request.data(),
license_.session_key.size(), kNoProviderKeyId, license_.request.data(),
license_.request.size());
// Depending on where/how the message is verified, an implementation can
@@ -159,14 +204,15 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidSignatureForModifedSignature) {
Modify(&license_.signature);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE);
}
// The license request is used to derive the signing key. If the request was
@@ -175,14 +221,15 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidSignatureForModifedLicenseRequest) {
Modify(&license_.request);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE);
}
// If the session key is modified, unwrapping it will fail. Therefore, we will
@@ -193,26 +240,28 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidSignatureForModifedSessionKey) {
Modify(&license_.session_key);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_SIGNATURE);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForNullWhitebox) {
ASSERT_EQ(WB_License_ProcessLicenseResponse(
nullptr, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
nullptr, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
@@ -223,7 +272,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
license_.core_message.size(), nullptr, license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
kNoProviderKeyId, license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
}
@@ -235,7 +284,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
license_.core_message.size(), license_.message.data(), 0,
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
kNoProviderKeyId, license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
}
@@ -247,7 +296,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
license_.core_message.size(), license_.message.data(),
license_.message.size(), nullptr, license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
kNoProviderKeyId, license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
}
@@ -259,7 +308,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(), 5,
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
kNoProviderKeyId, license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
}
@@ -271,7 +320,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), nullptr, license_.session_key.size(),
license_.request.data(), license_.request.size()),
kNoProviderKeyId, license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
}
@@ -283,32 +332,32 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(), 5,
license_.request.data(), license_.request.size()),
kNoProviderKeyId, license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForNullLicenseRequest) {
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), nullptr, license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
kNoProviderKeyId, nullptr, license_.request.size()),
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseErrorTest,
InvalidParameterForZeroLienseRequestSize) {
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), license_.request.data(), 0),
WB_RESULT_INVALID_PARAMETER);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
kNoProviderKeyId, license_.request.data(), 0),
WB_RESULT_INVALID_PARAMETER);
}
class LicenseWhiteboxMultiLicenseTest
@@ -328,25 +377,27 @@ class LicenseWhiteboxMultiLicenseTest
TEST_F(LicenseWhiteboxMultiLicenseTest, InvalidState) {
// Load the first license. This one is expected to succeed as the whitebox has
// not loaded a license yet.
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
// Attempt to load the same license again. This should fail as it already has
// a license (even though it is the same license).
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_STATE);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_INVALID_STATE);
}
// Even though a whitebox can only load a license once, if it fails to load a
@@ -356,25 +407,26 @@ TEST_F(LicenseWhiteboxMultiLicenseTest, SuccessAfterFailure) {
// in key derivation which is a later step of license parsing.
std::vector<uint8_t> bad_request = license_.request;
Modify(&bad_request);
ASSERT_NE(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), bad_request.data(), bad_request.size()),
WB_RESULT_OK);
// Attempt to load the license again, but use the correct (unmodified)
// request.
ASSERT_EQ(WB_License_ProcessLicenseResponse(
ASSERT_NE(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license_.core_message.data(), license_.core_message.size(),
license_.message.data(), license_.message.size(),
license_.signature.data(), license_.signature.size(),
license_.session_key.data(), license_.session_key.size(),
license_.request.data(), license_.request.size()),
kNoProviderKeyId, bad_request.data(), bad_request.size()),
WB_RESULT_OK);
// Attempt to load the license again, but use the correct (unmodified)
// request.
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(),
license_.core_message.size(), license_.message.data(),
license_.message.size(), license_.signature.data(),
license_.signature.size(), license_.session_key.data(),
license_.session_key.size(), kNoProviderKeyId,
license_.request.data(), license_.request.size()),
WB_RESULT_OK);
}
} // namespace widevine

View File

@@ -0,0 +1,16 @@
// Copyright 2021 Google LLC. All Rights Reserved.
#ifndef WHITEBOX_API_LICENSE_WHITEBOX_PROVIDER_KEYS_TEST_DATA_H_
#define WHITEBOX_API_LICENSE_WHITEBOX_PROVIDER_KEYS_TEST_DATA_H_
#include <stdint.h>
#include <vector>
namespace widevine {
// Returns init data that the license white-box will accept.
std::vector<uint8_t> GetLicenseWhiteboxProviderKeysInitData();
} // namespace widevine
#endif // WHITEBOX_API_LICENSE_WHITEBOX_PROVIDER_KEYS_TEST_DATA_H_

View File

@@ -76,7 +76,7 @@ class LicenseWhiteboxQueryContentKeyStatus
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), license.request.data(),
license.session_key.size(), kNoProviderKeyId, license.request.data(),
license.request.size());
}

View File

@@ -73,7 +73,7 @@ class LicenseWhiteboxQuerySigningKeyStatus
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), license.request.data(),
license.session_key.size(), kNoProviderKeyId, license.request.data(),
license.request.size());
}

View File

@@ -62,14 +62,15 @@ TEST_P(LicenseWhiteboxSecurityLevelTest, CanLoadAndUseKey) {
License license;
builder.Build(*server, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(),
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), kNoProviderKeyId, license.request.data(),
license.request.size()),
WB_RESULT_OK);
plaintext_size_ = golden_data_.CBCContent().ciphertext.size();
plaintext_.resize(plaintext_size_);

View File

@@ -8,6 +8,7 @@
#include "api/license_whitebox.h"
#include "api/license_whitebox_benchmark.h"
#include "api/license_whitebox_provider_keys_test_data.h"
#include "api/result.h"
#include "api/test_license_builder.h"
#include "benchmarking/data_source.h"
@@ -35,17 +36,19 @@ class LicenseWhiteboxSignBenchmark
key_mode_ = GetParam();
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
auto init_data = GetLicenseWhiteboxProviderKeysInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
const auto license =
CreateLicense(key_mode_, 1, SecurityLevel::kSoftwareSecureCrypto);
const auto license = CreateLicense(
key_mode_, 1, SecurityLevel::kSoftwareSecureCrypto, kNoProviderKeyId);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, key_mode_, license.core_message.data(),
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), license.request.data(),
license.request.size()),
license.session_key.size(), kNoProviderKeyId,
license.request.data(), license.request.size()),
WB_RESULT_OK);
}

View File

@@ -44,14 +44,15 @@ class LicenseWhiteboxSignRenewalPstTest
License license;
builder.Build(*server, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
kNoProviderKeyId, license.request.data(), license.request.size()),
WB_RESULT_OK);
}
// Get the expected signature for |message|. By returning the message, this
@@ -226,14 +227,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, KeyUnavailableForNoSigningKey) {
License license;
builder.Build(*server, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(),
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), kNoProviderKeyId, license.request.data(),
license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(),

View File

@@ -2,12 +2,15 @@
#include "api/license_whitebox_test_base.h"
#include "api/license_whitebox_provider_keys_test_data.h"
#include "api/test_license_whitebox_keys.h"
namespace widevine {
void LicenseWhiteboxTestBase::SetUp() {
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
auto init_data = GetLicenseWhiteboxProviderKeysInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
}
void LicenseWhiteboxTestBase::TearDown() {

View File

@@ -5,6 +5,7 @@
#include <vector>
#include "api/license_whitebox.h"
#include "api/license_whitebox_provider_keys_test_data.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace widevine {
@@ -342,6 +343,9 @@ const uint8_t kIv[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const size_t kIvSize = sizeof(kIv);
const size_t kNoProviderKeyId = 0;
} // namespace
class LicenseWhiteboxDecryptUatTest : public ::testing::Test {
@@ -352,14 +356,16 @@ class LicenseWhiteboxDecryptUatTest : public ::testing::Test {
};
TEST_F(LicenseWhiteboxDecryptUatTest, CryptoKeyWithCbcDataInCbcMode) {
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
auto init_data = GetLicenseWhiteboxProviderKeysInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, kCoreMessage,
kCoreMessageSize, kMessage, kMessageSize, kSignature, kSignatureSize,
kSessionKey, kSessionKeySize, kLicenseRequest, kLicenseRequestSize),
WB_RESULT_OK);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, kCoreMessage,
kCoreMessageSize, kMessage, kMessageSize, kSignature,
kSignatureSize, kSessionKey, kSessionKeySize, kNoProviderKeyId,
kLicenseRequest, kLicenseRequestSize),
WB_RESULT_OK);
size_t plaintext_size = kCiphertextSize;
std::vector<uint8_t> plaintext(plaintext_size);

View File

@@ -8,6 +8,7 @@
#include "api/license_whitebox.h"
#include "api/license_whitebox_benchmark.h"
#include "api/license_whitebox_provider_keys_test_data.h"
#include "api/result.h"
#include "api/test_license_builder.h"
#include "benchmarking/data_source.h"
@@ -27,18 +28,22 @@ class LicenseWhiteboxVerifyBenchmark : public LicenseWhiteboxBenchmark {
message_ = Data().Get(kMessageSize);
signature_ = SignAsServer(message_);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
const auto license = CreateLicense(WB_LICENSE_KEY_MODE_DUAL_KEY, 1,
SecurityLevel::kSoftwareSecureCrypto);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
auto init_data = GetLicenseWhiteboxProviderKeysInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
const auto license =
CreateLicense(WB_LICENSE_KEY_MODE_DUAL_KEY, 1,
SecurityLevel::kSoftwareSecureCrypto, kNoProviderKeyId);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
kNoProviderKeyId, license.request.data(), license.request.size()),
WB_RESULT_OK);
}
void TearDown() override { WB_License_Delete(whitebox_); }

View File

@@ -39,14 +39,15 @@ class LicenseWhiteboxVerifyRenewalResponseTest
License license;
builder.Build(*server, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
kNoProviderKeyId, license.request.data(), license.request.size()),
WB_RESULT_OK);
}
std::vector<uint8_t> Sign(const std::vector<uint8_t>& message) {
@@ -236,14 +237,15 @@ TEST_F(LicenseWhiteboxVerifyRenewalResponseTest,
License license;
builder.Build(*server, &license);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY,
license.core_message.data(), license.core_message.size(),
license.message.data(), license.message.size(),
license.signature.data(), license.signature.size(),
license.session_key.data(), license.session_key.size(),
license.request.data(), license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(
WB_License_ProcessLicenseResponse(
whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(),
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), kNoProviderKeyId, license.request.data(),
license.request.size()),
WB_RESULT_OK);
ASSERT_EQ(WB_License_VerifyRenewalResponse(whitebox_,
garbage_renewal_message_.data(),

View File

@@ -151,7 +151,7 @@ class RemoteAttestationAndVerificationTest
license.core_message.size(), license.message.data(),
license.message.size(), license.signature.data(),
license.signature.size(), license.session_key.data(),
license.session_key.size(), license.request.data(),
license.session_key.size(), kNoProviderKeyId, license.request.data(),
license.request.size());
}

View File

@@ -6,6 +6,7 @@
#include <ctime>
#include <map>
#include "api/test_license_provider_keys.h"
#include "base/check.h"
#include "base/check_op.h"
#include "cdm/keys/certs.h"
@@ -236,6 +237,44 @@ std::vector<uint8_t> GetPadding(TestLicenseBuilder::Padding padding) {
return {};
}
// Wrap the content key |unwrapped_content_key| using |provider_key_id| and
// |key_encryption_key|, as appropriate.
std::string WrapContentKey(const std::vector<uint8_t>& unwrapped_content_key,
size_t provider_key_id,
const std::string& key_encryption_key,
const std::string& key_encryption_key_iv) {
auto provider_keys = GetProviderKeys();
const bool provider_key_id_valid =
(provider_key_id >= 1 && provider_key_id <= provider_keys.size());
// If |provider_key_id| is used, encrypt the unwrapped key using the
// appropriate provider key. Otherwise, use |unwrapped_content_key| for the
// next step.
std::string provider_encrypted_key;
if (provider_key_id_valid) {
const auto& provider_key = provider_keys[provider_key_id - 1].key;
const std::string no_iv(16, 0);
provider_encrypted_key =
Encrypt(provider_key, no_iv, unwrapped_content_key);
} else {
provider_encrypted_key.assign(unwrapped_content_key.begin(),
unwrapped_content_key.end());
}
// Now apply the Key Encryption Key.
auto encrypted_key = Encrypt(key_encryption_key, key_encryption_key_iv,
provider_encrypted_key);
// If |provider_key_id| is used, then mask the resulting key.
if (provider_key_id_valid) {
const auto& mask = provider_keys[provider_key_id - 1].mask;
for (size_t i = 0; i < encrypted_key.size(); ++i)
encrypted_key[i] ^= mask[i];
}
return encrypted_key;
}
void AddContentKeyToContainer(const ContentKeyData& key_data,
const TestLicenseBuilder::Settings& settings,
const std::string& container_key,
@@ -271,9 +310,9 @@ void AddContentKeyToContainer(const ContentKeyData& key_data,
auto padding = GetPadding(settings.padding);
key.insert(key.end(), padding.begin(), padding.end());
auto encrypted_key = Encrypt(container_key, key_iv, key);
container->set_key(encrypted_key);
auto wrapped_content_key =
WrapContentKey(key, settings.provider_key_id, container_key, key_iv);
container->set_key(wrapped_content_key);
if (settings.content_key_key_size_override) {
container->mutable_key()->resize(settings.content_key_key_size);
@@ -456,6 +495,10 @@ void TestLicenseBuilder::Build(const TestServer& server,
break;
}
if (settings_.provider_key_id != kNoProviderKeyId) {
response.set_provider_key_id(settings_.provider_key_id);
}
for (const auto& key : signing_keys_) {
AddSigningKeyToContainer(key, settings_, container_key_,
response.add_key());

View File

@@ -13,6 +13,8 @@
namespace widevine {
constexpr size_t kNoProviderKeyId = 0;
struct License {
std::vector<uint8_t> request;
@@ -101,6 +103,11 @@ class TestLicenseBuilder {
bool signing_key_key_size_override = false;
size_t signing_key_key_size = 64;
size_t signing_key_iv_size = 16;
// If required, use a ProviderKey when encrypting the content keys.
// By default, no Provider key is used. Note that the list of available
// provider keys is fixed.
size_t provider_key_id = kNoProviderKeyId;
};
// Returns a default signing key that can be used with AddSigningKey().

View File

@@ -0,0 +1,23 @@
// Copyright 2021 Google LLC. All Rights Reserved.
#include "api/test_license_provider_keys.h"
namespace widevine {
std::vector<ProviderKey> GetProviderKeys() {
// Note that both mask and key must be 16 bytes each.
// This data must match what is provided to the whitebox in
// GetLicenseWhiteboxProviderKeysInitData().
return {
{// provider key 1
{0xd0, 0xc6, 0x91, 0xd7, 0x1d, 0xfd, 0xfb, 0x12, 0xa3, 0x41, 0x65, 0x68,
0x34, 0x72, 0xe5, 0xf6},
"ProviderKey12345"},
{// provider key 2
{0x67, 0x51, 0xa8, 0x7f, 0xe9, 0x9e, 0x28, 0xe4, 0x46, 0x7b, 0x8b, 0x7c,
0x7e, 0x69, 0xc6, 0x5e},
"ProviderKey23456"},
};
}
} // namespace widevine

View File

@@ -0,0 +1,21 @@
// Copyright 2021 Google LLC. All Rights Reserved.
#ifndef WHITEBOX_API_TEST_LICENSE_PROVIDER_KEYS_H_
#define WHITEBOX_API_TEST_LICENSE_PROVIDER_KEYS_H_
#include <cstdint>
#include <string>
#include <vector>
namespace widevine {
struct ProviderKey {
std::vector<uint8_t> mask;
std::string key;
};
std::vector<ProviderKey> GetProviderKeys();
} // namespace widevine
#endif // WHITEBOX_API_TEST_LICENSE_PROVIDER_KEYS_H_

View File

@@ -4,6 +4,8 @@
#include "api/test_license_whitebox_keys.h"
#include <cstddef>
namespace widevine {
namespace {

View File

@@ -2,6 +2,8 @@
#include "api/test_license_whitebox_keys.h"
#include <cstddef>
namespace widevine {
namespace {

View File

@@ -285,6 +285,9 @@ message License {
[default = PLATFORM_NO_VERIFICATION];
// IDs of the groups for which keys are delivered in this license, if any.
repeated bytes group_ids = 11;
// Optional: The provider key id indicates which provider key was used
// during provider key encryption.
optional uint32 provider_key_id = 13;
}
enum ProtocolVersion {

View File

@@ -23,7 +23,8 @@ bool AesCbcDecryptor::SetKey(const uint8_t* key, size_t key_size) {
LOG(WARNING) << "Incorrect key size " << key_size;
return false;
}
if (AES_set_decrypt_key(key, key_size * 8, &aes_key_) != 0) {
if (AES_set_decrypt_key(key, static_cast<int>(key_size * 8), &aes_key_) !=
0) {
LOG(WARNING) << "Invalid AES key.";
return false;
}

View File

@@ -23,7 +23,8 @@ bool AesCbcEncryptor::SetKey(const uint8_t* key, size_t key_size) {
LOG(WARNING) << "Incorrect key size " << key_size;
return false;
}
if (AES_set_encrypt_key(key, key_size * 8, &aes_key_) != 0) {
if (AES_set_encrypt_key(key, static_cast<int>(key_size * 8), &aes_key_) !=
0) {
LOG(WARNING) << "Invalid AES key.";
return false;
}

View File

@@ -35,7 +35,8 @@ bool AesCtrEncryptor::SetKey(const uint8_t* key, size_t key_size) {
LOG(WARNING) << "Incorrect key size " << key_size;
return false;
}
if (AES_set_encrypt_key(key, key_size * 8, &aes_key_) != 0) {
if (AES_set_encrypt_key(key, static_cast<int>(key_size * 8), &aes_key_) !=
0) {
LOG(WARNING) << "Invalid AES key.";
return false;
}

View File

@@ -57,7 +57,7 @@ std::string CreateSignatureHmacSha256(absl::string_view key,
absl::string_view message) {
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init(&ctx, key.data(), key.size(), EVP_sha256());
HMAC_Init(&ctx, key.data(), static_cast<int>(key.size()), EVP_sha256());
HMAC_Update(&ctx, reinterpret_cast<const unsigned char*>(message.data()),
message.size());
unsigned char digest[SHA256_DIGEST_LENGTH];
@@ -80,7 +80,7 @@ std::string CreateSignatureHmacSha1(absl::string_view key,
absl::string_view message) {
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init(&ctx, key.data(), key.size(), EVP_sha1());
HMAC_Init(&ctx, key.data(), static_cast<int>(key.size()), EVP_sha1());
HMAC_Update(&ctx, reinterpret_cast<const unsigned char*>(message.data()),
message.size());
unsigned char digest[SHA_DIGEST_LENGTH];

View File

@@ -39,7 +39,7 @@ bool SerializeKey(const Key* key,
}
bool success = false;
if (serialization_func(bio, const_cast<Key*>(key)) != 0) {
int serialized_size = BIO_pending(bio);
int serialized_size = static_cast<int>(BIO_pending(bio));
serialized_key->assign(serialized_size, 0);
if (BIO_read(bio, &(*serialized_key)[0], serialized_size) ==
serialized_size) {
@@ -67,7 +67,7 @@ bool DeserializeKey(const std::string& serialized_key,
return false;
}
BIO* bio = BIO_new_mem_buf(const_cast<char*>(serialized_key.data()),
serialized_key.size());
static_cast<int>(serialized_key.size()));
if (bio == nullptr) {
LOG(ERROR) << "BIO_new_mem_buf returned nullptr";
return false;

View File

@@ -101,7 +101,7 @@ bool SerializePrivateKeyInfo(const RSA* private_key,
goto cleanup;
}
{
int serialized_size = BIO_pending(bio);
int serialized_size = static_cast<int>(BIO_pending(bio));
serialized_private_key->assign(serialized_size, 0);
if (BIO_read(bio, &(*serialized_private_key)[0], serialized_size) !=
serialized_size) {
@@ -137,7 +137,7 @@ bool DeserializePrivateKeyInfo(const std::string& serialized_private_key,
// mechanism via d2i_PKCS8PrivateKey_bio is broken in the current openssl
// version (1.0.0c). Please refer to b/8560683.
BIO* bio = BIO_new_mem_buf(const_cast<char*>(serialized_private_key.data()),
serialized_private_key.size());
static_cast<int>(serialized_private_key.size()));
if (bio == nullptr) {
LOG(ERROR) << "BIO_new_mem_buf returned nullptr";
return false;
@@ -226,14 +226,14 @@ bool SerializeEncryptedPrivateKeyInfo(const RSA* private_key,
LOG(ERROR) << "BIO_new returned nullptr.";
goto cleanup;
}
if (i2d_PKCS8PrivateKey_bio(bio, evp, EVP_aes_256_cbc(),
const_cast<char*>(passphrase.data()),
passphrase.size(), nullptr, nullptr) == 0) {
if (i2d_PKCS8PrivateKey_bio(
bio, evp, EVP_aes_256_cbc(), const_cast<char*>(passphrase.data()),
static_cast<int>(passphrase.size()), nullptr, nullptr) == 0) {
LOG(ERROR) << "i2d_PKCS8PrivateKey_bio failed.";
goto cleanup;
}
{
int serialized_size = BIO_pending(bio);
int serialized_size = static_cast<int>(BIO_pending(bio));
serialized_private_key->assign(serialized_size, 0);
if (BIO_read(bio, &(*serialized_private_key)[0], serialized_size) !=
serialized_size) {
@@ -259,7 +259,7 @@ int get_password(char* buf, int size, int rwflag, void* u) {
const std::string* pass(static_cast<const std::string*>(u));
if (!pass->empty() && size >= static_cast<int>(pass->size())) {
memcpy(buf, pass->data(), pass->size());
return pass->size();
return static_cast<int>(pass->size());
}
return 0;
}
@@ -282,7 +282,7 @@ bool DeserializeEncryptedPrivateKeyInfo(
return false;
}
BIO* bio = BIO_new_mem_buf(const_cast<char*>(serialized_private_key.data()),
serialized_private_key.size());
static_cast<int>(serialized_private_key.size()));
if (bio == nullptr) {
LOG(ERROR) << "BIO_new_mem_buf returned nullptr";
return false;

View File

@@ -36,7 +36,7 @@ cc_library(
"oemcrypto/odk/include/odk_structs.h",
"oemcrypto/odk/include/odk_target.h",
],
copts = ["-std=c99"],
copts = ["-std=c99 -Wno-array-parameter"],
includes = [
"oemcrypto/odk/include",
],

View File

@@ -144,6 +144,18 @@ cc_library(
],
)
# The "license_whitebox_provider_keys_test_data" target provides the data for
# the license whitebox init data (Provider Keys) defined in
# "api/license_whitebox_provider_keys_test_data.h".
cc_library(
name = "license_whitebox_provider_keys_test_data",
srcs = ["license_whitebox_provider_keys_test_data.cc"],
visibility = ["//visibility:public"],
deps = [
"//api:license_whitebox_provider_keys_test_data",
],
)
# ==============================================================================
# AEAD White-box Targets
# ==============================================================================

View File

@@ -46,7 +46,7 @@ std::vector<uint8_t> DeriveKey(const WB_Aead_Whitebox* whitebox,
// While we get the key size in bytes, DeriveKey() needs the key size in bits.
const auto derived_key = widevine::crypto_util::DeriveKey(
init_data_view, kLabel, context_view,
EVP_AEAD_key_length(whitebox->algorithm) * 8);
static_cast<uint32_t>(EVP_AEAD_key_length(whitebox->algorithm) * 8));
return std::vector<uint8_t>(derived_key.begin(), derived_key.end());
}

View File

@@ -5,6 +5,7 @@
#include "base/check.h"
#include "base/check_op.h"
#include "crypto_utils/aes_cbc_decryptor.h"
#include "crypto_utils/crypto_util.h"
namespace widevine {
@@ -29,6 +30,51 @@ bool LicenseParser::Decrypt(const std::string& key,
reinterpret_cast<uint8_t*>(&decrypted->front()));
}
bool LicenseParser::UnwrapContentKey(
const std::string& wrapped_content_key,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id,
const std::string& key_decryption_key,
const std::string& key_decryption_key_iv,
std::string* unwrapped_content_key) {
const bool provider_key_id_valid =
(provider_key_id >= 1 && provider_key_id <= provider_keys.size());
// If |provider_key_id| is used and valid, then start by unmasking it.
std::string key(wrapped_content_key);
if (provider_key_id_valid) {
const auto& mask = provider_keys[provider_key_id - 1].mask;
for (size_t i = 0; i < key.size(); ++i)
key[i] ^= mask[i];
}
// Now decrypt the key using the Key Encryption Key.
std::string unwrapped_key(key);
if (!Decrypt(key_decryption_key, key_decryption_key_iv, key,
&unwrapped_key)) {
DVLOG(1) << "Failed to decrypt content key using KEK.";
return false;
}
// If |provider_key_id| not used, simply return the key decrypted so far.
if (!provider_key_id_valid) {
unwrapped_content_key->swap(unwrapped_key);
return true;
}
// |provider_key_id| is used, so decrypt the unwrapped key using the
// appropriate provider key.
std::string final_key(unwrapped_key);
const auto& provider_key = provider_keys[provider_key_id - 1].key;
const std::string no_iv(16, 0);
if (!Decrypt(provider_key, no_iv, unwrapped_key, &final_key)) {
DVLOG(1) << "Failed to decrypt content key using Provider Key.";
return false;
}
unwrapped_content_key->swap(final_key);
return true;
}
ContentKey LicenseParser::CreateContentKey(
video_widevine::License_KeyContainer_SecurityLevel level,
bool is_hw_verified,

View File

@@ -5,6 +5,7 @@
#include <map>
#include <string>
#include <vector>
#include "license_protocol.pb.h"
#include "reference/impl/content_key.h"
#include "reference/impl/odk.h"
@@ -14,6 +15,11 @@ namespace widevine {
class LicenseParser {
public:
struct ProviderKey {
std::vector<uint8_t> mask;
std::string key;
};
LicenseParser() = default;
virtual ~LicenseParser() = default;
@@ -21,9 +27,14 @@ class LicenseParser {
LicenseParser(const LicenseParser&) = delete;
LicenseParser& operator=(const LicenseParser&) = delete;
// If |provider_key_id| is valid, then use the appropriate provider key
// when extracting the content keys. If invalid, then assume no provider
// key was used.
virtual WB_Result Parse(const std::string& decryption_key,
const ODKContext& odk_context,
const std::string& message) = 0;
const std::string& message,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id) = 0;
// If there is no renewal key, then `nullptr` should be returned.
virtual const widevine::RenewalKey* GetRenewalKey() const = 0;
@@ -36,6 +47,16 @@ class LicenseParser {
const std::string& encrypted,
std::string* decrypted);
// Unwrap key |wrapped_content_key| using |provider_key_id| and
// |key_decryption_key|, as necessary. Returns true and
// |unwrapped_content_key| is updated on success, false otherwise.
static bool UnwrapContentKey(const std::string& wrapped_content_key,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id,
const std::string& key_decryption_key,
const std::string& key_decryption_key_iv,
std::string* unwrapped_content_key);
// Creates and returns a ContentKey based on the values provided.
// |level| determines whether decrypt or masked_decrypt is allowed.
// |is_hw_verified|, if set, overrides |level| so that both decrypt and

View File

@@ -108,6 +108,8 @@ struct WB_License_Whitebox {
std::unique_ptr<widevine::RenewalKey> renewal_key;
std::map<std::string, widevine::ContentKey> content_keys;
std::vector<widevine::LicenseParser::ProviderKey> provider_keys;
};
namespace {
@@ -226,14 +228,43 @@ std::unique_ptr<RsaPrivateKey> LoadPrivateKey(
return std::unique_ptr<RsaPrivateKey>(RsaPrivateKey::Create(key_string));
}
std::vector<widevine::LicenseParser::ProviderKey> CreateProviderKeys(
const uint8_t* whitebox_init_data,
size_t whitebox_init_data_size) {
std::vector<widevine::LicenseParser::ProviderKey> result;
for (size_t i = 0; i < whitebox_init_data_size / 32; ++i) {
widevine::LicenseParser::ProviderKey provider_key;
provider_key.mask.assign(whitebox_init_data, whitebox_init_data + 16);
provider_key.key.assign(whitebox_init_data + 16, whitebox_init_data + 32);
result.emplace_back(provider_key);
whitebox_init_data += 32;
}
return result;
}
} // namespace
WB_Result WB_License_Create(WB_License_Whitebox** whitebox) {
WB_Result WB_License_Create(const uint8_t* whitebox_init_data,
size_t whitebox_init_data_size,
WB_License_Whitebox** whitebox) {
if (whitebox == nullptr) {
DVLOG(1) << "Invalid parameter: null pointer.";
return WB_RESULT_INVALID_PARAMETER;
}
// whitebox_init_data is optional.
if (whitebox_init_data_size != 0 && whitebox_init_data == nullptr) {
DVLOG(1) << "Invalid parameter: Missing whitebox_init_data.";
return WB_RESULT_INVALID_PARAMETER;
}
// However, if specified, it must be a multiple of 32 bytes (as each Provider
// Key is a 16-byte mask followed by a 16-byte key).
if (whitebox_init_data_size % 32 != 0) {
DVLOG(1) << "Invalid parameter: whitebox_init_data_size must be a multiple "
"of 32.";
return WB_RESULT_INVALID_PARAMETER;
}
auto signing_key = LoadPrivateKey(widevine::GetSigningPrivateKey());
CHECK(signing_key) << "Failed to load (internal) signing private key.";
@@ -245,6 +276,8 @@ WB_Result WB_License_Create(WB_License_Whitebox** whitebox) {
*whitebox = new WB_License_Whitebox();
(*whitebox)->signing_key.swap(signing_key);
(*whitebox)->encryption_key.swap(encryption_key);
(*whitebox)->provider_keys =
CreateProviderKeys(whitebox_init_data, whitebox_init_data_size);
return WB_RESULT_OK;
}
@@ -303,6 +336,7 @@ WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox,
size_t signature_size,
const uint8_t* session_key,
size_t session_key_size,
size_t provider_key_id,
const uint8_t* license_request,
size_t license_request_size) {
const size_t kSigningKeySizeBytes =
@@ -440,7 +474,8 @@ WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox,
parser.reset(new widevine::ProtobufLicenseParser);
}
WB_Result result = parser->Parse(decryption_key, odk_context, message_str);
WB_Result result = parser->Parse(decryption_key, odk_context, message_str,
whitebox->provider_keys, provider_key_id);
if (result != WB_RESULT_OK) {
return result;

View File

@@ -0,0 +1,23 @@
// Copyright 2021 Google LLC. All Rights Reserved.
#include "api/license_whitebox_provider_keys_test_data.h"
namespace widevine {
std::vector<uint8_t> GetLicenseWhiteboxProviderKeysInitData() {
// This data must match what is used by the test license server, provided by
// GetProviderKeys() in api/test_license_provider_keys.cc. Format of the
// data below is dependent on the whitebox implementation.
return {
0xd0, 0xc6, 0x91, 0xd7, 0x1d, 0xfd, 0xfb, 0x12, // provider key 1 mask
0xa3, 0x41, 0x65, 0x68, 0x34, 0x72, 0xe5, 0xf6, //
0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, // provider key 1 key
0x4b, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34, 0x35, //
0x67, 0x51, 0xa8, 0x7f, 0xe9, 0x9e, 0x28, 0xe4, // provider key 2 mask
0x46, 0x7b, 0x8b, 0x7c, 0x7e, 0x69, 0xc6, 0x5e, //
0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, // provider key 2 key
0x4b, 0x65, 0x79, 0x32, 0x33, 0x34, 0x35, 0x36, //
};
}
} // namespace widevine

View File

@@ -66,7 +66,9 @@ std::string ExtractItem(const OEMCrypto_Substring& item,
WB_Result OdkLicenseParser::Parse(const std::string& decryption_key,
const ODKContext& odk_context,
const std::string& message) {
const std::string& message,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id) {
// Extract the signing keys.
const std::string signing_key_encrypted =
ExtractItem(odk_context.license.enc_mac_keys, message);
@@ -93,7 +95,8 @@ WB_Result OdkLicenseParser::Parse(const std::string& decryption_key,
// Add the key right away. The key will be invalid, so if we fail to
// parse the key, we'll already have an entry for the invalid key.
content_keys_[key_id] = ParseContentKey(decryption_key, message, key);
content_keys_[key_id] = ParseContentKey(decryption_key, message, key,
provider_keys, provider_key_id);
}
return WB_RESULT_OK;
@@ -150,7 +153,9 @@ RenewalKey OdkLicenseParser::ParseSigningKeys(const std::string& decryption_key,
ContentKey OdkLicenseParser::ParseContentKey(
const std::string& decryption_key,
const std::string& message,
const OEMCrypto_KeyObject& key) const {
const OEMCrypto_KeyObject& key,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id) const {
// This should have been verified before calling the parser.
CHECK_EQ(decryption_key.size(), 16u) << "Incorrect decryption key size.";
@@ -161,7 +166,7 @@ ContentKey OdkLicenseParser::ParseContentKey(
return ContentKey();
}
const std::string wrapped_key = ExtractItem(key.key_data, message);
std::string wrapped_key = ExtractItem(key.key_data, message);
// Unlike with protobufs, we don't need to handle padding here. The ODK will
// not include the padding as part of the key's size.
@@ -170,8 +175,9 @@ ContentKey OdkLicenseParser::ParseContentKey(
return ContentKey();
}
std::string unwrapped_key(wrapped_key);
if (!Decrypt(decryption_key, iv, wrapped_key, &unwrapped_key)) {
std::string unwrapped_key;
if (!UnwrapContentKey(wrapped_key, provider_keys, provider_key_id,
decryption_key, iv, &unwrapped_key)) {
VLOG(3) << "Failed to decrypt content key.";
return ContentKey();
}

View File

@@ -3,6 +3,8 @@
#ifndef WHITEBOX_REFERENCE_IMPL_ODK_LICENSE_PARSER_H_
#define WHITEBOX_REFERENCE_IMPL_ODK_LICENSE_PARSER_H_
#include <vector>
#include "reference/impl/content_key.h"
#include "reference/impl/license_parser.h"
@@ -12,7 +14,9 @@ class OdkLicenseParser : public LicenseParser {
public:
WB_Result Parse(const std::string& decryption_key,
const ODKContext& odk_context,
const std::string& message) override;
const std::string& message,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id) override;
const widevine::RenewalKey* GetRenewalKey() const override;
@@ -25,7 +29,9 @@ class OdkLicenseParser : public LicenseParser {
ContentKey ParseContentKey(const std::string& decryption_key,
const std::string& message,
const OEMCrypto_KeyObject& key) const;
const OEMCrypto_KeyObject& key,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id) const;
std::vector<widevine::RenewalKey> renewal_keys_;
std::map<std::string, ContentKey> content_keys_;

View File

@@ -64,11 +64,15 @@ bool IsPlatformHardwareVerified(const video_widevine::License& license) {
return table[vmp][ra] == 1;
}
} // namespace
WB_Result ProtobufLicenseParser::Parse(const std::string& decryption_key,
const ODKContext& odk_context,
const std::string& message) {
WB_Result ProtobufLicenseParser::Parse(
const std::string& decryption_key,
const ODKContext& odk_context,
const std::string& message,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id) {
video_widevine::License license;
if (!license.ParseFromString(message)) {
VLOG(3) << "Invalid parameter: Invalid license.";
@@ -101,8 +105,8 @@ WB_Result ProtobufLicenseParser::Parse(const std::string& decryption_key,
if (key.id().empty()) {
VLOG(3) << "Skipping content key : no key id.";
} else {
content_keys_[key.id()] =
ParseContentKey(decryption_key, key, is_verified);
content_keys_[key.id()] = ParseContentKey(
decryption_key, key, is_verified, provider_keys, provider_key_id);
}
break;
default:
@@ -172,7 +176,9 @@ RenewalKey ProtobufLicenseParser::ParseSigningKey(
ContentKey ProtobufLicenseParser::ParseContentKey(
const std::string& decryption_key,
const video_widevine::License_KeyContainer& key,
bool is_verified) const {
bool is_verified,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id) const {
// This should have been verified before calling the parser.
CHECK_EQ(decryption_key.size(), 16u) << "Incorrect decryption key size.";
CHECK_EQ(key.type(), video_widevine::License_KeyContainer::CONTENT);
@@ -192,9 +198,9 @@ ContentKey ProtobufLicenseParser::ParseContentKey(
}
std::string wrapped_key = key.key().substr(0, kKeySizeWithoutPadding);
std::string unwrapped_key(wrapped_key);
if (!Decrypt(decryption_key, key.iv(), wrapped_key, &unwrapped_key)) {
std::string unwrapped_key;
if (!UnwrapContentKey(wrapped_key, provider_keys, provider_key_id,
decryption_key, key.iv(), &unwrapped_key)) {
VLOG(3) << "Failed to decrypt content key.";
return ContentKey();
}

View File

@@ -13,7 +13,9 @@ class ProtobufLicenseParser : public LicenseParser {
public:
WB_Result Parse(const std::string& decryption_key,
const ODKContext& odk_context,
const std::string& message) override;
const std::string& message,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id) override;
const widevine::RenewalKey* GetRenewalKey() const override;
@@ -25,7 +27,9 @@ class ProtobufLicenseParser : public LicenseParser {
ContentKey ParseContentKey(const std::string& decryption_key,
const video_widevine::License_KeyContainer& key,
bool is_verified) const;
bool is_verified,
const std::vector<ProviderKey>& provider_keys,
size_t provider_key_id) const;
private:
std::vector<widevine::RenewalKey> renewal_keys_;

View File

@@ -54,6 +54,7 @@ cc_test(
deps = [
"//api:license_whitebox_test",
"//reference/impl:general_license_whitebox_without_vmpra",
"//reference/impl:license_whitebox_provider_keys_test_data"
],
)
@@ -63,6 +64,7 @@ cc_test(
deps = [
"//api:remote_attestation_and_verification_with_vmpra_test",
"//reference/impl:general_license_whitebox_with_vmpra",
"//reference/impl:license_whitebox_provider_keys_test_data"
],
)
@@ -72,6 +74,7 @@ cc_test(
deps = [
"//api:remote_attestation_and_verification_without_vmpra_test",
"//reference/impl:general_license_whitebox_without_vmpra",
"//reference/impl:license_whitebox_provider_keys_test_data"
],
)
@@ -81,6 +84,7 @@ cc_test(
deps = [
"//api:license_whitebox_benchmark",
"//reference/impl:general_license_whitebox_without_vmpra",
"//reference/impl:license_whitebox_provider_keys_test_data"
],
)
@@ -90,5 +94,6 @@ cc_test(
deps = [
"//api:license_whitebox_uat_test",
"//reference/impl:uat_license_whitebox",
"//reference/impl:license_whitebox_provider_keys_test_data"
],
)