Remove Init Data From WB_License_Create

Rather than having init data for the license white-box be passed in
via WB_License_Create, this changes it so that it is assumed that
the private key is compiled into the white-box code.

Minor changes in this code drop include:
  - Updating the git attributes to avoid line-ending conflicts between
    different operating systems

  - Resolving a linking issue seen on Windows

  - Removing default parameter for padding in conformance tests
This commit is contained in:
Aaron Vaage
2020-12-04 14:25:24 -08:00
parent 6b00ecfb33
commit 8ff9df8eeb
37 changed files with 609 additions and 616 deletions

9
whitebox/.gitattributes vendored Normal file
View File

@@ -0,0 +1,9 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.cc text
*.h text
*.txt text

View File

@@ -10,12 +10,6 @@ cc_library(
visibility = ["//visibility:public"],
)
cc_library(
name = "export",
hdrs = ["export.h"],
visibility = ["//visibility:private"],
)
cc_library(
name = "aead_whitebox",
hdrs = [
@@ -23,7 +17,6 @@ cc_library(
],
visibility = ["//visibility:public"],
deps = [
":export",
":result",
],
)
@@ -35,16 +28,24 @@ cc_library(
],
visibility = ["//visibility:public"],
deps = [
":export",
":result",
],
)
cc_library(
name = "test_data",
name = "test_public_key",
testonly = True,
hdrs = [
"test_data.h",
"test_public_key.h",
],
visibility = ["//visibility:public"],
)
cc_library(
name = "aead_test_data",
testonly = True,
hdrs = [
"aead_test_data.h",
],
visibility = ["//visibility:public"],
)
@@ -90,10 +91,11 @@ cc_library(
],
visibility = ["//visibility:public"],
deps = [
":aead_test_data",
":aead_whitebox",
":test_data",
"//chromium_deps/testing",
],
alwayslink = True,
)
cc_library(
@@ -104,13 +106,14 @@ cc_library(
],
visibility = ["//visibility:public"],
deps = [
":aead_test_data",
":aead_whitebox",
":test_data",
"//benchmarking:data_source",
"//benchmarking:measurements",
"//chromium_deps/base:glog",
"//chromium_deps/testing",
],
alwayslink = True,
)
cc_library(
@@ -134,15 +137,17 @@ cc_library(
],
visibility = ["//visibility:public"],
deps = [
":aead_test_data",
":golden_data",
":license_whitebox",
":test_data",
":test_license_builder",
":test_public_key",
"//chromium_deps/cdm/keys:api",
"//chromium_deps/cdm/protos:license_protocol_proto",
"//chromium_deps/testing",
"//crypto_utils:rsa_key",
],
alwayslink = True,
)
cc_library(
@@ -160,15 +165,17 @@ cc_library(
],
visibility = ["//visibility:public"],
deps = [
":aead_test_data",
":license_whitebox",
":test_data",
":test_license_builder",
":test_public_key",
"//benchmarking:data_source",
"//benchmarking:measurements",
"//chromium_deps/base:glog",
"//chromium_deps/testing",
"//crypto_utils:crypto_util",
],
alwayslink = True,
)
cc_library(
@@ -182,4 +189,5 @@ cc_library(
":license_whitebox",
"//chromium_deps/testing",
],
alwayslink = True,
)

View File

@@ -1,27 +1,23 @@
// Copyright 2020 Google LLC. All Rights Reserved.
#ifndef WHITEBOX_API_TEST_DATA_H_
#define WHITEBOX_API_TEST_DATA_H_
#ifndef WHITEBOX_API_AEAD_TEST_DATA_H_
#define WHITEBOX_API_AEAD_TEST_DATA_H_
#include <stdint.h>
#include <vector>
namespace widevine {
// Returns init data that the aead white-box will accept.
std::vector<uint8_t> GetValidAeadInitData();
// Returns init data that the aead white-box will reject.
std::vector<uint8_t> GetInvalidAeadInitData();
// Returns valid init_data needed by the license whitebox tests when calling
// WB_License_Create().
std::vector<uint8_t> GetLicenseInitData();
// Returns the matching public key for the data returned by
// GetLicenseInitData(). The format is a DER encoded PKCS#1 RSAPublicKey.
std::vector<uint8_t> GetMatchingLicensePublicKey();
// Returns invalid non-empty init_data that should be rejected by
// WB_License_Create().
std::vector<uint8_t> GetInvalidLicenseInitData();
} // namespace widevine
#endif // WHITEBOX_API_TEST_DATA_H_
#endif // WHITEBOX_API_AEAD_TEST_DATA_H_

View File

@@ -6,7 +6,6 @@
#include <stddef.h>
#include <stdint.h>
#include "api/export.h"
#include "api/result.h"
#ifdef __cplusplus
@@ -43,7 +42,7 @@ typedef struct WB_Aead_Whitebox WB_Aead_Whitebox;
// |context| was null, if |context_size| was zero, or if |whitebox| was null.
//
// WB_RESULT_OUT_OF_MEMORY if the necessary memory could not be allocated.
WB_API WB_Result WB_Aead_Create(const uint8_t* whitebox_init_data,
WB_Result WB_Aead_Create(const uint8_t* whitebox_init_data,
size_t whitebox_init_data_size,
const uint8_t* context,
size_t context_size,
@@ -55,7 +54,7 @@ WB_API WB_Result WB_Aead_Create(const uint8_t* whitebox_init_data,
// Args:
// whitebox (in) : A pointer to a white-box instance. Passing in null will
// result in a no-op.
WB_API void WB_Aead_Delete(WB_Aead_Whitebox* whitebox);
void WB_Aead_Delete(WB_Aead_Whitebox* whitebox);
// Encrypts |input_data| and writes the cipher data, nonce and the data
// verification tag to |output_data|. The implementation should generate and use
@@ -86,7 +85,7 @@ WB_API void WB_Aead_Delete(WB_Aead_Whitebox* whitebox);
//
// WB_RESULT_BUFFER_TOO_SMALL if |output_data_size| (as input) was less than
// the required size.
WB_API WB_Result WB_Aead_Encrypt(const WB_Aead_Whitebox* whitebox,
WB_Result WB_Aead_Encrypt(const WB_Aead_Whitebox* whitebox,
const uint8_t* input_data,
size_t input_data_size,
uint8_t* output_data,
@@ -120,7 +119,7 @@ WB_API WB_Result WB_Aead_Encrypt(const WB_Aead_Whitebox* whitebox,
//
// WB_RESULT_DATA_VERIFICATION_ERROR if |input_data| failed data verification.
// The state of |output_data| is undefined.
WB_API WB_Result WB_Aead_Decrypt(const WB_Aead_Whitebox* whitebox,
WB_Result WB_Aead_Decrypt(const WB_Aead_Whitebox* whitebox,
const uint8_t* input_data,
size_t input_data_size,
uint8_t* output_data,

View File

@@ -5,8 +5,8 @@
#include <vector>
#include "api/aead_test_data.h"
#include "api/aead_whitebox.h"
#include "api/test_data.h"
#include "benchmarking/data_source.h"
#include "benchmarking/measurements.h"
#include "testing/gtest/include/gtest/gtest.h"

View File

@@ -2,11 +2,11 @@
#include <vector>
#include "api/aead_test_data.h"
#include "api/aead_whitebox.h"
#include "api/test_data.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
namespace widevine {
class AeadWhiteboxCreateTest : public ::testing::Test {
protected:
@@ -72,4 +72,4 @@ TEST_F(AeadWhiteboxCreateTest, InvalidParameterForNullWhitebox) {
WB_RESULT_INVALID_PARAMETER);
ASSERT_FALSE(whitebox_);
}
} // namespace
} // namespace widevine

View File

@@ -2,11 +2,12 @@
#include <vector>
#include "api/aead_test_data.h"
#include "api/aead_whitebox.h"
#include "api/test_data.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
namespace widevine {
// These tests focus on functionality that should and should not exist between
// different Aead White-box instances. They assume that all other functionality
// of the white-box has already been verified.
@@ -122,4 +123,4 @@ TEST_F(AeadWhiteboxCrossInstanceTest, DataVerificationErrorForCommonContext) {
ASSERT_EQ(plaintext, common_plaintext_);
}
} // namespace
} // namespace widevine

View File

@@ -2,11 +2,12 @@
#include <vector>
#include "api/aead_test_data.h"
#include "api/aead_whitebox.h"
#include "api/test_data.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
namespace widevine {
// For our decrypt tests, we assume that WB_Aead_Create() and WB_Aead_Encrypt()
// work and each test will have valid encrypted data.
class AeadWhiteboxDecryptTest : public ::testing::Test {
@@ -153,4 +154,4 @@ TEST_F(AeadWhiteboxDecryptTest, DataVerificationError) {
plaintext.data(), &plaintext_size),
WB_RESULT_DATA_VERIFICATION_ERROR);
}
} // namespace
} // namespace widevine

View File

@@ -2,15 +2,17 @@
#include <vector>
#include "api/aead_test_data.h"
#include "api/aead_whitebox.h"
#include "api/test_data.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace widevine {
namespace {
// Regardless of implementation, we need to have enough room in our output
// buffer to hold the additional information added by WB_Aead_Encrypt(). So
// this number just needs to be reasonably big compared to the input.
constexpr size_t kDefaultOutputSize = 256;
} // namespace
// For our encrypt tests, we assume that WB_Aead_Create() works and each test
// will have a functional instance. In these tests, we will not be checking the
@@ -116,4 +118,4 @@ TEST_F(AeadWhiteboxEncryptTest, BufferTooSmallForSmallOutputBuffer) {
// only check that |output_size| is larger than |input_.size()|.
ASSERT_GT(output_size, input_.size());
}
} // namespace
} // namespace widevine

View File

@@ -1,12 +0,0 @@
// Copyright 2020 Google LLC. All Rights Reserved.
#ifndef WHITEBOX_API_EXPORT_H_
#define WHITEBOX_API_EXPORT_H_
#if defined(_WIN32)
#define WB_API _declspec(dllexport)
#else
#define WB_API __attribute__((visibility("default")))
#endif
#endif // WHITEBOX_API_EXPORT_H_

View File

@@ -6,7 +6,6 @@
#include <stddef.h>
#include <stdint.h>
#include "api/export.h"
#include "api/result.h"
#ifdef __cplusplus
@@ -21,27 +20,20 @@ typedef enum {
WB_CIPHER_MODE_CBC,
} WB_CipherMode;
// Creates a new white-box instance using |whitebox_init_data|. A pointer to the
// white-box instance will be returned via |whitebox|.
// Creates a new white-box instance using the implementation's internal private
// key|. A pointer to the white-box instance will be returned via |whitebox|.
//
// Args:
// whitebox_init_data (in) : The implementation-specific initialization data
// needed to initialize a new white-box instance.
//
// 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.
//
// Returns:
// WB_RESULT_OK if the white-box instance was successfully created.
//
// WB_RESULT_INVALID_PARAMETER if |whitebox_init_data| was null or invalid.
// WB_RESULT_INVALID_PARAMETER if |whitebox| was null.
//
// WB_RESULT_OUT_OF_MEMORY if the necessary memory could not be allocated.
WB_API WB_Result WB_License_Create(const uint8_t* whitebox_init_data,
size_t whitebox_init_data_size,
WB_License_Whitebox** whitebox);
WB_Result WB_License_Create(WB_License_Whitebox** whitebox);
// Releases all resources used by the white-box instance pointed to by
// |whitebox|.
@@ -49,7 +41,7 @@ WB_API WB_Result WB_License_Create(const uint8_t* whitebox_init_data,
// Args:
// whitebox (in) : A pointer to a white-box instance. Passing in null will
// result in a no-op.
WB_API void WB_License_Delete(WB_License_Whitebox* whitebox);
void WB_License_Delete(WB_License_Whitebox* whitebox);
// Signs a license request using the CDM's private signing key.
//
@@ -75,8 +67,7 @@ WB_API void WB_License_Delete(WB_License_Whitebox* whitebox);
//
// WB_RESULT_BUFFER_TOO_SMALL if |signature_size| (as input) was less than the
// required size.
WB_API WB_Result
WB_License_SignLicenseRequest(const WB_License_Whitebox* whitebox,
WB_Result WB_License_SignLicenseRequest(const WB_License_Whitebox* whitebox,
const uint8_t* license_request,
size_t license_request_size,
uint8_t* signature,
@@ -141,8 +132,7 @@ WB_License_SignLicenseRequest(const WB_License_Whitebox* whitebox,
// verification to fail (therefore we return WB_RESULT_INVALID_SIGNATURE).
// Doing this was found to allow for better hardening of the license processing
// code.
WB_API WB_Result
WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox,
WB_Result WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox,
const uint8_t* core_message,
size_t core_message_size,
const uint8_t* message,
@@ -181,8 +171,7 @@ WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox,
// required size.
//
// WB_RESULT_INVALID_STATE if |whitebox| had no signing keys.
WB_API WB_Result
WB_License_SignRenewalRequest(const WB_License_Whitebox* whitebox,
WB_Result WB_License_SignRenewalRequest(const WB_License_Whitebox* whitebox,
const uint8_t* message,
size_t message_size,
uint8_t* signature,
@@ -212,8 +201,7 @@ WB_License_SignRenewalRequest(const WB_License_Whitebox* whitebox,
// |signature|.
//
// WB_RESULT_INVALID_STATE if |whitebox| had not loaded a license.
WB_API WB_Result
WB_License_VerifyRenewalResponse(const WB_License_Whitebox* whitebox,
WB_Result WB_License_VerifyRenewalResponse(const WB_License_Whitebox* whitebox,
const uint8_t* message,
size_t message_size,
const uint8_t* signature,
@@ -261,7 +249,7 @@ WB_License_VerifyRenewalResponse(const WB_License_Whitebox* whitebox,
// the required size.
//
// WB_RESULT_INVALID_STATE if |whitebox| had not loaded a license.
WB_API WB_Result WB_License_GetSecretString(const WB_License_Whitebox* whitebox,
WB_Result WB_License_GetSecretString(const WB_License_Whitebox* whitebox,
WB_CipherMode mode,
const uint8_t* key_id,
size_t key_id_size,
@@ -316,7 +304,7 @@ WB_API WB_Result WB_License_GetSecretString(const WB_License_Whitebox* whitebox,
// the required size.
//
// WB_RESULT_INVALID_STATE if |whitebox| had not loaded a license.
WB_API WB_Result WB_License_Decrypt(const WB_License_Whitebox* whitebox,
WB_Result WB_License_Decrypt(const WB_License_Whitebox* whitebox,
WB_CipherMode mode,
const uint8_t* key_id,
size_t key_id_size,
@@ -380,7 +368,7 @@ WB_API WB_Result WB_License_Decrypt(const WB_License_Whitebox* whitebox,
// than the required size.
//
// WB_RESULT_INVALID_STATE if |whitebox| had not loaded a license.
WB_API WB_Result WB_License_MaskedDecrypt(const WB_License_Whitebox* whitebox,
WB_Result WB_License_MaskedDecrypt(const WB_License_Whitebox* whitebox,
WB_CipherMode mode,
const uint8_t* key_id,
size_t key_id_size,
@@ -417,7 +405,7 @@ WB_API WB_Result WB_License_MaskedDecrypt(const WB_License_Whitebox* whitebox,
// secret_string_size (in) : The number of bytes in |secret_string|.
//
// unmasked_data (out) : The output buffer to write the unmasked data to.
WB_API void WB_License_Unmask(const uint8_t* masked_data,
void WB_License_Unmask(const uint8_t* masked_data,
size_t offset,
size_t size,
const uint8_t* secret_string,

View File

@@ -9,8 +9,8 @@
#include <vector>
#include "api/license_whitebox.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "api/test_public_key.h"
#include "benchmarking/data_source.h"
#include "crypto_utils/crypto_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -25,7 +25,7 @@ void LicenseWhiteboxBenchmark::SetUp() {
key_ = data_source_.Get(kBlockSize);
iv_ = data_source_.Get(kBlockSize);
const auto public_key_data = GetMatchingLicensePublicKey();
const auto public_key_data = GetLicensePublicKey();
public_key_.reset(widevine::RsaPublicKey::Create(
std::string(public_key_data.begin(), public_key_data.end())));
ASSERT_TRUE(public_key_);
@@ -33,12 +33,13 @@ void LicenseWhiteboxBenchmark::SetUp() {
License LicenseWhiteboxBenchmark::CreateLicense() const {
widevine::TestLicenseBuilder license_builder;
license_builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey());
license_builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey(),
TestLicenseBuilder::NoPadding());
// Use secure crypto as it will work with both Decrypt() and
// MaskedDecrypt().
license_builder.AddContentKey(
video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_CRYPTO,
key_id_, key_);
key_id_, key_, TestLicenseBuilder::NoPadding());
widevine::License license;
license_builder.Build(*public_key_, &license);

View File

@@ -56,15 +56,18 @@ class LicenseWhiteboxChromeOSTest
// Only use CBC keys so that we can always use the CBC content.
builder.AddContentKey(golden_data_.CBCCryptoKey().level,
golden_data_.CBCCryptoKey().id,
golden_data_.CBCCryptoKey().content->key);
golden_data_.CBCCryptoKey().content->key,
TestLicenseBuilder::NoPadding());
builder.AddContentKey(golden_data_.CBCDecodeKey().level,
golden_data_.CBCDecodeKey().id,
golden_data_.CBCDecodeKey().content->key);
golden_data_.CBCDecodeKey().content->key,
TestLicenseBuilder::NoPadding());
builder.AddContentKey(golden_data_.CBCHardwareKey().level,
golden_data_.CBCHardwareKey().id,
golden_data_.CBCHardwareKey().content->key);
golden_data_.CBCHardwareKey().content->key,
TestLicenseBuilder::NoPadding());
builder.SetRemoteAttestation(remote_attestation_);
builder.SetVerificationStatus(verification_status_);

View File

@@ -2,20 +2,12 @@
#include "api/license_whitebox.h"
#include <vector>
#include "api/test_data.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class LicenseWhiteboxCreateTest : public ::testing::Test {
protected:
void SetUp() override {
init_data_ = GetLicenseInitData();
ASSERT_GT(init_data_.size(), 0u);
}
void TearDown() override { WB_License_Delete(whitebox_); }
WB_License_Whitebox* whitebox_ = nullptr;
@@ -23,35 +15,12 @@ class LicenseWhiteboxCreateTest : public ::testing::Test {
};
TEST_F(LicenseWhiteboxCreateTest, Succeeds) {
ASSERT_EQ(WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_TRUE(whitebox_);
}
TEST_F(LicenseWhiteboxCreateTest, InvalidParameterForNullInitData) {
ASSERT_EQ(WB_License_Create(nullptr, init_data_.size(), &whitebox_),
WB_RESULT_INVALID_PARAMETER);
ASSERT_FALSE(whitebox_);
}
TEST_F(LicenseWhiteboxCreateTest, InvalidParameterForZeroInitDataSize) {
ASSERT_EQ(WB_License_Create(init_data_.data(), 0, &whitebox_),
WB_RESULT_INVALID_PARAMETER);
ASSERT_FALSE(whitebox_);
}
TEST_F(LicenseWhiteboxCreateTest, InvalidParameterForInvalidInitData) {
const std::vector<uint8_t> invalid_init_data = GetInvalidLicenseInitData();
ASSERT_EQ(WB_License_Create(invalid_init_data.data(),
invalid_init_data.size(), &whitebox_),
WB_RESULT_INVALID_PARAMETER);
ASSERT_FALSE(whitebox_);
}
TEST_F(LicenseWhiteboxCreateTest, InvalidParameterForNullWhitebox) {
ASSERT_EQ(WB_License_Create(init_data_.data(), init_data_.size(), nullptr),
WB_RESULT_INVALID_PARAMETER);
ASSERT_EQ(WB_License_Create(nullptr), WB_RESULT_INVALID_PARAMETER);
}
} // namespace

View File

@@ -9,7 +9,6 @@
#include "api/license_whitebox.h"
#include "api/license_whitebox_benchmark.h"
#include "api/result.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "benchmarking/data_source.h"
#include "benchmarking/measurements.h"
@@ -44,9 +43,7 @@ class LicenseWhiteboxDecryptBenchmark
masked_text_.resize(bytes_per_call);
plaintext_.resize(bytes_per_call);
const auto init_data = GetLicenseInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
const auto license = CreateLicense();
ASSERT_EQ(

View File

@@ -8,7 +8,6 @@
#include "api/golden_data.h"
#include "api/license_whitebox_test_base.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "crypto_utils/rsa_key.h"
#include "testing/gtest/include/gtest/gtest.h"

View File

@@ -7,7 +7,6 @@
#include "api/golden_data.h"
#include "api/license_whitebox_test_base.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "crypto_utils/rsa_key.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,15 +32,18 @@ class LicenseWhiteboxGetSecretStringTest : public LicenseWhiteboxTestBase {
builder.AddContentKey(golden_data_.CBCCryptoKey().level,
golden_data_.CBCCryptoKey().id,
golden_data_.CBCCryptoKey().content->key);
golden_data_.CBCCryptoKey().content->key,
TestLicenseBuilder::NoPadding());
builder.AddContentKey(golden_data_.CBCDecodeKey().level,
golden_data_.CBCDecodeKey().id,
golden_data_.CBCDecodeKey().content->key);
golden_data_.CBCDecodeKey().content->key,
TestLicenseBuilder::NoPadding());
builder.AddContentKey(golden_data_.CBCHardwareKey().level,
golden_data_.CBCHardwareKey().id,
golden_data_.CBCHardwareKey().content->key);
golden_data_.CBCHardwareKey().content->key,
TestLicenseBuilder::NoPadding());
builder.AddOperatorSessionKey(non_content_key_id_);

View File

@@ -315,9 +315,7 @@ class LicenseWhiteboxDecryptGoldenData : public ::testing::Test {
};
TEST_F(LicenseWhiteboxDecryptGoldenData, CryptoKeyWithCbcDataInCbcMode) {
ASSERT_EQ(WB_License_Create(kLicenseWhiteboxInitData,
kLicenseWhiteboxInitDataSize, &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, kCoreMessage, kCoreMessageSize, kMessage,

View File

@@ -9,7 +9,6 @@
#include "api/golden_data.h"
#include "api/license_whitebox_test_base.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "crypto_utils/crypto_util.h"
#include "crypto_utils/rsa_key.h"
@@ -42,23 +41,28 @@ class LicenseWhiteboxMaskedDecryptTest : public LicenseWhiteboxTestBase {
builder.AddContentKey(golden_data_.CBCCryptoKey().level,
golden_data_.CBCCryptoKey().id,
golden_data_.CBCCryptoKey().content->key);
golden_data_.CBCCryptoKey().content->key,
TestLicenseBuilder::NoPadding());
builder.AddContentKey(golden_data_.CTRCryptoKey().level,
golden_data_.CTRCryptoKey().id,
golden_data_.CTRCryptoKey().content->key);
golden_data_.CTRCryptoKey().content->key,
TestLicenseBuilder::NoPadding());
builder.AddContentKey(golden_data_.CBCDecodeKey().level,
golden_data_.CBCDecodeKey().id,
golden_data_.CBCDecodeKey().content->key);
golden_data_.CBCDecodeKey().content->key,
TestLicenseBuilder::NoPadding());
builder.AddContentKey(golden_data_.CTRDecodeKey().level,
golden_data_.CTRDecodeKey().id,
golden_data_.CTRDecodeKey().content->key);
golden_data_.CTRDecodeKey().content->key,
TestLicenseBuilder::NoPadding());
builder.AddContentKey(golden_data_.CBCHardwareKey().level,
golden_data_.CBCHardwareKey().id,
golden_data_.CBCHardwareKey().content->key);
golden_data_.CBCHardwareKey().content->key,
TestLicenseBuilder::NoPadding());
builder.AddOperatorSessionKey(non_content_key_id_);

View File

@@ -6,7 +6,6 @@
#include "api/license_whitebox.h"
#include "api/license_whitebox_benchmark.h"
#include "api/result.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "benchmarking/measurements.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -37,16 +36,13 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark,
Sampler sampler;
for (size_t i = 0; i < kIterations; i++) {
const auto init_data = GetLicenseInitData();
// We can only call ProcessLicenseResponse() once per whitebox instance. So
// we need to create a new instance each time. Collect samples for create +
// process license + delete so that we know the cost of getting a new
// license.
timer.Reset();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, license_.core_message.data(),
@@ -74,15 +70,12 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark,
Sampler sampler;
for (size_t i = 0; i < kIterations; i++) {
const auto init_data = GetLicenseInitData();
// We can only call ProcessLicenseResponse() once per whitebox instance. So
// we need to create a new instance each time. Collect samples for create +
// process license so that we know the true start-up cost.
timer.Reset();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
ASSERT_EQ(WB_License_ProcessLicenseResponse(
whitebox_, license_.core_message.data(),
@@ -111,9 +104,7 @@ TEST_F(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.
const auto init_data = GetLicenseInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
timer.Reset();

View File

@@ -7,7 +7,6 @@
#include "api/golden_data.h"
#include "api/license_whitebox_test_base.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "crypto_utils/crypto_util.h"
#include "crypto_utils/rsa_key.h"
@@ -100,8 +99,7 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseTest,
WB_RESULT_INVALID_PARAMETER);
}
TEST_F(LicenseWhiteboxProcessLicenseResponseTest,
InvalidParameterWithNoKeys) {
TEST_F(LicenseWhiteboxProcessLicenseResponseTest, InvalidParameterWithNoKeys) {
UseLicenseWithNoKeys();
ASSERT_EQ(

View File

@@ -9,7 +9,6 @@
#include "api/license_whitebox.h"
#include "api/license_whitebox_benchmark.h"
#include "api/result.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "benchmarking/data_source.h"
#include "benchmarking/measurements.h"
@@ -32,9 +31,7 @@ class LicenseWhiteboxSignBenchmark : public LicenseWhiteboxBenchmark {
message_ = Data().Get(kMessageSize);
signature_.resize(kSignatureSize);
const auto init_data = GetLicenseInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
const auto license = CreateLicense();
ASSERT_EQ(

View File

@@ -7,7 +7,6 @@
#include <vector>
#include "api/license_whitebox_test_base.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "crypto_utils/rsa_key.h"
#include "testing/gtest/include/gtest/gtest.h"

View File

@@ -7,7 +7,6 @@
#include <vector>
#include "api/license_whitebox_test_base.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "crypto_utils/crypto_util.h"
#include "crypto_utils/rsa_key.h"

View File

@@ -4,16 +4,14 @@
#include <string>
#include "api/test_data.h"
#include "api/test_public_key.h"
namespace widevine {
void LicenseWhiteboxTestBase::SetUp() {
const std::vector<uint8_t> init_data = GetLicenseInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
const auto public_key_data = GetMatchingLicensePublicKey();
const auto public_key_data = GetLicensePublicKey();
public_key_.reset(RsaPublicKey::Create(
std::string(public_key_data.begin(), public_key_data.end())));

View File

@@ -9,7 +9,6 @@
#include "api/license_whitebox.h"
#include "api/license_whitebox_benchmark.h"
#include "api/result.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "benchmarking/data_source.h"
#include "benchmarking/measurements.h"
@@ -28,9 +27,7 @@ class LicenseWhiteboxVerifyBenchmark : public LicenseWhiteboxBenchmark {
message_ = Data().Get(kMessageSize);
signature_ = SignAsServer(message_);
const auto init_data = GetLicenseInitData();
ASSERT_EQ(WB_License_Create(init_data.data(), init_data.size(), &whitebox_),
WB_RESULT_OK);
ASSERT_EQ(WB_License_Create(&whitebox_), WB_RESULT_OK);
const auto license = CreateLicense();
ASSERT_EQ(

View File

@@ -7,7 +7,6 @@
#include <vector>
#include "api/license_whitebox_test_base.h"
#include "api/test_data.h"
#include "api/test_license_builder.h"
#include "crypto_utils/crypto_util.h"
#include "crypto_utils/rsa_key.h"

View File

@@ -50,7 +50,7 @@ class TestLicenseBuilder {
TestLicenseBuilder();
void AddSigningKey(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& padding = NoPadding());
const std::vector<uint8_t>& padding);
// Add a content key so that there is some key in the license. This should not
// be used with AddContentKey().
@@ -59,7 +59,7 @@ class TestLicenseBuilder {
void AddContentKey(video_widevine::License_KeyContainer_SecurityLevel level,
const std::vector<uint8_t>& key_id,
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& padding = NoPadding());
const std::vector<uint8_t>& padding);
// The key id will matter as we will need to reference it, but the key won't
// matter since we are only using it as a means to verify that a non-content

View File

@@ -0,0 +1,17 @@
// Copyright 2020 Google LLC. All Rights Reserved.
#ifndef WHITEBOX_API_TEST_PUBLIC_KEY_H_
#define WHITEBOX_API_TEST_PUBLIC_KEY_H_
#include <stdint.h>
#include <vector>
namespace widevine {
// Returns the public key that matches the private key used by the license
// white-box. The public key should be a DER encoded PKCS#1 RSAPublicKey.
std::vector<uint8_t> GetLicensePublicKey();
} // namespace widevine
#endif // WHITEBOX_API_TEST_PUBLIC_KEY_H_

View File

@@ -19,12 +19,20 @@ cc_library(
],
)
cc_library(
name = "license_private_key",
hdrs = [
"license_private_key.h",
],
)
cc_library(
name = "license_whitebox",
srcs = [
"license_whitebox_impl.cc",
],
deps = [
":license_private_key",
":memory_util",
"//api:license_whitebox",
"//api:result",
@@ -39,13 +47,25 @@ cc_library(
)
cc_library(
name = "test_data",
name = "aead_test_data",
testonly = True,
srcs = [
"test_data.cc",
"aead_test_data.cc",
],
deps = [
"//api:test_data",
"//api:aead_test_data",
],
)
cc_library(
name = "license_test_data",
testonly = True,
srcs = [
"license_test_data.cc",
],
deps = [
":license_private_key",
"//api:test_public_key",
"//crypto_utils:rsa_test_keys",
],
)
@@ -54,8 +74,8 @@ cc_test(
name = "aead_whitebox_test",
size = "small",
deps = [
":aead_test_data",
":aead_whitebox",
":test_data",
"//api:aead_whitebox_test",
],
)
@@ -64,8 +84,8 @@ cc_test(
name = "aead_whitebox_benchmark",
size = "small",
deps = [
":aead_test_data",
":aead_whitebox",
":test_data",
"//api:aead_whitebox_benchmark",
],
)
@@ -74,8 +94,8 @@ cc_test(
name = "license_whitebox_test",
size = "small",
deps = [
":license_test_data",
":license_whitebox",
":test_data",
"//api:license_whitebox_test",
],
)
@@ -84,8 +104,8 @@ cc_test(
name = "license_whitebox_benchmark",
size = "small",
deps = [
":license_test_data",
":license_whitebox",
":test_data",
"//api:license_whitebox_benchmark",
],
)

View File

@@ -0,0 +1,24 @@
// Copyright 2020 Google LLC. All Rights Reserved.
#include "api/aead_test_data.h"
#include <string>
namespace widevine {
std::vector<uint8_t> GetValidAeadInitData() {
// Valid init data for our AEAD implementation is any AES key, so it just
// needs to be 16 bytes.
return {
0x00, 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x0,
0x00, 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x0,
};
}
std::vector<uint8_t> GetInvalidAeadInitData() {
// Valid init data would be any 16 bytes. To avoid returning a length of
// zero, just return one byte, that way we are still returning "some data".
return {0x00};
}
} // namespace widevine

View File

@@ -0,0 +1,16 @@
// Copyright 2020 Google LLC. All Rights Reserved.
#ifndef WHITEBOX_IMPL_REFERENCE_LICENSE_PRIVATE_KEY_H_
#define WHITEBOX_IMPL_REFERENCE_LICENSE_PRIVATE_KEY_H_
#include <stdint.h>
#include <vector>
namespace widevine {
// Return a RSA 2048-bit private key.
std::vector<uint8_t> GetLicensePrivateKey();
} // namespace widevine
#endif // WHITEBOX_IMPL_REFERENCE_LICENSE_PRIVATE_KEY_H_

View File

@@ -0,0 +1,23 @@
// Copyright 2020 Google LLC. All Rights Reserved.
#include <string>
#include "api/test_public_key.h"
#include "crypto_utils/rsa_test_keys.h"
#include "impl/reference/license_private_key.h"
namespace widevine {
std::vector<uint8_t> GetLicensePrivateKey() {
widevine::RsaTestKeys key_generator;
std::string init_data = key_generator.private_test_key_2_2048_bits();
return std::vector<uint8_t>(init_data.begin(), init_data.end());
}
std::vector<uint8_t> GetLicensePublicKey() {
widevine::RsaTestKeys key_generator;
std::string init_data = key_generator.public_test_key_2_2048_bits();
return std::vector<uint8_t>(init_data.begin(), init_data.end());
}
} // namespace widevine

View File

@@ -3,9 +3,12 @@
#include <cstddef>
#include <cstdint>
#include "impl/reference/license_private_key.h"
namespace widevine {
extern const uint8_t kLicenseWhiteboxInitData[] = {
std::vector<uint8_t> GetLicensePrivateKey() {
return {
0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
0xae, 0xa6, 0xa8, 0xea, 0xdd, 0xac, 0x6f, 0xb4, 0x41, 0x47, 0xcb, 0x18,
0x81, 0xeb, 0xdf, 0x4f, 0x17, 0xf7, 0x17, 0xc0, 0xab, 0x6f, 0x47, 0x50,
@@ -105,9 +108,8 @@ extern const uint8_t kLicenseWhiteboxInitData[] = {
0x69, 0xcd, 0x36, 0x8a, 0xba, 0xa5, 0xe3, 0xfe, 0xce, 0x8e, 0x67, 0xc5,
0x54, 0x41, 0x8c, 0x44, 0xc5, 0x50, 0x55, 0x7a, 0x7c, 0x91, 0xc9, 0x2e,
0x9e, 0x32, 0x63, 0x37, 0x42, 0x68, 0x29, 0x76, 0x41, 0xdb, 0x77, 0xfd,
0xcb, 0x6a, 0x73, 0x10};
extern const size_t kLicenseWhiteboxInitDataSize =
sizeof(kLicenseWhiteboxInitData);
0xcb, 0x6a, 0x73, 0x10,
};
}
} // namespace widevine

View File

@@ -16,6 +16,7 @@
#include "crypto_utils/aes_ctr_encryptor.h"
#include "crypto_utils/crypto_util.h"
#include "crypto_utils/rsa_key.h"
#include "impl/reference/license_private_key.h"
#include "impl/reference/memory_util.h"
#include "oemcrypto/odk/include/odk.h"
#include "oemcrypto/odk/include/odk_structs.h"
@@ -343,27 +344,16 @@ bool IsPlatformHardwareVerified(const video_widevine::License& license) {
} // namespace
WB_Result WB_License_Create(const uint8_t* whitebox_init_data,
size_t whitebox_init_data_size,
WB_License_Whitebox** whitebox) {
if (!whitebox_init_data || !whitebox) {
WB_Result WB_License_Create(WB_License_Whitebox** whitebox) {
if (whitebox == nullptr) {
DVLOG(1) << "Invalid parameter: null pointer.";
return WB_RESULT_INVALID_PARAMETER;
}
if (whitebox_init_data_size == 0) {
DVLOG(1) << "Invalid parameter: array size 0.";
return WB_RESULT_INVALID_PARAMETER;
}
// |whitebox_init_data| is simply the bytes of a PKCS #8 PrivateKeyInfo block
// of a RSA 2048 bit key.
std::unique_ptr<RsaPrivateKey> key(RsaPrivateKey::Create(std::string(
whitebox_init_data, whitebox_init_data + whitebox_init_data_size)));
if (!key) {
DVLOG(1) << "Invalid parameter: invalid init data.";
return WB_RESULT_INVALID_PARAMETER;
}
const auto init_data = widevine::GetLicensePrivateKey();
std::unique_ptr<RsaPrivateKey> key(
RsaPrivateKey::Create(std::string(init_data.begin(), init_data.end())));
DCHECK(key) << "Failed to load (internal) private key.";
// Should always be non-null on modern compilers
// (https://isocpp.org/wiki/faq/freestore-mgmt).

View File

@@ -1,42 +0,0 @@
// Copyright 2020 Google LLC. All Rights Reserved.
#include "api/test_data.h"
#include <string>
#include "crypto_utils/rsa_test_keys.h"
std::vector<uint8_t> GetValidAeadInitData() {
// Valid init data for our AEAD implementation is any AES key, so it just
// needs to be 16 bytes.
return {
0x00, 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x0,
0x00, 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x0,
};
}
std::vector<uint8_t> GetInvalidAeadInitData() {
// Valid init data would be any 16 bytes. To avoid returning a length of
// zero, just return one byte, that way we are still returning "some data".
return {0x00};
}
std::vector<uint8_t> GetLicenseInitData() {
// For the OpenSSL implementation |init_data| is simply a RSA 2048-bit
// private key. Matching public key is public_test_key_2_2048_bits().
widevine::RsaTestKeys key_generator;
std::string init_data = key_generator.private_test_key_2_2048_bits();
return std::vector<uint8_t>(init_data.begin(), init_data.end());
}
std::vector<uint8_t> GetMatchingLicensePublicKey() {
widevine::RsaTestKeys key_generator;
std::string init_data = key_generator.public_test_key_2_2048_bits();
return std::vector<uint8_t>(init_data.begin(), init_data.end());
}
std::vector<uint8_t> GetInvalidLicenseInitData() {
// For the OpenSSL implementation |init_data| is a private key. So a random
// collection of bytes should not be accepted.
return {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
}