Benchmarking and Unmasking
In this code drop we introduce the benchmarking tests that allow us to
compare the performance of different implementations. Like the other
tests, any implementation can link with them to create their own
binary.
There are two types of benchmarks:
1 - Throughput, which measures the speed that a function can process
information (bits per second). These are used for AEAD decrypt
and license white-box decrypt functions.
2 - Samples, which measures the min, 25% percentile, median, 75%
percentile, and max observed values. These is used for all other
functions as a way to measure the execute duration of a call.
The other change in this code drop is the update to the unmasking
function to only unmask a subset of the bytes in the masked buffer.
This was added to better align with the decoder behaviour in the CDM.
This commit is contained in:
44
api/BUILD
44
api/BUILD
@@ -60,6 +60,7 @@ cc_library(
|
||||
testonly = True,
|
||||
srcs = ["test_license_builder.cc"],
|
||||
hdrs = ["test_license_builder.h"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//chromium_deps/cdm/keys:dev_certs",
|
||||
"//chromium_deps/cdm/protos:license_protocol_proto",
|
||||
@@ -86,6 +87,23 @@ cc_library(
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "aead_whitebox_benchmark",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"aead_whitebox_benchmark.cc",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":aead_whitebox",
|
||||
":test_data",
|
||||
"//benchmarking:data_source",
|
||||
"//benchmarking:measurements",
|
||||
"//chromium_deps/base:glog",
|
||||
"//chromium_deps/testing",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "license_whitebox_test",
|
||||
testonly = True,
|
||||
@@ -116,3 +134,29 @@ cc_library(
|
||||
"//crypto_utils:rsa_key",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "license_whitebox_benchmark",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"license_whitebox_benchmark.cc",
|
||||
"license_whitebox_decrypt_benchmark.cc",
|
||||
"license_whitebox_process_license_response_benchmark.cc",
|
||||
"license_whitebox_sign_benchmark.cc",
|
||||
"license_whitebox_verify_benchmark.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"license_whitebox_benchmark.h",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":license_whitebox",
|
||||
":test_data",
|
||||
":test_license_builder",
|
||||
"//benchmarking:data_source",
|
||||
"//benchmarking:measurements",
|
||||
"//chromium_deps/base:glog",
|
||||
"//chromium_deps/testing",
|
||||
"//crypto_utils:crypto_util",
|
||||
],
|
||||
)
|
||||
|
||||
158
api/aead_whitebox_benchmark.cc
Normal file
158
api/aead_whitebox_benchmark.cc
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "api/aead_whitebox.h"
|
||||
#include "api/test_data.h"
|
||||
#include "base/logging.h"
|
||||
#include "benchmarking/data_source.h"
|
||||
#include "benchmarking/measurements.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace widevine {
|
||||
namespace {
|
||||
constexpr size_t kSafeOverhead = 128;
|
||||
} // namespace
|
||||
|
||||
// Param:
|
||||
// - The number of bytes that should be pushed through Decrypt() each time.
|
||||
// - The number of iterations to run.
|
||||
class AeadWhiteboxBenchmark
|
||||
: public ::testing::Test,
|
||||
public testing::WithParamInterface<std::tuple<size_t, size_t>> {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
const std::vector<uint8_t> context = data_source_.Get(16);
|
||||
const std::vector<uint8_t> init_data = GetValidAeadInitData();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_Aead_Create(init_data.data(), init_data.size(), context.data(),
|
||||
context.size(), &whitebox_));
|
||||
|
||||
std::tie(plaintext_size_, iterations_) = GetParam();
|
||||
ciphertext_size_ = plaintext_size_ + kSafeOverhead;
|
||||
}
|
||||
|
||||
void TearDown() override { WB_Aead_Delete(whitebox_); }
|
||||
|
||||
void InitWithCiphertextAsInput() {
|
||||
// Make sure both buffers are the correct size for the test now that we know
|
||||
// that the ciphertext is the input and the plaintext is the output.
|
||||
input_.resize(ciphertext_size_);
|
||||
output_.resize(plaintext_size_);
|
||||
|
||||
const auto plaintext = data_source_.Get(plaintext_size_);
|
||||
|
||||
size_t size = ciphertext_size_;
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_Aead_Encrypt(whitebox_, plaintext.data(), plaintext.size(),
|
||||
input_.data(), &size));
|
||||
input_.resize(size);
|
||||
}
|
||||
|
||||
void InitWithPlaintextAsInput() {
|
||||
// Make sure both buffers are the correct size for the test now that we know
|
||||
// that the plaintext is the input and the ciphertext is the output.
|
||||
input_ = data_source_.Get(plaintext_size_);
|
||||
output_.resize(ciphertext_size_);
|
||||
}
|
||||
|
||||
WB_Aead_Whitebox* whitebox_ = nullptr;
|
||||
|
||||
DataSource data_source_;
|
||||
|
||||
size_t plaintext_size_;
|
||||
size_t ciphertext_size_;
|
||||
|
||||
std::vector<uint8_t> input_;
|
||||
std::vector<uint8_t> output_;
|
||||
|
||||
size_t iterations_;
|
||||
};
|
||||
|
||||
TEST_P(AeadWhiteboxBenchmark, EncryptDuration) {
|
||||
InitWithPlaintextAsInput();
|
||||
|
||||
Timer timer;
|
||||
Sampler sampler;
|
||||
|
||||
for (size_t i = 0; i < iterations_; i++) {
|
||||
timer.Reset();
|
||||
|
||||
size_t output_size = output_.size();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_Aead_Encrypt(whitebox_, input_.data(), input_.size(),
|
||||
output_.data(), &output_size));
|
||||
|
||||
sampler.Push(timer.Get());
|
||||
}
|
||||
|
||||
PrettyPrint("AEAD Encrypt Duration", sampler, input_.size());
|
||||
}
|
||||
|
||||
TEST_P(AeadWhiteboxBenchmark, EncryptThroughput) {
|
||||
InitWithPlaintextAsInput();
|
||||
|
||||
Timer timer;
|
||||
timer.Reset();
|
||||
|
||||
for (size_t i = 0; i < iterations_; i++) {
|
||||
size_t output_size = output_.size();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_Aead_Encrypt(whitebox_, input_.data(), input_.size(),
|
||||
output_.data(), &output_size));
|
||||
}
|
||||
|
||||
Throughput throughput(timer.Get(), input_.size() * iterations_);
|
||||
PrettyPrint("AEAD Encrypt Throughput", throughput, input_.size());
|
||||
}
|
||||
|
||||
TEST_P(AeadWhiteboxBenchmark, DecryptDuration) {
|
||||
InitWithCiphertextAsInput();
|
||||
|
||||
Timer timer;
|
||||
Sampler sampler;
|
||||
|
||||
for (size_t i = 0; i < iterations_; i++) {
|
||||
timer.Reset();
|
||||
|
||||
size_t output_size = output_.size();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_Aead_Decrypt(whitebox_, input_.data(), input_.size(),
|
||||
output_.data(), &output_size));
|
||||
|
||||
sampler.Push(timer.Get());
|
||||
}
|
||||
|
||||
PrettyPrint("AEAD Decrypt Duration", sampler, input_.size());
|
||||
}
|
||||
|
||||
TEST_P(AeadWhiteboxBenchmark, DecryptThroughput) {
|
||||
InitWithCiphertextAsInput();
|
||||
|
||||
Timer timer;
|
||||
timer.Reset();
|
||||
|
||||
for (size_t i = 0; i < iterations_; i++) {
|
||||
size_t output_size = output_.size();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_Aead_Decrypt(whitebox_, input_.data(), input_.size(),
|
||||
output_.data(), &output_size));
|
||||
}
|
||||
|
||||
Throughput throughput(timer.Get(), iterations_ * input_.size());
|
||||
PrettyPrint("AEAD Encrypt Throughput", throughput, input_.size());
|
||||
}
|
||||
|
||||
// Run the test will different sizes of input-per-call. The values we have
|
||||
// picked are divided into three groups, "bytes" and "kilobytes". The services
|
||||
// team says that a license will normally by 1KB as a base size and then 50 to
|
||||
// 100 bytes per key.
|
||||
INSTANTIATE_TEST_SUITE_P(DifferentBytesPerCall,
|
||||
AeadWhiteboxBenchmark,
|
||||
::testing::Values(std::make_tuple(1024, 100),
|
||||
std::make_tuple(16 * 1024, 50),
|
||||
std::make_tuple(256 * 1024, 25)));
|
||||
} // namespace widevine
|
||||
@@ -370,23 +370,35 @@ WB_Result WB_License_MaskedDecrypt(const WB_License_Whitebox* whitebox,
|
||||
uint8_t* masked_output_data,
|
||||
size_t* masked_output_data_size);
|
||||
|
||||
// Unmasks the data in |buffer| using |secret_string|. |buffer| is operated on
|
||||
// in-place.
|
||||
// Unmasks a subset of the data in |masked_data| using |secret_string| and
|
||||
// writes it to |unmasked_data|.
|
||||
//
|
||||
// The subset is denoted as |offset| (inclusive) to |offset + size| (exclusive).
|
||||
// It is assumed that |offset| and |offset + size - 1| are both valid indexes
|
||||
// into |masked_data|.
|
||||
//
|
||||
// It is assumed that indexes between 0 and |size - 1| (inclusive) are all valid
|
||||
// indexes into |unmasked_data|.
|
||||
//
|
||||
// Args:
|
||||
// secret_string (in) : The "key" used to unmask the data in |buffer|.
|
||||
// masked_data (in) : The masked data to read from.
|
||||
//
|
||||
// offset (in) : The index into |masked_data| from where to start reading data.
|
||||
//
|
||||
// size (in) : The number of bytes from |masked_data| to unmask and copy into
|
||||
// |unmasked_data|.
|
||||
//
|
||||
// secret_string (in) : The auxiliary data for unmasking |masked_data|.
|
||||
//
|
||||
// secret_string_size (in) : The number of bytes in |secret_string|.
|
||||
//
|
||||
// buffer (in/out) : As input, this is the masked data. As output, this is the
|
||||
// unmasked data. The number of bytes in the masked data will be equal to the
|
||||
// number of bytes in the unmasked data.
|
||||
//
|
||||
// buffer_size (in) : The number of bytes in |buffer|.
|
||||
void WB_License_Unmask(const uint8_t* secret_string,
|
||||
// unmasked_data (out) : The output buffer to write the unmasked data to.
|
||||
void WB_License_Unmask(const uint8_t* masked_data,
|
||||
size_t offset,
|
||||
size_t size,
|
||||
const uint8_t* secret_string,
|
||||
size_t secret_string_size,
|
||||
uint8_t* buffer,
|
||||
size_t buffer_size);
|
||||
uint8_t* unmasked_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
63
api/license_whitebox_benchmark.cc
Normal file
63
api/license_whitebox_benchmark.cc
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
||||
#include "api/license_whitebox_benchmark.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "api/license_whitebox.h"
|
||||
#include "api/test_data.h"
|
||||
#include "api/test_license_builder.h"
|
||||
#include "benchmarking/data_source.h"
|
||||
#include "crypto_utils/crypto_util.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace widevine {
|
||||
namespace {
|
||||
constexpr size_t kBlockSize = 16; // This must align with the AES block size.
|
||||
} // namespace
|
||||
|
||||
void LicenseWhiteboxBenchmark::SetUp() {
|
||||
key_id_ = data_source_.Get(8); // The id size is not meaningful.
|
||||
key_ = data_source_.Get(kBlockSize);
|
||||
iv_ = data_source_.Get(kBlockSize);
|
||||
|
||||
const auto public_key_data = GetMatchingLicensePublicKey();
|
||||
public_key_.reset(widevine::RsaPublicKey::Create(
|
||||
std::string(public_key_data.begin(), public_key_data.end())));
|
||||
ASSERT_TRUE(public_key_);
|
||||
}
|
||||
|
||||
License LicenseWhiteboxBenchmark::CreateLicense() const {
|
||||
widevine::TestLicenseBuilder license_builder;
|
||||
license_builder.AddSigningKey(TestLicenseBuilder::DefaultSigningKey());
|
||||
// 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_);
|
||||
|
||||
widevine::License license;
|
||||
license_builder.Build(*public_key_, &license);
|
||||
|
||||
return license;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> LicenseWhiteboxBenchmark::SignAsServer(
|
||||
const std::vector<uint8_t>& message) const {
|
||||
// The server key is the first half of the signing key.
|
||||
const auto key = TestLicenseBuilder::DefaultSigningKey();
|
||||
const std::string server_key(key.begin(),
|
||||
key.begin() + crypto_util::kSigningKeySizeBytes);
|
||||
|
||||
// crypto util uses strings, so we will need to convert the result back to a
|
||||
// vector before we return it.
|
||||
const auto signature = crypto_util::CreateSignatureHmacSha256(
|
||||
server_key, std::string(message.begin(), message.end()));
|
||||
return std::vector<uint8_t>(signature.begin(), signature.end());
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
47
api/license_whitebox_benchmark.h
Normal file
47
api/license_whitebox_benchmark.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
||||
#ifndef WHITEBOX_API_LICENSE_WHITEBOX_BENCHMARK_H_
|
||||
#define WHITEBOX_API_LICENSE_WHITEBOX_BENCHMARK_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "api/license_whitebox.h"
|
||||
#include "api/test_license_builder.h"
|
||||
#include "benchmarking/data_source.h"
|
||||
#include "crypto_utils/rsa_key.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace widevine {
|
||||
class LicenseWhiteboxBenchmark : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() override;
|
||||
|
||||
License CreateLicense() const;
|
||||
|
||||
std::vector<uint8_t> SignAsServer(const std::vector<uint8_t>& message) const;
|
||||
|
||||
DataSource& Data() { return data_source_; }
|
||||
|
||||
const RsaPublicKey* PublicKey() const { return public_key_.get(); }
|
||||
|
||||
const std::vector<uint8_t>& ContentKeyId() const { return key_id_; }
|
||||
|
||||
const std::vector<uint8_t>& ContentKey() const { return key_; }
|
||||
|
||||
const std::vector<uint8_t>& ContentIV() const { return iv_; }
|
||||
|
||||
private:
|
||||
DataSource data_source_;
|
||||
std::unique_ptr<RsaPublicKey> public_key_;
|
||||
|
||||
std::vector<uint8_t> key_id_;
|
||||
std::vector<uint8_t> key_;
|
||||
std::vector<uint8_t> iv_;
|
||||
};
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
#endif // WHITEBOX_API_LICENSE_WHITEBOX_BENCHMARK_H_
|
||||
182
api/license_whitebox_decrypt_benchmark.cc
Normal file
182
api/license_whitebox_decrypt_benchmark.cc
Normal file
@@ -0,0 +1,182 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#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 "base/logging.h"
|
||||
#include "benchmarking/data_source.h"
|
||||
#include "benchmarking/measurements.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace widevine {
|
||||
namespace {
|
||||
// The mask size can be any size (depends on the implementation), so 256 should
|
||||
// be more than enough for any implementation.
|
||||
constexpr size_t kMaskSize = 256;
|
||||
} // namespace
|
||||
|
||||
// Test Parameter:
|
||||
// - The number of blocks given to each decrypt call. Each block will be 16
|
||||
// bytes.
|
||||
// - The number of iterations to run.
|
||||
class LicenseWhiteboxDecryptBenchmark
|
||||
: public LicenseWhiteboxBenchmark,
|
||||
public testing::WithParamInterface<std::tuple<size_t, size_t>> {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
LicenseWhiteboxBenchmark::SetUp();
|
||||
|
||||
// Extract all parameters.
|
||||
size_t blocks_per_call;
|
||||
std::tie(blocks_per_call, iterations_) = GetParam();
|
||||
|
||||
// We are using AES with no padding, the input and output will be the same
|
||||
// size.
|
||||
const size_t bytes_per_call = blocks_per_call * 16;
|
||||
ciphertext_ = Data().Get(bytes_per_call);
|
||||
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);
|
||||
|
||||
const auto license = CreateLicense();
|
||||
ASSERT_EQ(WB_License_ProcessLicenseResponse(
|
||||
whitebox_, license.message.data(), license.message.size(),
|
||||
license.signature.data(), license.signature.size(),
|
||||
license.session_key.data(), license.session_key.size(),
|
||||
license.request.data(), license.request.size()),
|
||||
WB_RESULT_OK);
|
||||
}
|
||||
|
||||
void TearDown() override { WB_License_Delete(whitebox_); }
|
||||
|
||||
WB_License_Whitebox* whitebox_;
|
||||
|
||||
std::vector<uint8_t> ciphertext_;
|
||||
std::vector<uint8_t> masked_text_;
|
||||
std::vector<uint8_t> plaintext_;
|
||||
|
||||
size_t iterations_;
|
||||
};
|
||||
|
||||
TEST_P(LicenseWhiteboxDecryptBenchmark, DecryptCBCThroughput) {
|
||||
Timer timer;
|
||||
timer.Reset();
|
||||
|
||||
for (size_t i = 0; i < iterations_; i++) {
|
||||
size_t plaintext_size = plaintext_.size();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC,
|
||||
ContentKeyId().data(), ContentKeyId().size(),
|
||||
ciphertext_.data(), ciphertext_.size(),
|
||||
ContentIV().data(), ContentIV().size(),
|
||||
plaintext_.data(), &plaintext_size));
|
||||
}
|
||||
|
||||
Throughput throughput(timer.Get(), iterations_ * ciphertext_.size());
|
||||
PrettyPrint("License Decrypt CBC Throughput", throughput, ciphertext_.size());
|
||||
}
|
||||
|
||||
TEST_P(LicenseWhiteboxDecryptBenchmark, DecryptCTRThroughput) {
|
||||
Timer timer;
|
||||
timer.Reset();
|
||||
|
||||
for (size_t i = 0; i < iterations_; i++) {
|
||||
size_t plaintext_size = plaintext_.size();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CTR,
|
||||
ContentKeyId().data(), ContentKeyId().size(),
|
||||
ciphertext_.data(), ciphertext_.size(),
|
||||
ContentIV().data(), ContentIV().size(),
|
||||
plaintext_.data(), &plaintext_size));
|
||||
}
|
||||
|
||||
Throughput throughput(timer.Get(), iterations_ * ciphertext_.size());
|
||||
PrettyPrint("License Decrypt CTR Throughput", throughput, ciphertext_.size());
|
||||
}
|
||||
|
||||
TEST_P(LicenseWhiteboxDecryptBenchmark, MaskedDecryptCBCThroughput) {
|
||||
std::vector<uint8_t> mask(kMaskSize);
|
||||
size_t mask_size = mask.size();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_License_GetSecretString(
|
||||
whitebox_, WB_CIPHER_MODE_CBC, ContentKeyId().data(),
|
||||
ContentKeyId().size(), mask.data(), &mask_size));
|
||||
mask.resize(mask_size);
|
||||
|
||||
Timer timer;
|
||||
timer.Reset();
|
||||
|
||||
for (size_t i = 0; i < iterations_; i++) {
|
||||
// Include the unmask in the timing as it will be part of the flow from
|
||||
// encrypted to consumption.
|
||||
size_t plaintext_size = plaintext_.size();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_License_MaskedDecrypt(
|
||||
whitebox_, WB_CIPHER_MODE_CBC, ContentKeyId().data(),
|
||||
ContentKeyId().size(), ciphertext_.data(), ciphertext_.size(),
|
||||
ContentIV().data(), ContentIV().size(), masked_text_.data(),
|
||||
&plaintext_size));
|
||||
|
||||
WB_License_Unmask(masked_text_.data(), 0, plaintext_size, mask.data(),
|
||||
mask.size(), plaintext_.data());
|
||||
}
|
||||
|
||||
Throughput throughput(timer.Get(), iterations_ * ciphertext_.size());
|
||||
PrettyPrint("License Masked Decrypt CBC Throughput", throughput,
|
||||
ciphertext_.size());
|
||||
}
|
||||
|
||||
TEST_P(LicenseWhiteboxDecryptBenchmark, MaskedDecryptCTRThroughput) {
|
||||
std::vector<uint8_t> mask(kMaskSize);
|
||||
size_t mask_size = mask.size();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_License_GetSecretString(
|
||||
whitebox_, WB_CIPHER_MODE_CTR, ContentKeyId().data(),
|
||||
ContentKeyId().size(), mask.data(), &mask_size));
|
||||
mask.resize(mask_size);
|
||||
|
||||
Timer timer;
|
||||
timer.Reset();
|
||||
|
||||
for (size_t i = 0; i < iterations_; i++) {
|
||||
// Include the unmask in the timing as it will be part of the flow from
|
||||
// encrypted to consumption.
|
||||
size_t plaintext_size = plaintext_.size();
|
||||
ASSERT_EQ(WB_RESULT_OK,
|
||||
WB_License_MaskedDecrypt(
|
||||
whitebox_, WB_CIPHER_MODE_CTR, ContentKeyId().data(),
|
||||
ContentKeyId().size(), ciphertext_.data(), ciphertext_.size(),
|
||||
ContentIV().data(), ContentIV().size(), masked_text_.data(),
|
||||
&plaintext_size));
|
||||
|
||||
WB_License_Unmask(masked_text_.data(), 0, plaintext_size, mask.data(),
|
||||
mask.size(), plaintext_.data());
|
||||
}
|
||||
|
||||
Throughput throughput(timer.Get(), iterations_ * ciphertext_.size());
|
||||
PrettyPrint("License Masked Decrypt CTR Throughput", throughput,
|
||||
ciphertext_.size());
|
||||
}
|
||||
|
||||
// The first value is the number of blocks. Each block is 16 bytes.
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
DifferentBytesPerCall,
|
||||
LicenseWhiteboxDecryptBenchmark,
|
||||
::testing::Values(std::make_tuple(1, 100), // 16 B
|
||||
std::make_tuple(16, 100), // 256 B
|
||||
std::make_tuple(64, 100), // 1 KB
|
||||
std::make_tuple(1024, 100), // 16 KB
|
||||
std::make_tuple(16 * 1024, 25), // 256 KB
|
||||
std::make_tuple(64 * 1024, 10))); // 1 MB
|
||||
} // namespace widevine
|
||||
@@ -25,13 +25,13 @@ class LicenseWhiteboxMaskedDecryptTest : public LicenseWhiteboxTestBase {
|
||||
|
||||
// Because we are going to use the same buffer for both tests, make sure it
|
||||
// will be large enough for either.
|
||||
plaintext_size_ = std::max(golden_data_.CBCContent().ciphertext.size(),
|
||||
golden_data_.CTRContent().ciphertext.size());
|
||||
plaintext_.resize(plaintext_size_);
|
||||
masked_text_size_ = std::max(golden_data_.CBCContent().ciphertext.size(),
|
||||
golden_data_.CTRContent().ciphertext.size());
|
||||
masked_text_.resize(masked_text_size_);
|
||||
|
||||
// We have no idea how big the secret string will be, but it should be safe
|
||||
// to assume it won't be larger than the plaintext.
|
||||
secret_string_size_ = plaintext_size_;
|
||||
secret_string_size_ = masked_text_size_;
|
||||
secret_string_.resize(secret_string_size_);
|
||||
|
||||
golden_data_.MakeKeyIdDifferent(&non_content_key_id_);
|
||||
@@ -82,7 +82,9 @@ class LicenseWhiteboxMaskedDecryptTest : public LicenseWhiteboxTestBase {
|
||||
size_t secret_string_size_;
|
||||
std::vector<uint8_t> secret_string_;
|
||||
|
||||
size_t plaintext_size_;
|
||||
size_t masked_text_size_;
|
||||
std::vector<uint8_t> masked_text_;
|
||||
|
||||
std::vector<uint8_t> plaintext_;
|
||||
};
|
||||
|
||||
@@ -96,16 +98,16 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCbcMode) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
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(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CBCDecodeKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
|
||||
// Now unmask the data.
|
||||
ASSERT_EQ(
|
||||
@@ -115,8 +117,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCbcMode) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.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_EQ(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
}
|
||||
|
||||
@@ -130,16 +136,16 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCtrMode) {
|
||||
golden_data_.CTRDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CTRDecodeKey().content->iv.data(),
|
||||
golden_data_.CTRDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CTRDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
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(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CTRDecodeKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
|
||||
// Now unmask the data.
|
||||
ASSERT_EQ(
|
||||
@@ -149,8 +155,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCtrMode) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.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_EQ(plaintext_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
}
|
||||
|
||||
@@ -166,15 +176,15 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCtrMode) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
masked_text_.resize(masked_text_size_);
|
||||
|
||||
// Whatever is returned must not be the original text.
|
||||
ASSERT_EQ(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CBCDecodeKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
|
||||
// Now unmask the data. Still should not match.
|
||||
ASSERT_EQ(
|
||||
@@ -184,9 +194,13 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCtrMode) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
|
||||
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(masked_text_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
}
|
||||
|
||||
// We try to decrypt CTR encrypted data in CBC mode. All operations should be
|
||||
@@ -201,15 +215,15 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCbcMode) {
|
||||
golden_data_.CTRDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CTRDecodeKey().content->iv.data(),
|
||||
golden_data_.CTRDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CTRDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
masked_text_.resize(masked_text_size_);
|
||||
|
||||
// Whatever is returned must not be the original text.
|
||||
ASSERT_EQ(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CTRDecodeKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
|
||||
// Now unmask the data. Still should not match.
|
||||
ASSERT_EQ(
|
||||
@@ -219,9 +233,13 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCbcMode) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
|
||||
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(masked_text_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
|
||||
@@ -234,16 +252,16 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
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(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CBCDecodeKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
|
||||
// Now unmask the data.
|
||||
ASSERT_EQ(
|
||||
@@ -253,8 +271,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.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_EQ(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
}
|
||||
|
||||
@@ -268,16 +290,16 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCtrMode) {
|
||||
golden_data_.CTRDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CTRDecodeKey().content->iv.data(),
|
||||
golden_data_.CTRDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CTRDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
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(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CTRDecodeKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
|
||||
// Now unmask the data.
|
||||
ASSERT_EQ(
|
||||
@@ -287,8 +309,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCtrMode) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.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_EQ(plaintext_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
}
|
||||
|
||||
@@ -304,15 +330,15 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCtrMode) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
masked_text_.resize(masked_text_size_);
|
||||
|
||||
// Whatever is returned must not be the original text.
|
||||
ASSERT_EQ(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CBCDecodeKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
|
||||
// Now unmask the data. Still should not match.
|
||||
ASSERT_EQ(
|
||||
@@ -322,9 +348,13 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCtrMode) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
|
||||
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(masked_text_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
}
|
||||
|
||||
// We try to decrypt CTR encrypted data in CBC mode. All operations should be
|
||||
@@ -339,15 +369,15 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCbcMode) {
|
||||
golden_data_.CTRCryptoKey().content->ciphertext.data(),
|
||||
golden_data_.CTRCryptoKey().content->ciphertext.size(),
|
||||
golden_data_.CTRCryptoKey().content->iv.data(),
|
||||
golden_data_.CTRCryptoKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CTRCryptoKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
masked_text_.resize(masked_text_size_);
|
||||
|
||||
// Whatever is returned must not be the original text.
|
||||
ASSERT_EQ(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CTRCryptoKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CTRCryptoKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CTRCryptoKey().content->plaintext);
|
||||
|
||||
// Now unmask the data. Still should not match.
|
||||
ASSERT_EQ(
|
||||
@@ -357,9 +387,13 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCbcMode) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CTRCryptoKey().content->plaintext);
|
||||
|
||||
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(masked_text_, golden_data_.CTRCryptoKey().content->plaintext);
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) {
|
||||
@@ -372,16 +406,16 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) {
|
||||
golden_data_.CBCCryptoKey().content->ciphertext.data(),
|
||||
golden_data_.CBCCryptoKey().content->ciphertext.size(),
|
||||
golden_data_.CBCCryptoKey().content->iv.data(),
|
||||
golden_data_.CBCCryptoKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCCryptoKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
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(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CBCCryptoKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CBCCryptoKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CBCCryptoKey().content->plaintext);
|
||||
|
||||
// Now unmask the data.
|
||||
ASSERT_EQ(
|
||||
@@ -391,8 +425,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.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_EQ(plaintext_, golden_data_.CBCCryptoKey().content->plaintext);
|
||||
}
|
||||
|
||||
@@ -406,16 +444,16 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataAndPKCS8Padding) {
|
||||
golden_data_.CTRCryptoKey().content->ciphertext.data(),
|
||||
golden_data_.CTRCryptoKey().content->ciphertext.size(),
|
||||
golden_data_.CTRCryptoKey().content->iv.data(),
|
||||
golden_data_.CTRCryptoKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CTRCryptoKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
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(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CTRCryptoKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CTRCryptoKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CTRCryptoKey().content->plaintext);
|
||||
|
||||
// Now unmask the data.
|
||||
ASSERT_EQ(
|
||||
@@ -425,8 +463,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataAndPKCS8Padding) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.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_EQ(plaintext_, golden_data_.CTRCryptoKey().content->plaintext);
|
||||
}
|
||||
|
||||
@@ -445,16 +487,16 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
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(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CBCDecodeKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
|
||||
// Now unmask the data.
|
||||
ASSERT_EQ(
|
||||
@@ -464,14 +506,18 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.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_EQ(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||
|
||||
// Reset our output buffer.
|
||||
plaintext_.clear();
|
||||
plaintext_size_ = golden_data_.CTRDecodeKey().content->plaintext.size();
|
||||
plaintext_.resize(plaintext_size_);
|
||||
masked_text_.clear();
|
||||
masked_text_size_ = golden_data_.CTRDecodeKey().content->plaintext.size();
|
||||
masked_text_.resize(masked_text_size_);
|
||||
|
||||
ASSERT_EQ(
|
||||
WB_License_MaskedDecrypt(
|
||||
@@ -480,20 +526,20 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) {
|
||||
golden_data_.CTRDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CTRDecodeKey().content->iv.data(),
|
||||
golden_data_.CTRDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CTRDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
plaintext_.resize(plaintext_size_);
|
||||
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(plaintext_.size(),
|
||||
ASSERT_EQ(masked_text_.size(),
|
||||
golden_data_.CTRDecodeKey().content->plaintext.size());
|
||||
ASSERT_NE(plaintext_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
ASSERT_NE(masked_text_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
|
||||
// Now unmask the data.
|
||||
secret_string_.clear();
|
||||
secret_string_size_ = plaintext_.size();
|
||||
secret_string_size_ = masked_text_.size();
|
||||
secret_string_.resize(secret_string_size_);
|
||||
ASSERT_EQ(
|
||||
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CTR,
|
||||
@@ -502,8 +548,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) {
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
||||
plaintext_.data(), plaintext_.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_EQ(plaintext_, golden_data_.CTRDecodeKey().content->plaintext);
|
||||
}
|
||||
|
||||
@@ -517,8 +567,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullWhitebox) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -537,7 +587,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidCipherMode) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(),
|
||||
plaintext_.data(), &plaintext_size_),
|
||||
masked_text_.data(), &masked_text_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -551,7 +601,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullKeyId) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(),
|
||||
plaintext_.data(), &plaintext_size_),
|
||||
masked_text_.data(), &masked_text_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -564,8 +614,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullZeroKeyIdSize) {
|
||||
0, golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -578,8 +628,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullInputData) {
|
||||
golden_data_.CBCDecodeKey().id.size(), nullptr,
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -595,8 +645,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest,
|
||||
golden_data_.CBCDecodeKey().id.size(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(), 14,
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -610,8 +660,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForZeroInputDataSize) {
|
||||
golden_data_.CBCDecodeKey().id.size(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(), 0,
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -624,8 +674,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullIV) {
|
||||
golden_data_.CBCDecodeKey().id.size(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(), nullptr,
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -639,8 +689,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidIVSize) {
|
||||
golden_data_.CBCDecodeKey().id.size(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(), 9, plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(), 9,
|
||||
masked_text_.data(), &masked_text_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -655,7 +705,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutput) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), nullptr,
|
||||
&plaintext_size_),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@@ -669,7 +719,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutputSize) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
nullptr),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
@@ -687,7 +737,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForMissingKeyId) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(),
|
||||
plaintext_.data(), &plaintext_size_),
|
||||
masked_text_.data(), &masked_text_size_),
|
||||
WB_RESULT_KEY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@@ -701,7 +751,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForNonContentKey) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(),
|
||||
plaintext_.data(), &plaintext_size_),
|
||||
masked_text_.data(), &masked_text_size_),
|
||||
WB_RESULT_KEY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@@ -719,7 +769,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest,
|
||||
golden_data_.CBCHardwareKey().content->ciphertext.size(),
|
||||
golden_data_.CBCHardwareKey().content->iv.data(),
|
||||
golden_data_.CBCHardwareKey().content->iv.size(),
|
||||
plaintext_.data(), &plaintext_size_),
|
||||
masked_text_.data(), &masked_text_size_),
|
||||
WB_RESULT_INSUFFICIENT_SECURITY_LEVEL);
|
||||
}
|
||||
|
||||
@@ -734,8 +784,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidState) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_INVALID_STATE);
|
||||
}
|
||||
|
||||
@@ -744,7 +794,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, BufferTooSmall) {
|
||||
|
||||
// Our ciphertext will be large enough that we should not need to worry about
|
||||
// using a constant here.
|
||||
plaintext_size_ = 8;
|
||||
masked_text_size_ = 8;
|
||||
|
||||
ASSERT_EQ(
|
||||
WB_License_MaskedDecrypt(
|
||||
@@ -753,14 +803,52 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, BufferTooSmall) {
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
||||
&plaintext_size_),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_BUFFER_TOO_SMALL);
|
||||
|
||||
// We don't use padding so the reported plaintext size should be the same as
|
||||
// the cipher text size.
|
||||
ASSERT_EQ(plaintext_size_,
|
||||
ASSERT_EQ(masked_text_size_,
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size());
|
||||
}
|
||||
|
||||
// Check that the result of unmasking only a small portion of the data is the
|
||||
// same as when we unmask the whole buffer.
|
||||
TEST_F(LicenseWhiteboxMaskedDecryptTest, SuccessForSubRangeUnmask) {
|
||||
LoadLicense(TestLicenseBuilder::NoPadding());
|
||||
|
||||
ASSERT_EQ(
|
||||
WB_License_MaskedDecrypt(
|
||||
whitebox_, WB_CIPHER_MODE_CBC, golden_data_.CBCDecodeKey().id.data(),
|
||||
golden_data_.CBCDecodeKey().id.size(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||
&masked_text_size_),
|
||||
WB_RESULT_OK);
|
||||
|
||||
ASSERT_EQ(
|
||||
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CBC,
|
||||
golden_data_.CBCDecodeKey().id.data(),
|
||||
golden_data_.CBCDecodeKey().id.size(),
|
||||
secret_string_.data(), &secret_string_size_),
|
||||
WB_RESULT_OK);
|
||||
secret_string_.resize(secret_string_size_);
|
||||
|
||||
std::vector<uint8_t> full_unmask(masked_text_size_);
|
||||
std::vector<uint8_t> partial_unmask(3);
|
||||
|
||||
WB_License_Unmask(masked_text_.data(), 0, masked_text_size_,
|
||||
secret_string_.data(), secret_string_.size(),
|
||||
full_unmask.data());
|
||||
WB_License_Unmask(masked_text_.data(), 4, partial_unmask.size(),
|
||||
secret_string_.data(), secret_string_.size(),
|
||||
partial_unmask.data());
|
||||
|
||||
ASSERT_EQ(full_unmask[4], partial_unmask[0]);
|
||||
ASSERT_EQ(full_unmask[5], partial_unmask[1]);
|
||||
ASSERT_EQ(full_unmask[6], partial_unmask[2]);
|
||||
}
|
||||
} // namespace widevine
|
||||
|
||||
133
api/license_whitebox_process_license_response_benchmark.cc
Normal file
133
api/license_whitebox_process_license_response_benchmark.cc
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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 "base/logging.h"
|
||||
#include "benchmarking/measurements.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace widevine {
|
||||
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 = 100;
|
||||
} // namespace
|
||||
class LicenseWhiteboxProcessLicenseResponseBenchmark
|
||||
: public LicenseWhiteboxBenchmark {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
LicenseWhiteboxBenchmark::SetUp();
|
||||
license_ = CreateLicense();
|
||||
}
|
||||
|
||||
void TearDown() override { WB_License_Delete(whitebox_); }
|
||||
|
||||
WB_License_Whitebox* whitebox_;
|
||||
License license_;
|
||||
};
|
||||
|
||||
TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark,
|
||||
CreateAndProcessLicenseResponseAndDelete) {
|
||||
Timer timer;
|
||||
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_ProcessLicenseResponse(
|
||||
whitebox_, license_.message.data(), license_.message.size(),
|
||||
license_.signature.data(), license_.signature.size(),
|
||||
license_.session_key.data(), license_.session_key.size(),
|
||||
license_.request.data(), license_.request.size()),
|
||||
WB_RESULT_OK);
|
||||
|
||||
WB_License_Delete(whitebox_);
|
||||
|
||||
sampler.Push(timer.Get());
|
||||
|
||||
whitebox_ = nullptr;
|
||||
}
|
||||
|
||||
PrettyPrint("License White-box Create + Process License + Delete Duration",
|
||||
sampler, license_.message.size());
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark,
|
||||
CreateAndProcessLicenseResponse) {
|
||||
Timer timer;
|
||||
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_ProcessLicenseResponse(
|
||||
whitebox_, license_.message.data(), license_.message.size(),
|
||||
license_.signature.data(), license_.signature.size(),
|
||||
license_.session_key.data(), license_.session_key.size(),
|
||||
license_.request.data(), license_.request.size()),
|
||||
WB_RESULT_OK);
|
||||
|
||||
sampler.Push(timer.Get());
|
||||
|
||||
WB_License_Delete(whitebox_);
|
||||
whitebox_ = nullptr;
|
||||
}
|
||||
|
||||
PrettyPrint("License White-box Create + Process License Duration", sampler,
|
||||
license_.message.size());
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxProcessLicenseResponseBenchmark, ProcessLicenseResponse) {
|
||||
Timer timer;
|
||||
Sampler sampler;
|
||||
|
||||
for (size_t i = 0; i < kIterations; i++) {
|
||||
// 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);
|
||||
|
||||
timer.Reset();
|
||||
|
||||
ASSERT_EQ(WB_License_ProcessLicenseResponse(
|
||||
whitebox_, license_.message.data(), license_.message.size(),
|
||||
license_.signature.data(), license_.signature.size(),
|
||||
license_.session_key.data(), license_.session_key.size(),
|
||||
license_.request.data(), license_.request.size()),
|
||||
WB_RESULT_OK);
|
||||
|
||||
sampler.Push(timer.Get());
|
||||
|
||||
WB_License_Delete(whitebox_);
|
||||
whitebox_ = nullptr;
|
||||
}
|
||||
|
||||
PrettyPrint("License White-box Process License Duration", sampler,
|
||||
license_.message.size());
|
||||
}
|
||||
} // namespace widevine
|
||||
92
api/license_whitebox_sign_benchmark.cc
Normal file
92
api/license_whitebox_sign_benchmark.cc
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#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 "base/logging.h"
|
||||
#include "benchmarking/data_source.h"
|
||||
#include "benchmarking/measurements.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace widevine {
|
||||
namespace {
|
||||
|
||||
constexpr size_t kMessageSize = 4 * 1024;
|
||||
constexpr size_t kSignatureSize = 256;
|
||||
constexpr size_t kIterations = 100;
|
||||
|
||||
} // namespace
|
||||
|
||||
class LicenseWhiteboxSignBenchmark : public LicenseWhiteboxBenchmark {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
LicenseWhiteboxBenchmark::SetUp();
|
||||
|
||||
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);
|
||||
|
||||
const auto license = CreateLicense();
|
||||
ASSERT_EQ(WB_License_ProcessLicenseResponse(
|
||||
whitebox_, license.message.data(), license.message.size(),
|
||||
license.signature.data(), license.signature.size(),
|
||||
license.session_key.data(), license.session_key.size(),
|
||||
license.request.data(), license.request.size()),
|
||||
WB_RESULT_OK);
|
||||
}
|
||||
|
||||
void TearDown() override { WB_License_Delete(whitebox_); }
|
||||
|
||||
WB_License_Whitebox* whitebox_;
|
||||
|
||||
std::vector<uint8_t> message_;
|
||||
std::vector<uint8_t> signature_;
|
||||
};
|
||||
|
||||
TEST_F(LicenseWhiteboxSignBenchmark, SignLicenseRequest) {
|
||||
Timer timer;
|
||||
Sampler sampler;
|
||||
|
||||
for (size_t i = 0; i < kIterations; i++) {
|
||||
size_t signature_size = signature_.size();
|
||||
|
||||
timer.Reset();
|
||||
ASSERT_EQ(WB_RESULT_OK, WB_License_SignLicenseRequest(
|
||||
whitebox_, message_.data(), message_.size(),
|
||||
signature_.data(), &signature_size));
|
||||
sampler.Push(timer.Get());
|
||||
}
|
||||
|
||||
PrettyPrint("License White-box Sign License Request Duration", sampler,
|
||||
message_.size());
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxSignBenchmark, SignRenewalRequest) {
|
||||
Timer timer;
|
||||
Sampler sampler;
|
||||
|
||||
for (size_t i = 0; i < kIterations; i++) {
|
||||
size_t signature_size = signature_.size();
|
||||
|
||||
timer.Reset();
|
||||
ASSERT_EQ(WB_RESULT_OK, WB_License_SignRenewalRequest(
|
||||
whitebox_, message_.data(), message_.size(),
|
||||
signature_.data(), &signature_size));
|
||||
sampler.Push(timer.Get());
|
||||
}
|
||||
|
||||
PrettyPrint("License White-box Sign Renewal Request Duration", sampler,
|
||||
message_.size());
|
||||
}
|
||||
} // namespace widevine
|
||||
70
api/license_whitebox_verify_benchmark.cc
Normal file
70
api/license_whitebox_verify_benchmark.cc
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#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 "base/logging.h"
|
||||
#include "benchmarking/data_source.h"
|
||||
#include "benchmarking/measurements.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace widevine {
|
||||
namespace {
|
||||
constexpr size_t kMessageSize = 4 * 1024; // 4 KB license response.
|
||||
}
|
||||
|
||||
class LicenseWhiteboxVerifyBenchmark : public LicenseWhiteboxBenchmark {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
LicenseWhiteboxBenchmark::SetUp();
|
||||
|
||||
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);
|
||||
|
||||
const auto license = CreateLicense();
|
||||
ASSERT_EQ(WB_License_ProcessLicenseResponse(
|
||||
whitebox_, license.message.data(), license.message.size(),
|
||||
license.signature.data(), license.signature.size(),
|
||||
license.session_key.data(), license.session_key.size(),
|
||||
license.request.data(), license.request.size()),
|
||||
WB_RESULT_OK);
|
||||
}
|
||||
|
||||
void TearDown() override { WB_License_Delete(whitebox_); }
|
||||
|
||||
WB_License_Whitebox* whitebox_;
|
||||
|
||||
std::vector<uint8_t> message_;
|
||||
std::vector<uint8_t> signature_;
|
||||
};
|
||||
|
||||
TEST_F(LicenseWhiteboxVerifyBenchmark, VerifyRenewalResponse) {
|
||||
constexpr size_t kIterations = 100;
|
||||
|
||||
Timer timer;
|
||||
Sampler sampler;
|
||||
|
||||
for (size_t i = 0; i < kIterations; i++) {
|
||||
timer.Reset();
|
||||
ASSERT_EQ(WB_RESULT_OK, WB_License_VerifyRenewalResponse(
|
||||
whitebox_, message_.data(), message_.size(),
|
||||
signature_.data(), signature_.size()));
|
||||
sampler.Push(timer.Get());
|
||||
}
|
||||
|
||||
PrettyPrint("License White-box Verify Renewal Response Duration", sampler,
|
||||
message_.size());
|
||||
}
|
||||
} // namespace widevine
|
||||
Reference in New Issue
Block a user