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,
|
testonly = True,
|
||||||
srcs = ["test_license_builder.cc"],
|
srcs = ["test_license_builder.cc"],
|
||||||
hdrs = ["test_license_builder.h"],
|
hdrs = ["test_license_builder.h"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//chromium_deps/cdm/keys:dev_certs",
|
"//chromium_deps/cdm/keys:dev_certs",
|
||||||
"//chromium_deps/cdm/protos:license_protocol_proto",
|
"//chromium_deps/cdm/protos:license_protocol_proto",
|
||||||
@@ -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(
|
cc_library(
|
||||||
name = "license_whitebox_test",
|
name = "license_whitebox_test",
|
||||||
testonly = True,
|
testonly = True,
|
||||||
@@ -116,3 +134,29 @@ cc_library(
|
|||||||
"//crypto_utils:rsa_key",
|
"//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,
|
uint8_t* masked_output_data,
|
||||||
size_t* masked_output_data_size);
|
size_t* masked_output_data_size);
|
||||||
|
|
||||||
// Unmasks the data in |buffer| using |secret_string|. |buffer| is operated on
|
// Unmasks a subset of the data in |masked_data| using |secret_string| and
|
||||||
// in-place.
|
// 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:
|
// 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|.
|
// 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 (out) : The output buffer to write the unmasked data to.
|
||||||
// unmasked data. The number of bytes in the masked data will be equal to the
|
void WB_License_Unmask(const uint8_t* masked_data,
|
||||||
// number of bytes in the unmasked data.
|
size_t offset,
|
||||||
//
|
size_t size,
|
||||||
// buffer_size (in) : The number of bytes in |buffer|.
|
const uint8_t* secret_string,
|
||||||
void WB_License_Unmask(const uint8_t* secret_string,
|
|
||||||
size_t secret_string_size,
|
size_t secret_string_size,
|
||||||
uint8_t* buffer,
|
uint8_t* unmasked_data);
|
||||||
size_t buffer_size);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#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
|
// Because we are going to use the same buffer for both tests, make sure it
|
||||||
// will be large enough for either.
|
// will be large enough for either.
|
||||||
plaintext_size_ = std::max(golden_data_.CBCContent().ciphertext.size(),
|
masked_text_size_ = std::max(golden_data_.CBCContent().ciphertext.size(),
|
||||||
golden_data_.CTRContent().ciphertext.size());
|
golden_data_.CTRContent().ciphertext.size());
|
||||||
plaintext_.resize(plaintext_size_);
|
masked_text_.resize(masked_text_size_);
|
||||||
|
|
||||||
// We have no idea how big the secret string will be, but it should be safe
|
// 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.
|
// 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_);
|
secret_string_.resize(secret_string_size_);
|
||||||
|
|
||||||
golden_data_.MakeKeyIdDifferent(&non_content_key_id_);
|
golden_data_.MakeKeyIdDifferent(&non_content_key_id_);
|
||||||
@@ -82,7 +82,9 @@ class LicenseWhiteboxMaskedDecryptTest : public LicenseWhiteboxTestBase {
|
|||||||
size_t secret_string_size_;
|
size_t secret_string_size_;
|
||||||
std::vector<uint8_t> secret_string_;
|
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_;
|
std::vector<uint8_t> plaintext_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -96,16 +98,16 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCbcMode) {
|
|||||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
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
|
// Returned data is masked, so it should be the correct size but not
|
||||||
// match the original text.
|
// match the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CBCDecodeKey().content->plaintext.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.
|
// Now unmask the data.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -115,8 +117,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCbcMode) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
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);
|
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.data(),
|
||||||
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CTRDecodeKey().content->iv.data(),
|
golden_data_.CTRDecodeKey().content->iv.data(),
|
||||||
golden_data_.CTRDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CTRDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
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
|
// Returned data is masked, so it should be the correct size but not
|
||||||
// match the original text.
|
// match the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CTRDecodeKey().content->plaintext.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.
|
// Now unmask the data.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -149,8 +155,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCtrMode) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
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);
|
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.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
plaintext_.resize(plaintext_size_);
|
masked_text_.resize(masked_text_size_);
|
||||||
|
|
||||||
// Whatever is returned must not be the original text.
|
// Whatever is returned must not be the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CBCDecodeKey().content->plaintext.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.
|
// Now unmask the data. Still should not match.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -184,9 +194,13 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCtrMode) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
secret_string_.resize(secret_string_size_);
|
||||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
|
||||||
plaintext_.data(), plaintext_.size());
|
plaintext_.resize(masked_text_size_);
|
||||||
ASSERT_NE(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
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
|
// 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.data(),
|
||||||
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CTRDecodeKey().content->iv.data(),
|
golden_data_.CTRDecodeKey().content->iv.data(),
|
||||||
golden_data_.CTRDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CTRDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
plaintext_.resize(plaintext_size_);
|
masked_text_.resize(masked_text_size_);
|
||||||
|
|
||||||
// Whatever is returned must not be the original text.
|
// Whatever is returned must not be the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CTRDecodeKey().content->plaintext.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.
|
// Now unmask the data. Still should not match.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -219,9 +233,13 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCbcMode) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
secret_string_.resize(secret_string_size_);
|
||||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
|
||||||
plaintext_.data(), plaintext_.size());
|
plaintext_.resize(masked_text_size_);
|
||||||
ASSERT_NE(plaintext_, golden_data_.CTRDecodeKey().content->plaintext);
|
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) {
|
TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
|
||||||
@@ -234,16 +252,16 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
|
|||||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
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
|
// Returned data is masked, so it should be the correct size but not
|
||||||
// match the original text.
|
// match the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CBCDecodeKey().content->plaintext.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.
|
// Now unmask the data.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -253,8 +271,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
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);
|
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.data(),
|
||||||
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CTRDecodeKey().content->iv.data(),
|
golden_data_.CTRDecodeKey().content->iv.data(),
|
||||||
golden_data_.CTRDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CTRDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
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
|
// Returned data is masked, so it should be the correct size but not
|
||||||
// match the original text.
|
// match the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CTRDecodeKey().content->plaintext.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.
|
// Now unmask the data.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -287,8 +309,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCtrMode) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
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);
|
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.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
plaintext_.resize(plaintext_size_);
|
masked_text_.resize(masked_text_size_);
|
||||||
|
|
||||||
// Whatever is returned must not be the original text.
|
// Whatever is returned must not be the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CBCDecodeKey().content->plaintext.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.
|
// Now unmask the data. Still should not match.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -322,9 +348,13 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCtrMode) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
secret_string_.resize(secret_string_size_);
|
||||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
|
||||||
plaintext_.data(), plaintext_.size());
|
plaintext_.resize(masked_text_size_);
|
||||||
ASSERT_NE(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
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
|
// 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.data(),
|
||||||
golden_data_.CTRCryptoKey().content->ciphertext.size(),
|
golden_data_.CTRCryptoKey().content->ciphertext.size(),
|
||||||
golden_data_.CTRCryptoKey().content->iv.data(),
|
golden_data_.CTRCryptoKey().content->iv.data(),
|
||||||
golden_data_.CTRCryptoKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CTRCryptoKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
plaintext_.resize(plaintext_size_);
|
masked_text_.resize(masked_text_size_);
|
||||||
|
|
||||||
// Whatever is returned must not be the original text.
|
// Whatever is returned must not be the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CTRCryptoKey().content->plaintext.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.
|
// Now unmask the data. Still should not match.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -357,9 +387,13 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCbcMode) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
secret_string_.resize(secret_string_size_);
|
||||||
WB_License_Unmask(secret_string_.data(), secret_string_.size(),
|
|
||||||
plaintext_.data(), plaintext_.size());
|
plaintext_.resize(masked_text_size_);
|
||||||
ASSERT_NE(plaintext_, golden_data_.CTRCryptoKey().content->plaintext);
|
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) {
|
TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) {
|
||||||
@@ -372,16 +406,16 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) {
|
|||||||
golden_data_.CBCCryptoKey().content->ciphertext.data(),
|
golden_data_.CBCCryptoKey().content->ciphertext.data(),
|
||||||
golden_data_.CBCCryptoKey().content->ciphertext.size(),
|
golden_data_.CBCCryptoKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCCryptoKey().content->iv.data(),
|
golden_data_.CBCCryptoKey().content->iv.data(),
|
||||||
golden_data_.CBCCryptoKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCCryptoKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
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
|
// Returned data is masked, so it should be the correct size but not
|
||||||
// match the original text.
|
// match the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CBCCryptoKey().content->plaintext.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.
|
// Now unmask the data.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -391,8 +425,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
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);
|
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.data(),
|
||||||
golden_data_.CTRCryptoKey().content->ciphertext.size(),
|
golden_data_.CTRCryptoKey().content->ciphertext.size(),
|
||||||
golden_data_.CTRCryptoKey().content->iv.data(),
|
golden_data_.CTRCryptoKey().content->iv.data(),
|
||||||
golden_data_.CTRCryptoKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CTRCryptoKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
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
|
// Returned data is masked, so it should be the correct size but not
|
||||||
// match the original text.
|
// match the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CTRCryptoKey().content->plaintext.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.
|
// Now unmask the data.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -425,8 +463,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataAndPKCS8Padding) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
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);
|
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.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
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
|
// Returned data is masked, so it should be the correct size but not
|
||||||
// match the original text.
|
// match the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CBCDecodeKey().content->plaintext.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.
|
// Now unmask the data.
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
@@ -464,14 +506,18 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
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);
|
ASSERT_EQ(plaintext_, golden_data_.CBCDecodeKey().content->plaintext);
|
||||||
|
|
||||||
// Reset our output buffer.
|
// Reset our output buffer.
|
||||||
plaintext_.clear();
|
masked_text_.clear();
|
||||||
plaintext_size_ = golden_data_.CTRDecodeKey().content->plaintext.size();
|
masked_text_size_ = golden_data_.CTRDecodeKey().content->plaintext.size();
|
||||||
plaintext_.resize(plaintext_size_);
|
masked_text_.resize(masked_text_size_);
|
||||||
|
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
WB_License_MaskedDecrypt(
|
WB_License_MaskedDecrypt(
|
||||||
@@ -480,20 +526,20 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) {
|
|||||||
golden_data_.CTRDecodeKey().content->ciphertext.data(),
|
golden_data_.CTRDecodeKey().content->ciphertext.data(),
|
||||||
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
golden_data_.CTRDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CTRDecodeKey().content->iv.data(),
|
golden_data_.CTRDecodeKey().content->iv.data(),
|
||||||
golden_data_.CTRDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CTRDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_OK);
|
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
|
// Returned data is masked, so it should be the correct size but not
|
||||||
// match the original text.
|
// match the original text.
|
||||||
ASSERT_EQ(plaintext_.size(),
|
ASSERT_EQ(masked_text_.size(),
|
||||||
golden_data_.CTRDecodeKey().content->plaintext.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.
|
// Now unmask the data.
|
||||||
secret_string_.clear();
|
secret_string_.clear();
|
||||||
secret_string_size_ = plaintext_.size();
|
secret_string_size_ = masked_text_.size();
|
||||||
secret_string_.resize(secret_string_size_);
|
secret_string_.resize(secret_string_size_);
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CTR,
|
WB_License_GetSecretString(whitebox_, WB_CIPHER_MODE_CTR,
|
||||||
@@ -502,8 +548,12 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) {
|
|||||||
secret_string_.data(), &secret_string_size_),
|
secret_string_.data(), &secret_string_size_),
|
||||||
WB_RESULT_OK);
|
WB_RESULT_OK);
|
||||||
secret_string_.resize(secret_string_size_);
|
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);
|
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.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,7 +587,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidCipherMode) {
|
|||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(),
|
golden_data_.CBCDecodeKey().content->iv.size(),
|
||||||
plaintext_.data(), &plaintext_size_),
|
masked_text_.data(), &masked_text_size_),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,7 +601,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullKeyId) {
|
|||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(),
|
golden_data_.CBCDecodeKey().content->iv.size(),
|
||||||
plaintext_.data(), &plaintext_size_),
|
masked_text_.data(), &masked_text_size_),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,8 +614,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullZeroKeyIdSize) {
|
|||||||
0, golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
0, golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,8 +628,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullInputData) {
|
|||||||
golden_data_.CBCDecodeKey().id.size(), nullptr,
|
golden_data_.CBCDecodeKey().id.size(), nullptr,
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,8 +645,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest,
|
|||||||
golden_data_.CBCDecodeKey().id.size(),
|
golden_data_.CBCDecodeKey().id.size(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.data(), 14,
|
golden_data_.CBCDecodeKey().content->ciphertext.data(), 14,
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,8 +660,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForZeroInputDataSize) {
|
|||||||
golden_data_.CBCDecodeKey().id.size(),
|
golden_data_.CBCDecodeKey().id.size(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.data(), 0,
|
golden_data_.CBCDecodeKey().content->ciphertext.data(), 0,
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,8 +674,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullIV) {
|
|||||||
golden_data_.CBCDecodeKey().id.size(),
|
golden_data_.CBCDecodeKey().id.size(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(), nullptr,
|
golden_data_.CBCDecodeKey().content->ciphertext.size(), nullptr,
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,8 +689,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidIVSize) {
|
|||||||
golden_data_.CBCDecodeKey().id.size(),
|
golden_data_.CBCDecodeKey().id.size(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(), 9, plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(), 9,
|
||||||
&plaintext_size_),
|
masked_text_.data(), &masked_text_size_),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -655,7 +705,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutput) {
|
|||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), nullptr,
|
golden_data_.CBCDecodeKey().content->iv.size(), nullptr,
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -669,7 +719,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutputSize) {
|
|||||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
nullptr),
|
nullptr),
|
||||||
WB_RESULT_INVALID_PARAMETER);
|
WB_RESULT_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
@@ -687,7 +737,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForMissingKeyId) {
|
|||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(),
|
golden_data_.CBCDecodeKey().content->iv.size(),
|
||||||
plaintext_.data(), &plaintext_size_),
|
masked_text_.data(), &masked_text_size_),
|
||||||
WB_RESULT_KEY_UNAVAILABLE);
|
WB_RESULT_KEY_UNAVAILABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,7 +751,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForNonContentKey) {
|
|||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(),
|
golden_data_.CBCDecodeKey().content->iv.size(),
|
||||||
plaintext_.data(), &plaintext_size_),
|
masked_text_.data(), &masked_text_size_),
|
||||||
WB_RESULT_KEY_UNAVAILABLE);
|
WB_RESULT_KEY_UNAVAILABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,7 +769,7 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest,
|
|||||||
golden_data_.CBCHardwareKey().content->ciphertext.size(),
|
golden_data_.CBCHardwareKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCHardwareKey().content->iv.data(),
|
golden_data_.CBCHardwareKey().content->iv.data(),
|
||||||
golden_data_.CBCHardwareKey().content->iv.size(),
|
golden_data_.CBCHardwareKey().content->iv.size(),
|
||||||
plaintext_.data(), &plaintext_size_),
|
masked_text_.data(), &masked_text_size_),
|
||||||
WB_RESULT_INSUFFICIENT_SECURITY_LEVEL);
|
WB_RESULT_INSUFFICIENT_SECURITY_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,8 +784,8 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, InvalidState) {
|
|||||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_INVALID_STATE);
|
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
|
// Our ciphertext will be large enough that we should not need to worry about
|
||||||
// using a constant here.
|
// using a constant here.
|
||||||
plaintext_size_ = 8;
|
masked_text_size_ = 8;
|
||||||
|
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
WB_License_MaskedDecrypt(
|
WB_License_MaskedDecrypt(
|
||||||
@@ -753,14 +803,52 @@ TEST_F(LicenseWhiteboxMaskedDecryptTest, BufferTooSmall) {
|
|||||||
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
golden_data_.CBCDecodeKey().content->ciphertext.data(),
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
golden_data_.CBCDecodeKey().content->ciphertext.size(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.data(),
|
golden_data_.CBCDecodeKey().content->iv.data(),
|
||||||
golden_data_.CBCDecodeKey().content->iv.size(), plaintext_.data(),
|
golden_data_.CBCDecodeKey().content->iv.size(), masked_text_.data(),
|
||||||
&plaintext_size_),
|
&masked_text_size_),
|
||||||
WB_RESULT_BUFFER_TOO_SMALL);
|
WB_RESULT_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
// We don't use padding so the reported plaintext size should be the same as
|
// We don't use padding so the reported plaintext size should be the same as
|
||||||
// the cipher text size.
|
// the cipher text size.
|
||||||
ASSERT_EQ(plaintext_size_,
|
ASSERT_EQ(masked_text_size_,
|
||||||
golden_data_.CBCDecodeKey().content->ciphertext.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
|
} // 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
|
||||||
30
benchmarking/BUILD
Normal file
30
benchmarking/BUILD
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Copyright 2020 Google LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
package(default_visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
])
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "data_source",
|
||||||
|
testonly = True,
|
||||||
|
srcs = [
|
||||||
|
"data_source.cc",
|
||||||
|
],
|
||||||
|
hdrs = [
|
||||||
|
"data_source.h",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "measurements",
|
||||||
|
testonly = True,
|
||||||
|
srcs = [
|
||||||
|
"measurements.cc",
|
||||||
|
],
|
||||||
|
hdrs = [
|
||||||
|
"measurements.h",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//chromium_deps/base:glog",
|
||||||
|
],
|
||||||
|
)
|
||||||
467
benchmarking/data_source.cc
Normal file
467
benchmarking/data_source.cc
Normal file
@@ -0,0 +1,467 @@
|
|||||||
|
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "benchmarking/data_source.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring> // memcpy
|
||||||
|
|
||||||
|
namespace widevine {
|
||||||
|
namespace {
|
||||||
|
const uint8_t kGoldenData[] = {
|
||||||
|
0x91, 0x08, 0xed, 0x18, 0xe2, 0x8f, 0x22, 0x85, 0x9f, 0x7b, 0x07, 0xdd,
|
||||||
|
0xd3, 0x37, 0x09, 0xca, 0x53, 0x94, 0x37, 0xcd, 0x09, 0xff, 0x52, 0x77,
|
||||||
|
0xf0, 0xa5, 0x98, 0x07, 0x65, 0x25, 0x0a, 0x5a, 0x5a, 0xea, 0xfd, 0x24,
|
||||||
|
0xb0, 0xce, 0xa9, 0xb4, 0x64, 0x4e, 0x1f, 0x00, 0xa6, 0xb8, 0xf1, 0x3b,
|
||||||
|
0xc0, 0x5a, 0xa4, 0xe8, 0xb0, 0x32, 0x07, 0xff, 0x73, 0xcc, 0xc7, 0xd1,
|
||||||
|
0xfa, 0x2c, 0xb4, 0x43, 0x4a, 0xb4, 0xae, 0x91, 0xee, 0xb5, 0x6b, 0xce,
|
||||||
|
0xf6, 0x90, 0xb0, 0x22, 0x0b, 0xe7, 0x98, 0x77, 0xfe, 0x78, 0x68, 0xfd,
|
||||||
|
0x0e, 0xae, 0xf5, 0x1d, 0x37, 0xb8, 0x34, 0xf3, 0xca, 0xb5, 0x66, 0xba,
|
||||||
|
0xa2, 0x13, 0xdc, 0x4c, 0xb5, 0x13, 0x79, 0x9c, 0x55, 0xeb, 0x9f, 0x68,
|
||||||
|
0xd4, 0xfc, 0x0d, 0x41, 0x38, 0x3f, 0xca, 0x02, 0xe8, 0x22, 0xbf, 0xc1,
|
||||||
|
0xb0, 0x0a, 0xaf, 0x73, 0x9e, 0x9f, 0xee, 0xad, 0xa8, 0x10, 0x03, 0x32,
|
||||||
|
0xa8, 0x5c, 0x0c, 0x01, 0x64, 0xae, 0x01, 0x44, 0x10, 0x44, 0x79, 0x13,
|
||||||
|
0x30, 0x3b, 0xa9, 0xa5, 0xb5, 0x20, 0x2b, 0xfa, 0x1b, 0xa0, 0x85, 0x90,
|
||||||
|
0xfc, 0xef, 0xff, 0x19, 0xcb, 0x18, 0x0e, 0xc2, 0xdf, 0xfa, 0xd2, 0xf2,
|
||||||
|
0x6e, 0xd7, 0x4a, 0x36, 0xdc, 0xa9, 0x55, 0x67, 0x08, 0x68, 0x19, 0xbd,
|
||||||
|
0x47, 0x4e, 0xeb, 0x1a, 0x24, 0x05, 0x0e, 0xb9, 0x04, 0x01, 0xaf, 0xf0,
|
||||||
|
0x89, 0xa4, 0xc8, 0x2a, 0xa5, 0xf4, 0xd3, 0x67, 0x00, 0xbc, 0xe6, 0x6c,
|
||||||
|
0x32, 0x50, 0x15, 0x7f, 0x7e, 0xd6, 0x31, 0x9e, 0xc0, 0x43, 0x87, 0xa9,
|
||||||
|
0x29, 0x28, 0x50, 0x3e, 0xd3, 0x47, 0x10, 0xbf, 0xfa, 0x83, 0x20, 0x42,
|
||||||
|
0x6f, 0x72, 0xac, 0xbc, 0x81, 0xc8, 0xf6, 0xcc, 0x1f, 0xa7, 0xfe, 0x1d,
|
||||||
|
0xf7, 0x11, 0xe5, 0xe6, 0x6e, 0x9e, 0x38, 0x9e, 0xdd, 0x3b, 0x4b, 0x3d,
|
||||||
|
0x99, 0x23, 0xe1, 0xc4, 0xe1, 0x93, 0xde, 0x1a, 0x4f, 0xa1, 0x4c, 0xd4,
|
||||||
|
0x3f, 0xbe, 0x25, 0x37, 0xdd, 0x6f, 0xf3, 0xd4, 0x02, 0xa4, 0x5b, 0x86,
|
||||||
|
0xf7, 0xea, 0x97, 0x41, 0x67, 0x83, 0xad, 0x61, 0xe4, 0x2a, 0x01, 0x29,
|
||||||
|
0x6e, 0xdc, 0xe8, 0x73, 0x7d, 0xea, 0x22, 0xd4, 0xfb, 0xe5, 0x5e, 0x56,
|
||||||
|
0x1a, 0x32, 0x9f, 0x98, 0x20, 0x44, 0x67, 0x4e, 0x22, 0x51, 0xd5, 0x43,
|
||||||
|
0xbe, 0xb1, 0x65, 0x11, 0x13, 0x08, 0xfd, 0xad, 0x8b, 0xcb, 0x26, 0x2b,
|
||||||
|
0xee, 0x1e, 0x12, 0xe6, 0x2c, 0xe8, 0xe1, 0x81, 0x6a, 0x14, 0xf1, 0x45,
|
||||||
|
0x8f, 0x74, 0x94, 0x53, 0xd2, 0x3f, 0x01, 0x3d, 0x07, 0x34, 0xbc, 0xc1,
|
||||||
|
0x25, 0x32, 0x1d, 0x60, 0x8c, 0x15, 0xb1, 0x1a, 0xd1, 0x17, 0x04, 0x18,
|
||||||
|
0xfa, 0xdd, 0x48, 0x0f, 0xd3, 0xf9, 0xf4, 0x1f, 0x32, 0xb6, 0xd0, 0xa9,
|
||||||
|
0x66, 0x61, 0x40, 0x4d, 0x1a, 0xe1, 0xe4, 0x70, 0x6e, 0x04, 0x94, 0xd6,
|
||||||
|
0xc8, 0xa4, 0x43, 0x57, 0x2a, 0x19, 0x16, 0xfc, 0x56, 0x79, 0x2c, 0x3a,
|
||||||
|
0x8b, 0xf3, 0xad, 0x7b, 0x4f, 0xf8, 0xc5, 0x4d, 0x14, 0x13, 0x8a, 0xbd,
|
||||||
|
0x5e, 0xef, 0xdd, 0x79, 0x31, 0xdf, 0x65, 0xe1, 0x62, 0x92, 0x99, 0xf6,
|
||||||
|
0x1a, 0xd5, 0x18, 0x24, 0xb5, 0x27, 0x22, 0xb2, 0x1a, 0x2c, 0xab, 0x02,
|
||||||
|
0x7a, 0x47, 0xb4, 0xd6, 0x8b, 0x26, 0xb3, 0x5d, 0x9b, 0xf9, 0x87, 0x78,
|
||||||
|
0x5e, 0x8e, 0xaa, 0x7d, 0x0d, 0x8c, 0x7c, 0xf7, 0xbc, 0x4c, 0x9b, 0xad,
|
||||||
|
0x53, 0x8a, 0xdc, 0x50, 0xf5, 0x01, 0xcb, 0x74, 0x98, 0x83, 0x45, 0x41,
|
||||||
|
0x78, 0xf3, 0x00, 0x55, 0xb7, 0xd0, 0xdf, 0xff, 0xd3, 0xd9, 0xa1, 0xcc,
|
||||||
|
0xa1, 0xe8, 0x98, 0x33, 0x10, 0xcf, 0x8f, 0xcf, 0x5c, 0x3e, 0x50, 0xd6,
|
||||||
|
0xdc, 0xf9, 0x70, 0x9f, 0x7e, 0xc4, 0x1b, 0x87, 0x90, 0xbd, 0xb7, 0x2a,
|
||||||
|
0xb7, 0x91, 0x06, 0x1c, 0xad, 0x6c, 0xce, 0x60, 0x84, 0x51, 0xc4, 0x87,
|
||||||
|
0xf4, 0x46, 0x87, 0x9e, 0x72, 0x0d, 0x91, 0xe9, 0x69, 0xbf, 0xa3, 0x87,
|
||||||
|
0x6f, 0x24, 0xf9, 0x24, 0x75, 0xac, 0x7d, 0x36, 0x55, 0x85, 0x50, 0x23,
|
||||||
|
0x48, 0xb9, 0x74, 0xd3, 0xb7, 0x79, 0x70, 0xcf, 0x13, 0xee, 0x1d, 0x0f,
|
||||||
|
0xd9, 0x03, 0xe7, 0xdc, 0x4a, 0x3b, 0x06, 0x50, 0x7f, 0x1a, 0x37, 0x8e,
|
||||||
|
0xdd, 0xd4, 0x6f, 0xc7, 0xd2, 0x13, 0x8b, 0x00, 0xd0, 0x83, 0xe6, 0x15,
|
||||||
|
0x0f, 0x6b, 0x42, 0x65, 0xdb, 0xcd, 0x20, 0x8f, 0xdc, 0x3b, 0x0d, 0x32,
|
||||||
|
0x6a, 0x11, 0x18, 0x08, 0xf6, 0x3e, 0x4c, 0xdc, 0x9f, 0x5f, 0x45, 0xdf,
|
||||||
|
0xf4, 0x28, 0xbc, 0xd6, 0xb8, 0x53, 0x86, 0xe8, 0xfd, 0xa0, 0x68, 0x4e,
|
||||||
|
0x26, 0xba, 0x80, 0x93, 0x1d, 0x62, 0x2f, 0x4d, 0x2d, 0xf1, 0x65, 0xcf,
|
||||||
|
0xda, 0xbc, 0x32, 0xfb, 0xaf, 0x0b, 0xa0, 0x24, 0xe1, 0xdd, 0x94, 0x64,
|
||||||
|
0x0e, 0xb7, 0xf5, 0x04, 0xaf, 0x20, 0xf4, 0xaf, 0x8a, 0x67, 0xe6, 0x47,
|
||||||
|
0xc9, 0xb2, 0x25, 0x8b, 0x2c, 0xa1, 0xa8, 0x80, 0xa4, 0x70, 0xb9, 0xbe,
|
||||||
|
0xb9, 0x0b, 0x98, 0xbf, 0x62, 0xad, 0xdc, 0x73, 0x38, 0x0d, 0x74, 0xc4,
|
||||||
|
0x1b, 0xd5, 0xad, 0x6e, 0x50, 0x94, 0x46, 0xcd, 0xcf, 0x9a, 0x53, 0x04,
|
||||||
|
0x18, 0x40, 0xe9, 0xad, 0x92, 0x09, 0xd7, 0x6e, 0x16, 0x9c, 0xcf, 0xce,
|
||||||
|
0x20, 0xd6, 0x2a, 0xbc, 0x84, 0xbf, 0x33, 0xd0, 0x3f, 0x49, 0xa0, 0x66,
|
||||||
|
0x8c, 0xdf, 0xc7, 0x1f, 0xf7, 0x7c, 0xfa, 0xd3, 0xef, 0x8c, 0x51, 0x13,
|
||||||
|
0x6b, 0xe5, 0x3d, 0x80, 0x15, 0x11, 0x25, 0x2d, 0xe4, 0x23, 0xe1, 0xd9,
|
||||||
|
0xfe, 0x69, 0x81, 0xd0, 0x01, 0xc6, 0x41, 0xa1, 0xcf, 0x73, 0x5f, 0xca,
|
||||||
|
0x3c, 0xe9, 0x59, 0x25, 0x07, 0x97, 0x60, 0xda, 0xc4, 0x57, 0x98, 0x51,
|
||||||
|
0xd7, 0x30, 0xa5, 0x39, 0x7c, 0x0b, 0x65, 0xb2, 0x41, 0x03, 0xf5, 0x99,
|
||||||
|
0x1e, 0x0a, 0xc4, 0x2a, 0x14, 0x4e, 0x00, 0xf0, 0x27, 0xa7, 0xe6, 0x73,
|
||||||
|
0x15, 0xf6, 0x3d, 0x21, 0xc7, 0xeb, 0x53, 0xa7, 0x9b, 0x61, 0xdc, 0x0a,
|
||||||
|
0xcf, 0x0b, 0x6c, 0xbe, 0xb5, 0x77, 0xb3, 0xbc, 0xe6, 0x29, 0x9e, 0x09,
|
||||||
|
0x8d, 0x91, 0xde, 0xde, 0xb7, 0xd2, 0x18, 0x89, 0xc0, 0xf0, 0x79, 0xfd,
|
||||||
|
0xa6, 0xe4, 0xc1, 0x53, 0x04, 0x08, 0xdb, 0x0e, 0x97, 0xda, 0x1e, 0xcd,
|
||||||
|
0x1a, 0x63, 0x65, 0x24, 0xc2, 0x01, 0x1b, 0x6a, 0xae, 0xb5, 0x56, 0xa8,
|
||||||
|
0x94, 0xc5, 0x37, 0xb0, 0x2e, 0x69, 0xb0, 0xb9, 0x90, 0xe3, 0xb9, 0x2e,
|
||||||
|
0x03, 0xad, 0xe2, 0xc5, 0x1e, 0x36, 0x2e, 0xa9, 0xa8, 0xbe, 0xf0, 0xc6,
|
||||||
|
0xa8, 0x64, 0xb6, 0xb9, 0x9d, 0x25, 0xf1, 0x06, 0x28, 0xf9, 0x6e, 0x3a,
|
||||||
|
0x4e, 0x23, 0xcd, 0x32, 0x79, 0xa3, 0x19, 0x4a, 0x36, 0x8a, 0xfd, 0x81,
|
||||||
|
0x8c, 0x0e, 0x4e, 0xd0, 0x6c, 0x06, 0xf7, 0x2f, 0x8d, 0x19, 0x90, 0x47,
|
||||||
|
0x76, 0x7c, 0x7a, 0xb0, 0x26, 0x85, 0xaa, 0xfc, 0x3b, 0x03, 0xb7, 0x4c,
|
||||||
|
0xdd, 0xfb, 0xa9, 0x6c, 0x8c, 0x35, 0x88, 0xd9, 0x41, 0xf5, 0xd7, 0x74,
|
||||||
|
0x30, 0xea, 0xa5, 0xb1, 0xf5, 0x08, 0xeb, 0x29, 0x72, 0x1c, 0x18, 0x5f,
|
||||||
|
0xf6, 0x7e, 0x5b, 0x1b, 0xc1, 0x40, 0xa7, 0x4f, 0xf2, 0x87, 0x61, 0xca,
|
||||||
|
0xcd, 0x9a, 0x94, 0xa8, 0xce, 0x33, 0x1d, 0xa4, 0x07, 0x67, 0xb6, 0x37,
|
||||||
|
0xf4, 0xd0, 0x34, 0xa0, 0x4b, 0x5c, 0x7f, 0xc2, 0x06, 0xaa, 0x6d, 0x23,
|
||||||
|
0xb8, 0x68, 0xc5, 0xe7, 0x3b, 0xd5, 0x10, 0xce, 0x36, 0x07, 0x60, 0x7f,
|
||||||
|
0xbb, 0xc0, 0x5b, 0xd2, 0x9f, 0x96, 0x31, 0x67, 0x6c, 0x30, 0x55, 0x88,
|
||||||
|
0xd3, 0xf0, 0xfe, 0x5e, 0x2f, 0x96, 0x90, 0xcc, 0xfa, 0xe4, 0x08, 0x6e,
|
||||||
|
0xd4, 0xa1, 0x4a, 0x52, 0xf9, 0x8b, 0xf5, 0x3a, 0x92, 0xae, 0x90, 0x7b,
|
||||||
|
0xf1, 0xc0, 0x2f, 0xb1, 0xe1, 0x3a, 0x05, 0x60, 0x62, 0x81, 0xd1, 0xaa,
|
||||||
|
0x47, 0xb9, 0x44, 0x35, 0x6e, 0x77, 0x0b, 0x55, 0x37, 0x31, 0x02, 0xde,
|
||||||
|
0xfd, 0xa7, 0x25, 0x4a, 0x61, 0x24, 0x8b, 0x0d, 0x68, 0x77, 0x66, 0x31,
|
||||||
|
0xa9, 0xf4, 0x07, 0x6b, 0x59, 0x51, 0x5a, 0x79, 0x11, 0x2c, 0x45, 0x92,
|
||||||
|
0xb4, 0x96, 0xe9, 0x7a, 0x1e, 0x0a, 0xf2, 0xd1, 0x74, 0x1e, 0xbb, 0x16,
|
||||||
|
0x62, 0xd3, 0x20, 0x59, 0x9d, 0x63, 0xd3, 0xa0, 0x36, 0x86, 0xcc, 0xa2,
|
||||||
|
0xe3, 0x40, 0xdc, 0x65, 0x6b, 0x2d, 0x72, 0xeb, 0x3e, 0x12, 0x71, 0x5a,
|
||||||
|
0x8d, 0xab, 0xa8, 0xb6, 0x7e, 0x7f, 0x37, 0xf7, 0x12, 0x00, 0xc4, 0xfe,
|
||||||
|
0xa6, 0xd6, 0xf9, 0xde, 0x4f, 0x43, 0xd2, 0x06, 0x19, 0x70, 0x14, 0x88,
|
||||||
|
0xe9, 0x69, 0xf5, 0xd1, 0x83, 0x9b, 0x1d, 0x8c, 0x64, 0xd1, 0xa0, 0x3e,
|
||||||
|
0x11, 0x85, 0x93, 0x9f, 0xf7, 0xaa, 0x43, 0x5d, 0x9f, 0x91, 0x50, 0xbb,
|
||||||
|
0xe4, 0x0e, 0xba, 0x12, 0x22, 0xc5, 0x9e, 0x93, 0xd7, 0x5c, 0x74, 0xb5,
|
||||||
|
0x63, 0xaf, 0xf1, 0xae, 0xf6, 0xaf, 0x9a, 0xf4, 0xb4, 0x9f, 0x4d, 0x64,
|
||||||
|
0x6a, 0xc7, 0x5f, 0xcb, 0x95, 0x5c, 0xc9, 0x62, 0x85, 0x52, 0xb7, 0x58,
|
||||||
|
0xdd, 0x75, 0x18, 0xf9, 0xfc, 0xf8, 0xe4, 0x82, 0x3b, 0xc3, 0x12, 0x0e,
|
||||||
|
0x9c, 0xef, 0xa8, 0x2a, 0xd1, 0xf8, 0xc6, 0x53, 0x59, 0xac, 0x69, 0x87,
|
||||||
|
0x1b, 0xf6, 0xd2, 0x06, 0x4e, 0x9e, 0x25, 0x0c, 0x0e, 0xc3, 0x66, 0x73,
|
||||||
|
0x00, 0xda, 0x3f, 0xc5, 0x12, 0xed, 0x8d, 0x43, 0xbf, 0x78, 0x7c, 0xa4,
|
||||||
|
0xc2, 0x96, 0x8e, 0x15, 0x27, 0x38, 0xbd, 0xc7, 0x05, 0xd6, 0xdd, 0x3a,
|
||||||
|
0x5f, 0xdd, 0xcd, 0x22, 0x9b, 0x19, 0x57, 0x95, 0x2f, 0x51, 0x2a, 0xf9,
|
||||||
|
0xb5, 0x21, 0x85, 0x26, 0x2c, 0x5f, 0x5b, 0x9c, 0xff, 0x70, 0x9a, 0x78,
|
||||||
|
0xc2, 0x86, 0x5a, 0xe3, 0x23, 0x30, 0xd7, 0xb0, 0xf7, 0x28, 0xf6, 0xbb,
|
||||||
|
0x81, 0x85, 0x17, 0x46, 0x22, 0xfa, 0xb9, 0xff, 0x8e, 0x4c, 0xca, 0x58,
|
||||||
|
0x25, 0x8b, 0xa3, 0x3e, 0xa4, 0xd8, 0xe4, 0x4b, 0x2e, 0x65, 0x80, 0x55,
|
||||||
|
0xe5, 0x1f, 0x84, 0x13, 0xdf, 0x78, 0x65, 0xce, 0x91, 0x07, 0x6e, 0xe7,
|
||||||
|
0x59, 0x79, 0x5c, 0x84, 0xf2, 0x38, 0xb4, 0x80, 0xca, 0x71, 0xfe, 0x80,
|
||||||
|
0xf6, 0x80, 0x09, 0x31, 0x5b, 0xd2, 0xbb, 0x98, 0xcc, 0x27, 0x4e, 0xe2,
|
||||||
|
0x34, 0x13, 0xd6, 0x79, 0xdf, 0xc0, 0x6e, 0x91, 0xbf, 0xb4, 0x67, 0x49,
|
||||||
|
0x73, 0x0c, 0x0b, 0xd3, 0x7d, 0x31, 0x01, 0x3b, 0x68, 0xd4, 0x2e, 0x35,
|
||||||
|
0x09, 0x94, 0x90, 0x83, 0x10, 0x0c, 0x7e, 0xcd, 0x8f, 0xa3, 0xed, 0xd9,
|
||||||
|
0x8c, 0x23, 0xeb, 0x65, 0x9c, 0xfb, 0x4a, 0x0d, 0x08, 0x6f, 0x13, 0xac,
|
||||||
|
0x21, 0xff, 0x1d, 0xda, 0xf9, 0xf8, 0x90, 0x35, 0x36, 0x2f, 0xc0, 0xec,
|
||||||
|
0x8c, 0xca, 0xbf, 0xfb, 0x3f, 0x23, 0x60, 0x0e, 0xca, 0xf5, 0x24, 0x27,
|
||||||
|
0x0a, 0x15, 0xcd, 0xb7, 0x9d, 0x05, 0x67, 0xe3, 0xd6, 0xe6, 0x22, 0x90,
|
||||||
|
0x68, 0x68, 0x4a, 0x63, 0x5f, 0xfd, 0xcd, 0xfa, 0xaf, 0xd5, 0x92, 0x5a,
|
||||||
|
0x09, 0xdc, 0x08, 0xef, 0x01, 0xb8, 0x0f, 0x1f, 0x1d, 0xcf, 0x2d, 0xd3,
|
||||||
|
0xfc, 0xfd, 0x2e, 0x9b, 0xab, 0x45, 0xa0, 0xaf, 0xe1, 0x06, 0xf9, 0xa4,
|
||||||
|
0x44, 0xe2, 0x8a, 0x09, 0xdf, 0x91, 0xe7, 0x24, 0x63, 0x78, 0x42, 0xce,
|
||||||
|
0x69, 0xdc, 0x88, 0x34, 0xde, 0xfd, 0x82, 0x43, 0xf0, 0x3d, 0x0d, 0x48,
|
||||||
|
0x74, 0xa3, 0x74, 0xde, 0xc7, 0xf1, 0x7c, 0xcd, 0x05, 0xd9, 0xee, 0x8b,
|
||||||
|
0x59, 0x3f, 0x20, 0x25, 0x8a, 0x61, 0x97, 0x18, 0xda, 0xdd, 0xe4, 0x85,
|
||||||
|
0x06, 0x82, 0x0b, 0x3a, 0x41, 0xe0, 0x48, 0xf7, 0x8c, 0xc2, 0xf1, 0xc8,
|
||||||
|
0x93, 0x96, 0x25, 0x71, 0xe4, 0x26, 0x8c, 0xd9, 0x4e, 0x9b, 0x55, 0x6d,
|
||||||
|
0x1a, 0x1f, 0xcf, 0x68, 0x26, 0xd0, 0xdd, 0xa5, 0x12, 0x12, 0x75, 0xec,
|
||||||
|
0x5e, 0x41, 0xdd, 0xad, 0x0c, 0xfc, 0xae, 0x0c, 0x4d, 0xfd, 0x7b, 0xa0,
|
||||||
|
0x20, 0xcb, 0x47, 0xc2, 0xef, 0x77, 0xa2, 0xcf, 0x44, 0x24, 0x75, 0xd3,
|
||||||
|
0xf7, 0x39, 0x49, 0xad, 0x8c, 0x09, 0xa6, 0x4a, 0x40, 0xb4, 0x38, 0x8e,
|
||||||
|
0xb7, 0xd2, 0x8b, 0xd3, 0xe5, 0xf6, 0x6c, 0xe7, 0x24, 0x65, 0x04, 0xcb,
|
||||||
|
0xd4, 0xeb, 0xcb, 0xa2, 0x75, 0xc4, 0x00, 0x60, 0xcc, 0x20, 0xde, 0xa0,
|
||||||
|
0x83, 0xc9, 0x5b, 0xb8, 0x9a, 0x6c, 0xaa, 0x58, 0xc9, 0x18, 0x21, 0x2d,
|
||||||
|
0xd1, 0x3e, 0xe3, 0xb7, 0xb8, 0x52, 0x0d, 0x53, 0xc7, 0x8c, 0xbe, 0xa3,
|
||||||
|
0xb9, 0x15, 0x05, 0x3e, 0x6a, 0x4e, 0xeb, 0xc0, 0xee, 0xab, 0x26, 0x05,
|
||||||
|
0x94, 0x5c, 0x5a, 0x2d, 0xe2, 0xe5, 0x35, 0x6d, 0x59, 0xba, 0x74, 0xb5,
|
||||||
|
0x78, 0x07, 0x89, 0xb9, 0x26, 0x1f, 0xd3, 0x08, 0xcb, 0xe0, 0xe3, 0xc3,
|
||||||
|
0x41, 0xf8, 0x68, 0x19, 0xf3, 0xb5, 0x35, 0x7e, 0xe1, 0x3e, 0xc7, 0xc3,
|
||||||
|
0x4d, 0x53, 0x78, 0x9d, 0xbf, 0x83, 0x2a, 0xfe, 0xcd, 0x21, 0x82, 0xba,
|
||||||
|
0x47, 0x11, 0x00, 0x8f, 0xab, 0xb9, 0x30, 0xb0, 0xfc, 0x7b, 0x23, 0x3b,
|
||||||
|
0xc9, 0x6a, 0xcd, 0x68, 0x12, 0x9a, 0xd4, 0x72, 0xb9, 0x47, 0x66, 0x3f,
|
||||||
|
0xf5, 0xe0, 0x05, 0x0e, 0x9c, 0x3f, 0xc1, 0x91, 0xd8, 0xa5, 0x1c, 0x18,
|
||||||
|
0xce, 0x5b, 0xa6, 0x91, 0xc0, 0x24, 0xc1, 0xa9, 0x76, 0xe8, 0x5f, 0x78,
|
||||||
|
0xea, 0x0f, 0x41, 0x59, 0xb9, 0x19, 0xa9, 0xd0, 0x19, 0x88, 0x12, 0xbe,
|
||||||
|
0x63, 0x60, 0xff, 0x8c, 0x2e, 0x14, 0xeb, 0x8b, 0x73, 0x5a, 0x35, 0x02,
|
||||||
|
0xff, 0xe3, 0xf0, 0xe9, 0x19, 0xa5, 0xd8, 0x1c, 0x1b, 0xdd, 0x5c, 0x5a,
|
||||||
|
0x7b, 0xff, 0x1e, 0x06, 0x2e, 0x78, 0xa6, 0xf9, 0x62, 0xfd, 0xb0, 0x75,
|
||||||
|
0xec, 0x95, 0x3e, 0xef, 0x4d, 0xba, 0xd6, 0x40, 0xdf, 0x94, 0x47, 0xb3,
|
||||||
|
0x74, 0x5c, 0x8e, 0xe4, 0xd6, 0x23, 0x13, 0x40, 0x15, 0x06, 0x55, 0x87,
|
||||||
|
0xd1, 0x3b, 0x53, 0x9e, 0x4f, 0xfd, 0x94, 0xf2, 0x6c, 0xfe, 0x66, 0x8c,
|
||||||
|
0xa8, 0xf7, 0xf0, 0x40, 0xb2, 0x46, 0x3b, 0xcc, 0x6a, 0x01, 0xee, 0x64,
|
||||||
|
0x51, 0x73, 0x55, 0x46, 0xd3, 0xb1, 0x9d, 0x8b, 0xbe, 0xfe, 0x5d, 0xe9,
|
||||||
|
0x65, 0x52, 0xda, 0x4c, 0x47, 0x6d, 0xa0, 0x16, 0xc2, 0xad, 0x3f, 0x35,
|
||||||
|
0x27, 0x74, 0x26, 0x2f, 0xdb, 0x8a, 0x1b, 0x25, 0x38, 0xeb, 0x98, 0xfb,
|
||||||
|
0x62, 0x40, 0x94, 0xcb, 0x33, 0xcd, 0xc8, 0x80, 0x7f, 0x0e, 0x28, 0x76,
|
||||||
|
0x0b, 0xd0, 0xe6, 0x67, 0x17, 0x43, 0xba, 0xf3, 0x56, 0x9d, 0x12, 0xc6,
|
||||||
|
0xf0, 0xb5, 0x8d, 0x1f, 0xaf, 0x88, 0x44, 0x1d, 0xd2, 0x9b, 0x61, 0xb3,
|
||||||
|
0x08, 0x7a, 0xc9, 0x39, 0x99, 0xf2, 0x80, 0xbc, 0xdd, 0x05, 0x37, 0x09,
|
||||||
|
0x75, 0x69, 0x7b, 0x91, 0x52, 0xae, 0x4f, 0x26, 0xa9, 0x70, 0xaa, 0xb7,
|
||||||
|
0x6c, 0xa3, 0x64, 0x0e, 0xae, 0xc0, 0xb0, 0xe6, 0xdb, 0xd4, 0x9b, 0x28,
|
||||||
|
0x2d, 0xce, 0x49, 0xbd, 0xc6, 0xe0, 0xdd, 0x04, 0x1a, 0x8f, 0x43, 0x58,
|
||||||
|
0x3b, 0xd8, 0x31, 0x19, 0x71, 0xb2, 0x0e, 0x30, 0x77, 0x84, 0x71, 0xbe,
|
||||||
|
0x9a, 0x66, 0x07, 0xdf, 0x94, 0xe1, 0xed, 0x14, 0xf0, 0x4e, 0xbd, 0xde,
|
||||||
|
0xbb, 0xcd, 0xd8, 0xe2, 0xff, 0x49, 0xef, 0x60, 0x0b, 0x9b, 0xb5, 0x99,
|
||||||
|
0x35, 0x57, 0xba, 0xf8, 0xeb, 0xdd, 0x2e, 0x5f, 0xc5, 0x1b, 0x15, 0xb2,
|
||||||
|
0xa0, 0x02, 0xf4, 0xb4, 0x0f, 0x5c, 0x5a, 0x89, 0x69, 0xf1, 0x3d, 0xf4,
|
||||||
|
0x51, 0x39, 0x55, 0xa1, 0x6a, 0x82, 0x43, 0x33, 0xf4, 0xe8, 0xcf, 0x09,
|
||||||
|
0x69, 0xcc, 0x3b, 0xf3, 0xd4, 0x8e, 0x46, 0x7d, 0xe7, 0x21, 0x2a, 0x9e,
|
||||||
|
0x3d, 0x73, 0x9e, 0x5d, 0x5e, 0xdf, 0x5b, 0x5d, 0xcc, 0x10, 0xdb, 0x88,
|
||||||
|
0xee, 0x4b, 0xdc, 0x19, 0xd2, 0xb2, 0x3e, 0x57, 0x0f, 0x73, 0x48, 0x3e,
|
||||||
|
0xed, 0x50, 0xae, 0xc3, 0xa1, 0x98, 0xbe, 0xaa, 0x02, 0x5a, 0xf0, 0xad,
|
||||||
|
0x53, 0x4a, 0xdf, 0x86, 0x6d, 0x49, 0xac, 0xe5, 0xcf, 0x06, 0x02, 0x10,
|
||||||
|
0x51, 0x2a, 0xce, 0xd6, 0xae, 0x59, 0x7a, 0x10, 0xc5, 0xbf, 0x78, 0xc9,
|
||||||
|
0x71, 0x20, 0x40, 0x05, 0x95, 0xc8, 0x6c, 0x49, 0x14, 0x95, 0xfd, 0xcc,
|
||||||
|
0x56, 0x19, 0x87, 0x00, 0xbf, 0x7c, 0xef, 0x55, 0x42, 0x45, 0xf8, 0x39,
|
||||||
|
0x30, 0x14, 0x0c, 0xc0, 0x2a, 0x98, 0xc2, 0xf8, 0x53, 0x49, 0x7a, 0xd0,
|
||||||
|
0x6d, 0xb7, 0x4f, 0x5e, 0x3c, 0x9b, 0x6b, 0x86, 0x42, 0xdc, 0x8c, 0xa3,
|
||||||
|
0xf8, 0xac, 0xef, 0x18, 0x5f, 0x9b, 0xbf, 0x68, 0x2a, 0xb9, 0x73, 0xa8,
|
||||||
|
0x79, 0x5c, 0x31, 0xb4, 0x57, 0x24, 0x11, 0x67, 0xc3, 0x2c, 0x13, 0x85,
|
||||||
|
0x77, 0xf7, 0x10, 0x78, 0x87, 0x8f, 0xba, 0xd1, 0x17, 0x38, 0x96, 0x54,
|
||||||
|
0xa7, 0xca, 0x5e, 0x01, 0x6d, 0xb6, 0xd8, 0x54, 0x40, 0x9e, 0x5d, 0xac,
|
||||||
|
0x68, 0xf4, 0x67, 0x95, 0x1b, 0x72, 0xbb, 0x33, 0x59, 0x89, 0x23, 0xc6,
|
||||||
|
0xa9, 0xa9, 0xe4, 0xbc, 0x1e, 0x5f, 0xdc, 0x74, 0xd3, 0x35, 0x6d, 0x46,
|
||||||
|
0x7d, 0xc3, 0x82, 0xc9, 0xef, 0xa6, 0xd6, 0xc8, 0x3c, 0x6a, 0xc6, 0xb3,
|
||||||
|
0xa3, 0xbe, 0xeb, 0xee, 0x76, 0xf7, 0x79, 0xa0, 0xd0, 0xce, 0x39, 0x20,
|
||||||
|
0xb0, 0xff, 0x18, 0x1a, 0xe1, 0x31, 0xae, 0x60, 0xf2, 0x8a, 0xdb, 0xbe,
|
||||||
|
0xdb, 0x7d, 0x86, 0x88, 0xdc, 0xcb, 0x57, 0xc4, 0x8a, 0x28, 0x3a, 0x93,
|
||||||
|
0x8f, 0x4f, 0xae, 0xa0, 0x35, 0x12, 0x79, 0x42, 0x30, 0xed, 0xf1, 0x1a,
|
||||||
|
0x6c, 0xb3, 0x3e, 0x2b, 0x2f, 0xda, 0x4c, 0x6f, 0x8a, 0x02, 0x35, 0x9d,
|
||||||
|
0x72, 0xaa, 0x4c, 0x87, 0x25, 0x05, 0xe0, 0x73, 0xd8, 0xbb, 0xac, 0x0a,
|
||||||
|
0x9e, 0xef, 0xba, 0xd6, 0x70, 0x2b, 0xc3, 0x56, 0x3a, 0xd5, 0xea, 0x6c,
|
||||||
|
0x86, 0xb8, 0x92, 0xa5, 0xd8, 0xc6, 0x5c, 0xc1, 0xad, 0xc5, 0x69, 0x59,
|
||||||
|
0xa6, 0xb8, 0xa1, 0x82, 0x11, 0x2c, 0x83, 0x7d, 0xe3, 0xff, 0x5a, 0xb1,
|
||||||
|
0xa9, 0xa9, 0x79, 0x22, 0x4c, 0x7e, 0xfb, 0x53, 0x4a, 0x39, 0x86, 0x3a,
|
||||||
|
0xac, 0x63, 0xdb, 0x72, 0xb2, 0xe2, 0x6e, 0x65, 0x25, 0xfb, 0x79, 0x04,
|
||||||
|
0xe6, 0x4a, 0xb7, 0xf0, 0x1d, 0x13, 0x61, 0x7d, 0x64, 0x19, 0xcd, 0x5e,
|
||||||
|
0x22, 0xc5, 0x9b, 0xf1, 0x38, 0xfb, 0xc0, 0x3c, 0x7a, 0xcc, 0xeb, 0xe5,
|
||||||
|
0x15, 0x27, 0x10, 0x43, 0xa1, 0xbb, 0x22, 0x2d, 0xcc, 0x1f, 0x88, 0xf4,
|
||||||
|
0xda, 0x9b, 0x1f, 0xa0, 0xbc, 0x69, 0x80, 0x24, 0x28, 0xba, 0xf6, 0xe8,
|
||||||
|
0xfc, 0x11, 0x12, 0x94, 0xda, 0x2b, 0xc0, 0xb7, 0x67, 0xeb, 0xfc, 0x54,
|
||||||
|
0xe2, 0x40, 0xf1, 0x3f, 0x36, 0x12, 0xa2, 0xa5, 0xa7, 0x7f, 0xf8, 0xfb,
|
||||||
|
0x16, 0x03, 0x6d, 0x9d, 0xcf, 0x96, 0xb7, 0xdd, 0x48, 0xe0, 0x9f, 0x1a,
|
||||||
|
0xe4, 0x4f, 0xdd, 0x5b, 0x64, 0x79, 0x0d, 0xdb, 0x27, 0x40, 0x2f, 0x10,
|
||||||
|
0xe5, 0xd3, 0x63, 0x9f, 0x41, 0xd8, 0x79, 0x68, 0x00, 0xf3, 0x33, 0xb7,
|
||||||
|
0x38, 0x83, 0x93, 0xe7, 0xb1, 0x2f, 0xbb, 0xbd, 0x13, 0xa8, 0x55, 0x56,
|
||||||
|
0x79, 0x8a, 0x77, 0x1b, 0x35, 0x80, 0x9e, 0x20, 0xc0, 0x5b, 0x45, 0x6b,
|
||||||
|
0xb7, 0x48, 0xcf, 0x37, 0x5e, 0x03, 0xd4, 0x41, 0x1b, 0x1c, 0x02, 0x7f,
|
||||||
|
0x8a, 0x25, 0x76, 0x4d, 0xfc, 0xd3, 0x76, 0x43, 0x67, 0x6d, 0xda, 0x75,
|
||||||
|
0xf9, 0x24, 0xe4, 0xcb, 0x0b, 0x61, 0x73, 0x91, 0x66, 0x14, 0x9d, 0x8b,
|
||||||
|
0x66, 0x8e, 0x8f, 0x9d, 0xcc, 0x1b, 0xd0, 0x94, 0x0e, 0x9d, 0x31, 0xc7,
|
||||||
|
0xce, 0xfd, 0x51, 0x98, 0xa6, 0x0d, 0xf7, 0x22, 0x0c, 0xc7, 0x02, 0x24,
|
||||||
|
0x19, 0xe5, 0x6a, 0xa4, 0x32, 0x38, 0xab, 0x0f, 0xb8, 0xb8, 0x85, 0xe8,
|
||||||
|
0xc1, 0x86, 0x5d, 0x91, 0xa8, 0xf5, 0x2e, 0xf5, 0x7b, 0x43, 0xf3, 0x47,
|
||||||
|
0x83, 0xe7, 0x4b, 0xa7, 0x75, 0x5b, 0x04, 0x4d, 0x72, 0x11, 0x3a, 0x9b,
|
||||||
|
0x1c, 0x3a, 0x06, 0xe6, 0xd3, 0x11, 0x8a, 0x2e, 0x6f, 0x70, 0xc6, 0xba,
|
||||||
|
0xd0, 0xf9, 0x02, 0x41, 0x12, 0xae, 0x58, 0xf0, 0x6b, 0x06, 0x2c, 0xcb,
|
||||||
|
0x40, 0xb1, 0x56, 0x90, 0x83, 0xbc, 0x33, 0x4d, 0x70, 0x62, 0xd7, 0x64,
|
||||||
|
0xb9, 0x96, 0x2f, 0x51, 0x33, 0x99, 0x72, 0x80, 0x09, 0xb9, 0x2b, 0xd5,
|
||||||
|
0x7e, 0x96, 0x1d, 0x99, 0xf6, 0x4d, 0xe4, 0x1d, 0x15, 0xb3, 0x85, 0xd0,
|
||||||
|
0x75, 0xa9, 0x6d, 0x9d, 0xfc, 0xfa, 0xd9, 0xf1, 0x0a, 0x28, 0x63, 0x6b,
|
||||||
|
0x64, 0x06, 0xf5, 0x78, 0x17, 0x9a, 0x72, 0x28, 0x00, 0xb9, 0x8f, 0x3a,
|
||||||
|
0xd3, 0x87, 0xc0, 0x62, 0x25, 0x9d, 0xd5, 0xcb, 0x36, 0xef, 0x3c, 0x67,
|
||||||
|
0xdd, 0x4d, 0x50, 0x0d, 0x47, 0x91, 0x9d, 0x60, 0x8b, 0xcb, 0x28, 0x8a,
|
||||||
|
0x57, 0x9b, 0x7a, 0x0a, 0xfd, 0x3c, 0xf6, 0x18, 0x7d, 0x32, 0xce, 0x74,
|
||||||
|
0x38, 0xcd, 0x2c, 0x2b, 0x91, 0x72, 0x28, 0xc3, 0x27, 0x20, 0x7d, 0x9e,
|
||||||
|
0x72, 0xce, 0xf1, 0x4e, 0x18, 0xfb, 0xc3, 0x89, 0x10, 0x4f, 0x84, 0x23,
|
||||||
|
0xf0, 0x79, 0x64, 0x15, 0xa3, 0xa5, 0xe8, 0xc1, 0xb0, 0x2c, 0x32, 0x39,
|
||||||
|
0x4c, 0x40, 0x6b, 0x6b, 0xa4, 0x7d, 0xdd, 0x21, 0x63, 0xe5, 0xf6, 0x00,
|
||||||
|
0x74, 0x73, 0xd8, 0x62, 0x2e, 0xb8, 0xc6, 0xa5, 0x3e, 0xf7, 0xdb, 0xc3,
|
||||||
|
0x52, 0x21, 0x85, 0xa9, 0x98, 0xb5, 0x79, 0x10, 0x93, 0x5d, 0xd4, 0x3f,
|
||||||
|
0x3c, 0xa9, 0x2d, 0xb8, 0xe9, 0xa8, 0x09, 0xe9, 0xef, 0xe1, 0x03, 0x34,
|
||||||
|
0xe5, 0x24, 0x08, 0x03, 0x8e, 0x83, 0xb9, 0x66, 0x2e, 0xa6, 0x89, 0xb5,
|
||||||
|
0x61, 0x0b, 0x16, 0x0b, 0x6b, 0xa5, 0x4b, 0x7d, 0xe7, 0x8a, 0x28, 0xda,
|
||||||
|
0xaf, 0x85, 0xd6, 0x27, 0x7e, 0x6a, 0xa0, 0x35, 0xe1, 0x65, 0x50, 0xe5,
|
||||||
|
0xa9, 0x38, 0xf3, 0xf5, 0x48, 0xa7, 0x7a, 0xbb, 0x77, 0x4f, 0xb5, 0x52,
|
||||||
|
0x77, 0xec, 0x48, 0x6a, 0xe3, 0x2d, 0xd3, 0x7c, 0xc5, 0xe9, 0xe3, 0x26,
|
||||||
|
0x14, 0x76, 0xc2, 0x3e, 0xfa, 0x19, 0xa2, 0x9a, 0x00, 0x02, 0x84, 0xae,
|
||||||
|
0xee, 0xce, 0xf6, 0x49, 0x40, 0x50, 0x56, 0x8f, 0x48, 0x67, 0x8d, 0xb1,
|
||||||
|
0x8a, 0x56, 0xe0, 0x27, 0x1b, 0xb6, 0xdb, 0x37, 0x78, 0x34, 0x49, 0x26,
|
||||||
|
0x8d, 0xa8, 0x21, 0xba, 0xf2, 0xd9, 0xe7, 0x67, 0x6a, 0x81, 0x98, 0x16,
|
||||||
|
0xef, 0x77, 0x51, 0x22, 0x78, 0xa4, 0xb8, 0x75, 0xe1, 0x92, 0xa8, 0x77,
|
||||||
|
0xbe, 0x03, 0x83, 0xc1, 0xef, 0x10, 0x59, 0xde, 0x92, 0x4c, 0x15, 0x7d,
|
||||||
|
0xd4, 0x11, 0x5e, 0x5e, 0x40, 0xee, 0xc7, 0x2f, 0x5f, 0xca, 0xda, 0x65,
|
||||||
|
0x74, 0x92, 0xbd, 0xc9, 0x6b, 0x52, 0x44, 0x66, 0x3a, 0x42, 0x3a, 0x37,
|
||||||
|
0xeb, 0xb3, 0xb5, 0x73, 0xaa, 0xbf, 0x2d, 0xea, 0x8e, 0x17, 0xd1, 0xa6,
|
||||||
|
0xf3, 0x99, 0x3d, 0x8d, 0x94, 0x93, 0x7a, 0x0e, 0x45, 0xe6, 0xcf, 0xd1,
|
||||||
|
0xb2, 0xf3, 0xc6, 0xd5, 0xc6, 0xa1, 0x24, 0x03, 0x4a, 0x12, 0xe3, 0x1e,
|
||||||
|
0x94, 0x57, 0xac, 0x11, 0x5d, 0xda, 0xdc, 0x9a, 0xfd, 0x7a, 0x37, 0x9c,
|
||||||
|
0x07, 0x08, 0x2b, 0x3b, 0x59, 0xc5, 0x7f, 0x72, 0x30, 0xf4, 0x40, 0x08,
|
||||||
|
0x61, 0x19, 0x33, 0x12, 0xaa, 0xaf, 0xbb, 0xa5, 0x8f, 0xfc, 0x37, 0xdb,
|
||||||
|
0xa0, 0xc6, 0xe1, 0xa4, 0xe7, 0x2f, 0xef, 0xd3, 0x0a, 0x50, 0x10, 0x65,
|
||||||
|
0xfb, 0xbd, 0xe6, 0x94, 0x4a, 0x5c, 0xc8, 0x11, 0xee, 0xf9, 0xb5, 0xcc,
|
||||||
|
0x77, 0xe8, 0x74, 0xe8, 0x86, 0x0c, 0xea, 0x03, 0x38, 0x31, 0x85, 0x6f,
|
||||||
|
0xe8, 0xa7, 0xd5, 0xf7, 0xae, 0x5f, 0x29, 0xa7, 0x53, 0xff, 0x49, 0xfc,
|
||||||
|
0x62, 0x10, 0xfc, 0xf6, 0x2b, 0xdb, 0x02, 0x86, 0x24, 0x90, 0x43, 0x12,
|
||||||
|
0x94, 0x34, 0x91, 0xfd, 0x5c, 0xa4, 0x42, 0xb1, 0xdf, 0x90, 0xeb, 0x96,
|
||||||
|
0x2b, 0xfb, 0xd6, 0x23, 0x5e, 0xb7, 0x64, 0x20, 0x24, 0xd2, 0xc4, 0x88,
|
||||||
|
0x2b, 0x93, 0xb5, 0x7b, 0x4e, 0x71, 0x0e, 0xbc, 0x4b, 0xdc, 0xeb, 0x05,
|
||||||
|
0x50, 0xb4, 0x1a, 0x41, 0xce, 0x61, 0xdf, 0x83, 0xe3, 0x15, 0xae, 0x1a,
|
||||||
|
0x3c, 0xc6, 0x2b, 0x2e, 0x71, 0x50, 0xf1, 0x79, 0xf3, 0x33, 0xdf, 0x37,
|
||||||
|
0xfa, 0x02, 0x7e, 0x6c, 0x28, 0xf8, 0x31, 0x43, 0x56, 0x82, 0xd3, 0x2f,
|
||||||
|
0x5f, 0x55, 0x1d, 0xea, 0x10, 0xe3, 0x74, 0x85, 0x1b, 0xcc, 0x00, 0x35,
|
||||||
|
0x21, 0x76, 0xf3, 0xac, 0x81, 0xf2, 0x4e, 0x42, 0xfc, 0xfb, 0x88, 0xd9,
|
||||||
|
0x2b, 0xaf, 0x8e, 0x89, 0x24, 0xea, 0x68, 0x2c, 0x1a, 0x91, 0x05, 0x21,
|
||||||
|
0xc5, 0x6b, 0x80, 0xcb, 0xa1, 0x17, 0x61, 0xf5, 0xac, 0xc8, 0x65, 0xec,
|
||||||
|
0x6f, 0x5d, 0x4e, 0xa6, 0xd9, 0xb9, 0x13, 0xe9, 0x7e, 0xb7, 0xf2, 0x8d,
|
||||||
|
0x29, 0x00, 0x49, 0xf3, 0x52, 0x99, 0x3f, 0xd8, 0xf3, 0xfd, 0x86, 0x1c,
|
||||||
|
0x03, 0x49, 0x21, 0xc1, 0x81, 0xb6, 0xb0, 0xaf, 0x82, 0x30, 0x0d, 0xa1,
|
||||||
|
0xb6, 0xbf, 0xd2, 0xd8, 0x8c, 0x02, 0xea, 0xdd, 0xcb, 0x36, 0x49, 0x42,
|
||||||
|
0xe4, 0x25, 0xfe, 0x2a, 0x4e, 0x58, 0x26, 0x96, 0xc6, 0xec, 0x92, 0x34,
|
||||||
|
0x21, 0x94, 0x55, 0xd3, 0x06, 0xa7, 0x05, 0x60, 0x75, 0x93, 0x46, 0x71,
|
||||||
|
0xec, 0xba, 0x7c, 0x56, 0xfb, 0xd2, 0x08, 0xa3, 0x26, 0x62, 0x8c, 0x78,
|
||||||
|
0x53, 0x2c, 0x75, 0x36, 0x38, 0x85, 0xfe, 0xe3, 0x01, 0x20, 0x34, 0x75,
|
||||||
|
0x51, 0x66, 0xd2, 0x32, 0xcf, 0x4a, 0xf6, 0x21, 0xfe, 0x9a, 0xc2, 0xfc,
|
||||||
|
0xaa, 0xae, 0x1c, 0x55, 0xa1, 0x2c, 0x24, 0xa1, 0x86, 0x89, 0x54, 0x5e,
|
||||||
|
0x47, 0x42, 0xd4, 0x63, 0x0e, 0x85, 0xf8, 0x97, 0x55, 0x8c, 0x75, 0xa2,
|
||||||
|
0x94, 0x25, 0xaf, 0x9c, 0x9e, 0x17, 0xdb, 0xea, 0x16, 0x1e, 0x48, 0x1a,
|
||||||
|
0x6d, 0xa6, 0x4c, 0x31, 0x25, 0x7e, 0x44, 0xdb, 0x10, 0x0f, 0xf3, 0xaf,
|
||||||
|
0x63, 0x71, 0xb3, 0xad, 0x09, 0x16, 0xbc, 0xa0, 0x35, 0x5d, 0x17, 0x56,
|
||||||
|
0xe7, 0x69, 0xd1, 0x5b, 0x26, 0x9d, 0xc3, 0x2d, 0x06, 0x3a, 0x69, 0xfd,
|
||||||
|
0xfc, 0xa9, 0x31, 0xa7, 0xc5, 0xd4, 0x8f, 0x52, 0x45, 0x44, 0xe2, 0xd2,
|
||||||
|
0x7b, 0x15, 0xe9, 0xa7, 0xac, 0xe3, 0x51, 0xf0, 0x3d, 0x18, 0xd6, 0x9b,
|
||||||
|
0xf6, 0xbd, 0x5f, 0x1f, 0xff, 0x27, 0x46, 0x26, 0xfa, 0x0a, 0x63, 0xe0,
|
||||||
|
0x56, 0x8e, 0x6e, 0xc1, 0x9f, 0xd2, 0xcb, 0x24, 0x22, 0x39, 0x5c, 0x21,
|
||||||
|
0x83, 0x7d, 0xcf, 0x9f, 0x5e, 0xa1, 0x31, 0x1b, 0x7c, 0x6a, 0x80, 0x88,
|
||||||
|
0x23, 0x4f, 0xe0, 0x51, 0x4d, 0x01, 0x94, 0xf8, 0x13, 0xf5, 0xf8, 0xb2,
|
||||||
|
0x20, 0x94, 0xb8, 0x99, 0x5d, 0x5d, 0xa1, 0xf4, 0x4d, 0x02, 0x1a, 0x9e,
|
||||||
|
0xb6, 0x9b, 0x3b, 0x4e, 0xa5, 0xee, 0x22, 0x26, 0xba, 0x32, 0x29, 0xa3,
|
||||||
|
0xa1, 0x36, 0x72, 0xde, 0x84, 0x7b, 0xbb, 0x0b, 0x77, 0xad, 0x65, 0xec,
|
||||||
|
0x0b, 0x0c, 0x5d, 0x8a, 0xfe, 0x98, 0x6a, 0x42, 0xd7, 0xad, 0x91, 0x08,
|
||||||
|
0x66, 0xc6, 0x30, 0xab, 0x8d, 0x6c, 0x7c, 0xe2, 0x3a, 0xf7, 0x55, 0xe8,
|
||||||
|
0x15, 0xa5, 0x2a, 0x64, 0xad, 0x1a, 0x3b, 0xcc, 0x93, 0xad, 0xe7, 0x2c,
|
||||||
|
0xae, 0x80, 0x0a, 0xbb, 0x98, 0xf7, 0x88, 0x3f, 0x1b, 0x30, 0x7b, 0xd6,
|
||||||
|
0x5e, 0x68, 0x39, 0x63, 0xc3, 0x2b, 0x35, 0xf3, 0x99, 0x3d, 0xa0, 0x36,
|
||||||
|
0x62, 0x9a, 0xcf, 0xb4, 0xe8, 0x89, 0x0f, 0x13, 0x56, 0x08, 0xef, 0x3c,
|
||||||
|
0x1c, 0x18, 0x9e, 0x7e, 0x0e, 0xa4, 0xa1, 0x76, 0x5c, 0x0a, 0xa8, 0x83,
|
||||||
|
0x72, 0xca, 0x35, 0xe6, 0xee, 0x44, 0x6e, 0x01, 0x5d, 0x43, 0x87, 0xd5,
|
||||||
|
0x5d, 0x77, 0xac, 0x08, 0x99, 0xd2, 0x70, 0x53, 0x57, 0x35, 0xbd, 0xee,
|
||||||
|
0x3d, 0x71, 0xfd, 0x4e, 0x31, 0xe0, 0xbc, 0x24, 0x4d, 0x27, 0xf3, 0x41,
|
||||||
|
0x0b, 0xde, 0xc7, 0x21, 0x6b, 0x8c, 0xab, 0xf2, 0x65, 0x86, 0x4c, 0xa5,
|
||||||
|
0x18, 0x77, 0xa9, 0xbb, 0x71, 0xf9, 0x9d, 0x97, 0x5a, 0x96, 0x61, 0xe8,
|
||||||
|
0x42, 0x03, 0x07, 0x12, 0x60, 0x33, 0x58, 0x03, 0xf4, 0x3b, 0x2b, 0xd0,
|
||||||
|
0x68, 0x70, 0x83, 0xf6, 0x3a, 0x73, 0x56, 0xcc, 0x8a, 0x3b, 0xef, 0xf4,
|
||||||
|
0xcc, 0x89, 0xa1, 0x77, 0x94, 0x62, 0x78, 0x51, 0xb9, 0x0c, 0x0f, 0xf6,
|
||||||
|
0x00, 0xa9, 0x1e, 0xa5, 0x95, 0xb7, 0x12, 0x36, 0xb8, 0x0e, 0x9e, 0x02,
|
||||||
|
0xdb, 0x60, 0x5f, 0xe8, 0xfe, 0x91, 0x20, 0x22, 0x23, 0xdd, 0x6d, 0xf9,
|
||||||
|
0x08, 0xfc, 0xfc, 0x00, 0x14, 0x48, 0xbd, 0x5a, 0x2f, 0xba, 0x70, 0x2b,
|
||||||
|
0xd1, 0xa6, 0x4f, 0xde, 0x66, 0x4c, 0xaa, 0xd1, 0xc1, 0xcf, 0x3f, 0x5d,
|
||||||
|
0xaa, 0x3a, 0xe9, 0x00, 0x17, 0xa0, 0x96, 0x90, 0x7f, 0xf5, 0x9f, 0x27,
|
||||||
|
0xf0, 0x93, 0x42, 0x16, 0x79, 0x2f, 0xaa, 0x95, 0x23, 0x9e, 0x56, 0x31,
|
||||||
|
0xc2, 0x33, 0x99, 0xc1, 0x6a, 0x0b, 0xdf, 0xd9, 0x6b, 0x27, 0x0b, 0x81,
|
||||||
|
0x37, 0x19, 0xf9, 0x78, 0xff, 0xfd, 0x88, 0x31, 0x6c, 0xba, 0xa0, 0x3c,
|
||||||
|
0x22, 0x9f, 0x5f, 0x4c, 0x1a, 0xe8, 0x29, 0x84, 0xcf, 0x64, 0x72, 0xde,
|
||||||
|
0x60, 0x43, 0x13, 0x69, 0x11, 0x29, 0xd9, 0xec, 0x7e, 0x0d, 0x96, 0xe0,
|
||||||
|
0xfb, 0x67, 0x14, 0x1d, 0x4a, 0x20, 0x1f, 0xfd, 0xc7, 0xe5, 0x7b, 0x5e,
|
||||||
|
0x5f, 0xda, 0x7d, 0x85, 0x2c, 0xa9, 0x84, 0x98, 0x63, 0x0a, 0x2e, 0xef,
|
||||||
|
0xba, 0xfd, 0x41, 0x6d, 0xfa, 0xad, 0xcd, 0x60, 0xa5, 0xe9, 0x08, 0xdf,
|
||||||
|
0x3d, 0xd2, 0xaf, 0x3d, 0xc4, 0xb7, 0xa0, 0x0d, 0x99, 0xdd, 0x9c, 0xcb,
|
||||||
|
0x31, 0xf6, 0x1d, 0xe1, 0x4f, 0x64, 0x2c, 0x5c, 0xca, 0x2e, 0xc9, 0x67,
|
||||||
|
0x0b, 0x4e, 0x14, 0xf6, 0x98, 0x20, 0x09, 0xab, 0x3b, 0x22, 0x01, 0xf0,
|
||||||
|
0x0b, 0x8e, 0x41, 0x25, 0x4f, 0x9d, 0x6b, 0x02, 0x3d, 0xab, 0xb4, 0xbb,
|
||||||
|
0xbe, 0x12, 0x84, 0x88, 0xf6, 0xe6, 0x20, 0xcd, 0x45, 0xca, 0xd0, 0x3c,
|
||||||
|
0xe3, 0x87, 0x33, 0x9b, 0x27, 0xf4, 0x30, 0xa2, 0x61, 0xde, 0x06, 0x07,
|
||||||
|
0x46, 0x47, 0x8a, 0xae, 0x65, 0x17, 0x25, 0xf5, 0x57, 0x7b, 0x9c, 0xd8,
|
||||||
|
0x74, 0xc5, 0xa6, 0xd3, 0xa4, 0xee, 0x50, 0x02, 0x9a, 0x22, 0x57, 0x3b,
|
||||||
|
0xf6, 0xcf, 0xa0, 0xb4, 0x7a, 0x4f, 0x31, 0x6c, 0xc1, 0x16, 0x05, 0xfd,
|
||||||
|
0xa8, 0x70, 0x9a, 0xc4, 0xdf, 0xac, 0x0d, 0xcc, 0x9b, 0x61, 0x8c, 0xf7,
|
||||||
|
0x58, 0xec, 0xf0, 0x06, 0x1b, 0x56, 0x98, 0xad, 0x37, 0xbb, 0xd4, 0x72,
|
||||||
|
0x60, 0x59, 0x84, 0xbf, 0xd8, 0xad, 0x08, 0x89, 0x4d, 0x28, 0x94, 0x35,
|
||||||
|
0x0a, 0x6c, 0xc1, 0x37, 0x7b, 0xc8, 0xb1, 0x3f, 0x84, 0x6b, 0xe9, 0x67,
|
||||||
|
0x18, 0x9a, 0x9d, 0x6e, 0xc1, 0xa2, 0x0a, 0x3e, 0x20, 0x58, 0xf5, 0x97,
|
||||||
|
0x12, 0xa7, 0x38, 0xeb, 0x0e, 0xd8, 0x67, 0xfb, 0x1e, 0xc1, 0xaa, 0x32,
|
||||||
|
0x27, 0x4c, 0x14, 0xe7, 0x39, 0x8d, 0x21, 0x68, 0x05, 0x93, 0x78, 0x12,
|
||||||
|
0xbc, 0x19, 0xe4, 0x57, 0x0f, 0xd2, 0xbf, 0x61, 0x3d, 0x96, 0x5a, 0xa6,
|
||||||
|
0xdb, 0xb3, 0xde, 0xf1, 0x2d, 0x7e, 0x44, 0x6f, 0xde, 0x81, 0x46, 0x9e,
|
||||||
|
0xec, 0x1a, 0xc8, 0x38, 0x97, 0x73, 0x5e, 0x1a, 0xc8, 0xf2, 0x6d, 0x1d,
|
||||||
|
0xdd, 0x30, 0x0c, 0x85, 0x73, 0x6a, 0xfd, 0x05, 0x57, 0x4c, 0x75, 0x43,
|
||||||
|
0x59, 0xc1, 0x11, 0x15, 0x64, 0xf3, 0x88, 0x50, 0x8d, 0xf3, 0xf4, 0xbf,
|
||||||
|
0x25, 0x5a, 0xc2, 0x78, 0x95, 0xf4, 0xb4, 0x70, 0x6d, 0x7a, 0x4a, 0xb8,
|
||||||
|
0x56, 0xe9, 0xad, 0x0f, 0xbf, 0x29, 0xd1, 0x09, 0x38, 0xef, 0xca, 0xab,
|
||||||
|
0x4d, 0x87, 0xd9, 0x10, 0x5d, 0x57, 0x6b, 0xe0, 0xea, 0x71, 0x51, 0x36,
|
||||||
|
0x8e, 0xb3, 0x7a, 0xe5, 0xb7, 0x13, 0x66, 0x70, 0x30, 0xa5, 0xd2, 0xc6,
|
||||||
|
0x49, 0x12, 0xc4, 0x70, 0x08, 0xe9, 0x8f, 0x3d, 0xd5, 0x6a, 0xbf, 0xf5,
|
||||||
|
0x61, 0x3e, 0x35, 0xc2, 0xfa, 0xb0, 0x55, 0x92, 0x32, 0xf2, 0x27, 0x6a,
|
||||||
|
0x19, 0x9f, 0xc5, 0xc8, 0xee, 0x3a, 0xa2, 0x8c, 0x23, 0x40, 0xd6, 0x7d,
|
||||||
|
0x8e, 0x15, 0x78, 0xcd, 0x22, 0xad, 0xea, 0xf2, 0x2a, 0xf7, 0x43, 0x50,
|
||||||
|
0xc9, 0xa1, 0x53, 0x12, 0x4e, 0x67, 0x38, 0xb5, 0x80, 0xae, 0xdf, 0x26,
|
||||||
|
0x98, 0xb4, 0x75, 0x88, 0x5f, 0x1f, 0xf5, 0xa9, 0x93, 0x90, 0x60, 0x28,
|
||||||
|
0xba, 0xd2, 0x26, 0x7d, 0x22, 0xa4, 0x23, 0xd4, 0xff, 0x4e, 0xac, 0x1b,
|
||||||
|
0x2f, 0xac, 0x6a, 0x7c, 0xfa, 0x9e, 0x0d, 0xfb, 0x17, 0x7a, 0x9d, 0x04,
|
||||||
|
0xd8, 0xfb, 0xd9, 0x96, 0xd1, 0xd1, 0x7d, 0xc0, 0xe9, 0xf0, 0x34, 0x19,
|
||||||
|
0x89, 0xe2, 0x15, 0x65, 0x7b, 0x9c, 0x94, 0x6a, 0x17, 0x59, 0x28, 0x1f,
|
||||||
|
0x28, 0x10, 0x98, 0xaf, 0x1a, 0xc7, 0x62, 0x41, 0x77, 0xe2, 0x00, 0x7f,
|
||||||
|
0x20, 0x0d, 0xb3, 0x35, 0x86, 0xfb, 0xae, 0xa5, 0xaf, 0xf7, 0x3c, 0x3c,
|
||||||
|
0x63, 0xe2, 0xa2, 0xd4, 0x44, 0x3a, 0xe1, 0x2d, 0x3b, 0x38, 0x01, 0x89,
|
||||||
|
0x0d, 0xca, 0x67, 0xa4, 0x5f, 0xcb, 0x9b, 0xdc, 0x7a, 0xb9, 0xf2, 0x8e,
|
||||||
|
0x43, 0x18, 0x74, 0xd9, 0xd6, 0x4d, 0x95, 0x80, 0x54, 0x62, 0xf9, 0x15,
|
||||||
|
0xdc, 0x0a, 0xcb, 0xac, 0x52, 0xf4, 0xe9, 0xb8, 0x2b, 0x75, 0xda, 0x17,
|
||||||
|
0x70, 0x3f, 0xe5, 0xc4, 0x87, 0x11, 0x87, 0x27, 0x0c, 0xe1, 0xf8, 0x8e,
|
||||||
|
0xec, 0xae, 0x33, 0x63, 0x5e, 0xef, 0x94, 0xe4, 0xa6, 0x85, 0xd0, 0x52,
|
||||||
|
0x60, 0xc3, 0x47, 0x02, 0x21, 0xff, 0xd6, 0x42, 0x98, 0xf3, 0x36, 0xfd,
|
||||||
|
0xca, 0x00, 0xf0, 0x58, 0x24, 0x02, 0x4e, 0xf5, 0x1f, 0xc6, 0x46, 0x9c,
|
||||||
|
0xa2, 0x36, 0x3f, 0x50, 0x9a, 0x25, 0x34, 0x03, 0xe5, 0xc3, 0x43, 0xe2,
|
||||||
|
0x5d, 0x3d, 0xf0, 0xa1, 0x70, 0xb6, 0xa1, 0x5e, 0x54, 0x7d, 0x8e, 0xbe,
|
||||||
|
0x80, 0xbd, 0x62, 0xd6, 0x71, 0xf6, 0xe2, 0xc0, 0x3d, 0xa3, 0x5d, 0x6f,
|
||||||
|
0xd3, 0x1c, 0x00, 0x1e, 0x9b, 0x4e, 0x02, 0xd9, 0x2e, 0x4f, 0x30, 0xc6,
|
||||||
|
0x0d, 0xba, 0xef, 0x7a, 0xe1, 0xc5, 0xc7, 0x77, 0xef, 0x10, 0x27, 0x9f,
|
||||||
|
0x8f, 0x4b, 0x3f, 0xb9, 0xa9, 0x8b, 0xfa, 0x8d, 0x1f, 0x27, 0xf0, 0xf5,
|
||||||
|
0x01, 0x65, 0x7b, 0x8c, 0xdf, 0x4b, 0xa9, 0x1e, 0xbe, 0x3a, 0xae, 0x14,
|
||||||
|
0x8b, 0x16, 0xf8, 0xa9, 0xa3, 0xe1, 0xc3, 0xe9, 0x1f, 0xbc, 0x86, 0x70,
|
||||||
|
0x5c, 0xe7, 0x53, 0x0a, 0xb7, 0x61, 0x52, 0x5f, 0x6f, 0xa4, 0x80, 0x64,
|
||||||
|
0x0f, 0xa9, 0x97, 0x07, 0xb5, 0x5d, 0x80, 0x6e, 0xb3, 0xbe, 0xfb, 0x0e,
|
||||||
|
0xdf, 0xe1, 0x71, 0xb9, 0xf0, 0xa6, 0xaf, 0xdf, 0xa6, 0xca, 0xd7, 0x4b,
|
||||||
|
0x9d, 0xc2, 0x45, 0xc3, 0x8d, 0x99, 0x2b, 0xc1, 0x2b, 0xb8, 0x92, 0x61,
|
||||||
|
0x41, 0x54, 0xaa, 0x6a, 0xab, 0xea, 0x7c, 0x48, 0xee, 0xdd, 0x32, 0x7b,
|
||||||
|
0xf4, 0xad, 0xe8, 0xbe, 0x71, 0x5e, 0x3e, 0x57, 0xb4, 0x1a, 0x78, 0x7a,
|
||||||
|
0x1d, 0xcd, 0x26, 0xfa, 0x72, 0x17, 0x55, 0xd7, 0x93, 0x2a, 0xc8, 0x34,
|
||||||
|
0xd2, 0x50, 0x2a, 0x44, 0x5e, 0x2f, 0x99, 0xd8, 0x08, 0x86, 0xa7, 0xb6,
|
||||||
|
0x07, 0x1e, 0x59, 0x2b, 0x65, 0x99, 0x2a, 0xe4, 0xf4, 0x7a, 0x1a, 0x5b,
|
||||||
|
0xf6, 0x28, 0x38, 0x2f, 0x56, 0x1a, 0xf3, 0xec, 0x81, 0xde, 0xc3, 0x4b,
|
||||||
|
0xd9, 0x62, 0xc8, 0x72, 0x3b, 0x96, 0x09, 0x8c, 0xda, 0x9f, 0x58, 0x13,
|
||||||
|
0x7b, 0x72, 0x32, 0x71, 0xff, 0x3b, 0x29, 0x31, 0x2d, 0x52, 0x15, 0xb9,
|
||||||
|
0xef, 0x09, 0x03, 0x66, 0xfb, 0xa0, 0x64, 0xdf, 0xa3, 0x99, 0x96, 0xc4,
|
||||||
|
0xb0, 0x8d, 0xcd, 0x82, 0xac, 0xfe, 0xc7, 0xf4, 0x5d, 0x97, 0x75, 0x4d,
|
||||||
|
0xb6, 0x81, 0xd7, 0xdb, 0xa1, 0x5d, 0xd8, 0x33, 0x59, 0x70, 0x35, 0x36,
|
||||||
|
0x41, 0x89, 0x70, 0xa5, 0x81, 0xdd, 0x2b, 0x84, 0x4b, 0x1c, 0xd7, 0xef,
|
||||||
|
0x4b, 0x3f, 0xdb, 0xdd, 0x7c, 0xe3, 0x9a, 0xb2, 0xd7, 0x66, 0x32, 0x53,
|
||||||
|
0xc4, 0xa0, 0x1c, 0x8b, 0xd9, 0x9f, 0x03, 0x0b, 0xf9, 0x6c, 0x18, 0x68,
|
||||||
|
0x10, 0x70, 0xb1, 0xd7, 0xdf, 0xa0, 0x7a, 0xbb, 0x78, 0x23, 0x8b, 0x20,
|
||||||
|
0xf9, 0x30, 0x07, 0x76, 0x1f, 0x64, 0x79, 0x78, 0x5b, 0x0f, 0x40, 0x90,
|
||||||
|
0x4d, 0xaa, 0x5d, 0xee, 0x54, 0x84, 0xeb, 0xcb, 0xab, 0xf8, 0xbf, 0x18,
|
||||||
|
0xa9, 0xf2, 0xbb, 0xe4, 0x36, 0x3e, 0xc8, 0x2d, 0x5c, 0x8e, 0x24, 0x2b,
|
||||||
|
0xf5, 0xe7, 0x9a, 0x52, 0x36, 0xf0, 0x35, 0x4e, 0xaa, 0x60, 0xa5, 0x51,
|
||||||
|
0x39, 0x7b, 0xae, 0xa1, 0x3c, 0x77, 0x42, 0xb3, 0xfd, 0xba, 0x6e, 0xb8,
|
||||||
|
0xcc, 0x7e, 0xc4, 0xbf, 0x49, 0xbc, 0x7d, 0x99, 0xc7, 0x58, 0xd4, 0x18,
|
||||||
|
0x6f, 0x26, 0xaf, 0x68, 0x74, 0xad, 0x05, 0xa5, 0x39, 0xc0, 0x42, 0xa3,
|
||||||
|
0x26, 0x4a, 0xad, 0x8d, 0x89, 0xaa, 0x8b, 0x48, 0xbc, 0x2d, 0xe2, 0xc9,
|
||||||
|
0xc2, 0xe9, 0x73, 0x32, 0x0f, 0xb5, 0xb6, 0x02, 0xa5, 0xa4, 0x18, 0x1b,
|
||||||
|
0x70, 0xf7, 0x6f, 0x96, 0xa4, 0xa9, 0xfe, 0x87, 0x1a, 0x45, 0x08, 0x71,
|
||||||
|
0x12, 0xba, 0xad, 0xc9, 0x82, 0x54, 0x83, 0xb2, 0xf8, 0x42, 0xe8, 0xb2,
|
||||||
|
0x63, 0x89, 0xbd, 0xe8, 0xb6, 0xfa, 0xa2, 0xc0, 0x4f, 0xd2, 0xcb, 0xa1,
|
||||||
|
0xd3, 0x0f, 0x31, 0xb0, 0x3c, 0xf6, 0xc2, 0x16, 0x37, 0x44, 0x30, 0xff,
|
||||||
|
0x4d, 0x00, 0xb9, 0x6f, 0xbb, 0xf5, 0xd9, 0x8d, 0x60, 0xce, 0xa0, 0x33,
|
||||||
|
0x7f, 0xef, 0x4c, 0xd8, 0xb8, 0xc8, 0xdc, 0x9b, 0x1e, 0x01, 0x91, 0x9d,
|
||||||
|
0x4d, 0xe0, 0x4e, 0x6b, 0x9d, 0x36, 0xa7, 0x42, 0x86, 0xce, 0x97, 0xbc,
|
||||||
|
0x3b, 0x63, 0xa5, 0x9f, 0xc6, 0xff, 0x22, 0x08, 0x7d, 0xe3, 0x59, 0xb2,
|
||||||
|
0x25, 0xa0, 0x5d, 0xf1, 0x3b, 0x22, 0xbd, 0x7a, 0xf2, 0x5a, 0xb7, 0x31,
|
||||||
|
0x72, 0x4f, 0x58, 0x3b, 0x1f, 0x37, 0xa6, 0xd4, 0x1f, 0xa1, 0x24, 0x4c,
|
||||||
|
0x8d, 0x3f, 0xbb, 0xf5, 0x28, 0xbf, 0x8a, 0x7e, 0x64, 0xcb, 0x14, 0x03,
|
||||||
|
0x7c, 0x32, 0x72, 0xd7, 0x71, 0xc3, 0x27, 0xfe, 0xdb, 0x9e, 0x29, 0x64,
|
||||||
|
0xa7, 0xd0, 0x52, 0x88, 0xa8, 0x35, 0x9f, 0xc2, 0x92, 0x17, 0xd8, 0x6e,
|
||||||
|
0x5e, 0x1b, 0xe5, 0xa3, 0xdf, 0xee, 0xc6, 0x00, 0xf3, 0xdc, 0xba, 0x49,
|
||||||
|
0x7c, 0xb4, 0x4e, 0x69, 0xee, 0x9e, 0x05, 0x6a, 0x6c, 0xdd, 0xfb, 0x90,
|
||||||
|
0xa2, 0xb7, 0x84, 0xea, 0x32, 0xca, 0xec, 0x15, 0x1c, 0x24, 0xd6, 0x60,
|
||||||
|
0xef, 0xf2, 0x2f, 0x4b, 0x87, 0x46, 0xeb, 0xe1, 0x89, 0x78, 0xba, 0xd0,
|
||||||
|
0xcd, 0xd7, 0x41, 0x01, 0xf9, 0xb4, 0x2c, 0x33, 0x34, 0xb1, 0x07, 0xe5,
|
||||||
|
0x9f, 0x0e, 0xb3, 0xc9, 0x60, 0xc1, 0x3c, 0xbd, 0x4e, 0x58, 0x08, 0x05,
|
||||||
|
0x3b, 0xf8, 0x29, 0x0c, 0x26, 0x68, 0x18, 0xaf, 0x84, 0x55, 0xc0, 0xd1,
|
||||||
|
0xfb, 0x08, 0xac, 0x40, 0x04, 0xf8, 0xd0, 0x73, 0x54, 0x64, 0x0f, 0xbd,
|
||||||
|
0x1f, 0x40, 0xd8, 0x16, 0xa4, 0x0b, 0x9a, 0xd9, 0x4e, 0x0e, 0xcb, 0x14,
|
||||||
|
0xe4, 0xec, 0xa3, 0xb0, 0xef, 0x45, 0xeb, 0x03, 0xdf, 0x62, 0x9f, 0x5d,
|
||||||
|
0x4a, 0x84, 0x12, 0x78, 0xb0, 0x3b, 0x94, 0x69, 0xd0, 0x5f, 0x99, 0x40,
|
||||||
|
0x1e, 0x82, 0x0b, 0x9e, 0x73, 0x45, 0xd9, 0x6d, 0xc3, 0x92, 0x22, 0x3e,
|
||||||
|
0x3e, 0x93, 0x41, 0x46, 0x64, 0xcd, 0xe8, 0x09, 0x8f, 0xe1, 0x13, 0xfb,
|
||||||
|
0xd5, 0xe4, 0xbc, 0x70, 0xdd, 0x6c, 0x98, 0xe8};
|
||||||
|
|
||||||
|
const size_t kGoldenDataSize = sizeof(kGoldenDataSize);
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::vector<uint8_t> DataSource::Get(size_t size) {
|
||||||
|
std::vector<uint8_t> buffer(size);
|
||||||
|
|
||||||
|
size_t write_head = 0;
|
||||||
|
|
||||||
|
while (write_head < size) {
|
||||||
|
const size_t remaining_read = kGoldenDataSize - read_head_;
|
||||||
|
const size_t remaining_write = size - write_head;
|
||||||
|
|
||||||
|
// Figure out how much more we can write. If we are nearing the end of the
|
||||||
|
// read buffer, we have to cut short our read so that we can loop back to
|
||||||
|
// the start of the read buffer.
|
||||||
|
size_t next_write = std::min(remaining_read, remaining_write);
|
||||||
|
memcpy(buffer.data() + write_head, kGoldenData + read_head_, next_write);
|
||||||
|
|
||||||
|
// Move both the read and write heads forward. Make sure to loop the read
|
||||||
|
// head back to the start so that we we can restart reading when necessary.
|
||||||
|
write_head += next_write;
|
||||||
|
read_head_ = (read_head_ + next_write) % kGoldenDataSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace widevine
|
||||||
23
benchmarking/data_source.h
Normal file
23
benchmarking/data_source.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#ifndef WHITEBOX_BENCHMARKING_DATA_SOURCE_H_
|
||||||
|
#define WHITEBOX_BENCHMARKING_DATA_SOURCE_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace widevine {
|
||||||
|
|
||||||
|
class DataSource {
|
||||||
|
public:
|
||||||
|
std::vector<uint8_t> Get(size_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t read_head_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace widevine
|
||||||
|
|
||||||
|
#endif // WHITEBOX_BENCHMARKING_DATA_SOURCE_H_
|
||||||
78
benchmarking/measurements.cc
Normal file
78
benchmarking/measurements.cc
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "benchmarking/measurements.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "base/logging.h"
|
||||||
|
|
||||||
|
namespace widevine {
|
||||||
|
namespace {
|
||||||
|
size_t RoundUp(size_t num, size_t denum) {
|
||||||
|
return (num + denum - 1) / denum;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Timer::Reset() {
|
||||||
|
start_ = Clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
Period Timer::Get() const {
|
||||||
|
const auto now = Clock::now();
|
||||||
|
return std::chrono::duration_cast<Period>(now - start_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Throughput::Throughput() : bytes(0), microseconds(0), bits_per_second(0) {}
|
||||||
|
|
||||||
|
Throughput::Throughput(const Period& duration, size_t bytes) {
|
||||||
|
this->bytes = bytes;
|
||||||
|
microseconds = duration.count();
|
||||||
|
|
||||||
|
bits_per_second = 0;
|
||||||
|
|
||||||
|
if (microseconds > 0) {
|
||||||
|
// Make sure to only do one division to ensure that we are not loosing too
|
||||||
|
// much information as we are avoiding floating-point values.
|
||||||
|
bits_per_second = (bytes * 8 * 1000 * 1000) / microseconds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Period& Sampler::Percentile::Get(size_t percentile) const {
|
||||||
|
// Nearest-rank method:
|
||||||
|
// https://en.wikipedia.org/wiki/Percentile#The_nearest-rank_method
|
||||||
|
const size_t index = RoundUp(samples_.size() * percentile, 100);
|
||||||
|
|
||||||
|
// The index will be from 1 to N, but we need it to be 0 to N-1.
|
||||||
|
return samples_[index - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sampler::Push(const Period& period) {
|
||||||
|
samples_.push_back(period);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrettyPrint(const std::string& title,
|
||||||
|
const Throughput& throughput,
|
||||||
|
size_t bytes_per_call) {
|
||||||
|
LOG(INFO) << title;
|
||||||
|
LOG(INFO) << " bytes per call: " << bytes_per_call;
|
||||||
|
LOG(INFO) << " bytes: " << throughput.bytes;
|
||||||
|
LOG(INFO) << " microseconds: " << throughput.microseconds;
|
||||||
|
LOG(INFO) << " bits per second: " << throughput.bits_per_second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrettyPrint(const std::string& title,
|
||||||
|
const Sampler& samples,
|
||||||
|
size_t per_sample_size) {
|
||||||
|
const auto& percentiles = samples.Percentiles();
|
||||||
|
|
||||||
|
LOG(INFO) << title;
|
||||||
|
LOG(INFO) << " Sample Size: " << samples.SampleSize() << " ("
|
||||||
|
<< per_sample_size << " bytes)";
|
||||||
|
LOG(INFO) << " Min (0%): " << percentiles.Get(0).count() << " us";
|
||||||
|
LOG(INFO) << " 25%: " << percentiles.Get(25).count() << " us";
|
||||||
|
LOG(INFO) << " Median (50%): " << percentiles.Get(50).count() << " us";
|
||||||
|
LOG(INFO) << " 75%: " << percentiles.Get(75).count() << " us";
|
||||||
|
LOG(INFO) << " Max (100%): " << percentiles.Get(100).count() << " us";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace widevine
|
||||||
72
benchmarking/measurements.h
Normal file
72
benchmarking/measurements.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
#ifndef WHITEBOX_BENCHMARKING_MEASUREMENT_H_
|
||||||
|
#define WHITEBOX_BENCHMARKING_MEASUREMENT_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <chrono>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace widevine {
|
||||||
|
|
||||||
|
using Clock = std::chrono::high_resolution_clock;
|
||||||
|
using Period = std::chrono::microseconds;
|
||||||
|
|
||||||
|
class Timer {
|
||||||
|
public:
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
Period Get() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Clock::time_point start_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Throughput {
|
||||||
|
size_t bytes;
|
||||||
|
uint64_t microseconds;
|
||||||
|
uint64_t bits_per_second;
|
||||||
|
|
||||||
|
Throughput();
|
||||||
|
Throughput(const Period& duration, size_t bytes);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Sampler {
|
||||||
|
public:
|
||||||
|
class Percentile {
|
||||||
|
public:
|
||||||
|
Percentile(const std::vector<Period>& samples) : samples_(samples) {
|
||||||
|
std::sort(samples_.begin(), samples_.end());
|
||||||
|
};
|
||||||
|
|
||||||
|
const Period& Get(size_t percentile) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Period> samples_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Push(const Period& period);
|
||||||
|
|
||||||
|
Percentile Percentiles() const { return Percentile(samples_); }
|
||||||
|
|
||||||
|
size_t SampleSize() const { return samples_.size(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Period> samples_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void PrettyPrint(const std::string& title,
|
||||||
|
const Throughput& throughput,
|
||||||
|
size_t bytes_per_call);
|
||||||
|
|
||||||
|
void PrettyPrint(const std::string& title,
|
||||||
|
const Sampler& samples,
|
||||||
|
size_t sample_input_size);
|
||||||
|
|
||||||
|
} // namespace widevine
|
||||||
|
|
||||||
|
#endif // WHITEBOX_BENCHMARKING_MEASUREMENT_H_
|
||||||
@@ -59,6 +59,16 @@ cc_test(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "aead_whitebox_benchmark",
|
||||||
|
size = "small",
|
||||||
|
deps = [
|
||||||
|
":aead_whitebox",
|
||||||
|
":test_data",
|
||||||
|
"//api:aead_whitebox_benchmark",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
cc_test(
|
cc_test(
|
||||||
name = "license_whitebox_test",
|
name = "license_whitebox_test",
|
||||||
size = "small",
|
size = "small",
|
||||||
@@ -69,6 +79,16 @@ cc_test(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "license_whitebox_benchmark",
|
||||||
|
size = "small",
|
||||||
|
deps = [
|
||||||
|
":license_whitebox",
|
||||||
|
":test_data",
|
||||||
|
"//api:license_whitebox_benchmark",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "memory_util",
|
name = "memory_util",
|
||||||
srcs = ["memory_util.cc"],
|
srcs = ["memory_util.cc"],
|
||||||
|
|||||||
@@ -54,31 +54,14 @@ struct WB_License_Whitebox {
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Secret string value. For simplicity the pattern will just be 0xAAAAAAAA which
|
// For simplicity we use a basic pad but we use a different byte for each
|
||||||
// is xor'd to the buffer, and removed by xor'ing it a second time.
|
// position as we need to support abirtary indexes and we want to make sure that
|
||||||
|
// a wrong index will actually trigger a failure.
|
||||||
const uint8_t kSecretStringPattern[] = {
|
const uint8_t kSecretStringPattern[] = {
|
||||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||||
};
|
};
|
||||||
const size_t kSecretStringPatternSize = sizeof(kSecretStringPattern);
|
const size_t kSecretStringPatternSize = sizeof(kSecretStringPattern);
|
||||||
static_assert(kSecretStringPatternSize == AES_BLOCK_SIZE,
|
|
||||||
"Secret string must be AES_BLOCK_SIZE.");
|
|
||||||
|
|
||||||
void ApplyPattern(const uint8_t* input_buffer,
|
|
||||||
size_t input_buffer_size,
|
|
||||||
const uint8_t* pattern,
|
|
||||||
size_t pattern_size,
|
|
||||||
uint8_t* output_buffer) {
|
|
||||||
DCHECK(input_buffer);
|
|
||||||
DCHECK(pattern);
|
|
||||||
DCHECK(output_buffer);
|
|
||||||
DCHECK_GT(pattern_size, 0u);
|
|
||||||
DCHECK_EQ(input_buffer_size % pattern_size, 0u);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < input_buffer_size; ++i) {
|
|
||||||
output_buffer[i] = input_buffer[i] ^ pattern[i % pattern_size];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ContentKey* FindKey(const WB_License_Whitebox* whitebox,
|
const ContentKey* FindKey(const WB_License_Whitebox* whitebox,
|
||||||
const uint8_t* id,
|
const uint8_t* id,
|
||||||
@@ -681,22 +664,31 @@ WB_Result WB_License_MaskedDecrypt(const WB_License_Whitebox* whitebox,
|
|||||||
|
|
||||||
// Trivial implementation that simply takes the decrypted output and XORs it
|
// Trivial implementation that simply takes the decrypted output and XORs it
|
||||||
// with a fixed pattern. |output|'s size is based on |masked_output_data| so
|
// with a fixed pattern. |output|'s size is based on |masked_output_data| so
|
||||||
// we shouldn't need to worry about overflow.
|
// we shouldn't need to worry about overflow. This logic must be mirrored in
|
||||||
ApplyPattern(output.data(), output.size(), kSecretStringPattern,
|
// Unmask().
|
||||||
kSecretStringPatternSize, masked_output_data);
|
const uint8_t* mask = kSecretStringPattern;
|
||||||
|
const size_t mask_size = kSecretStringPatternSize;
|
||||||
|
for (size_t i = 0; i < output.size(); ++i) {
|
||||||
|
masked_output_data[i] = output[i] ^ mask[i % mask_size];
|
||||||
|
}
|
||||||
|
|
||||||
return WB_RESULT_OK;
|
return WB_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WB_License_Unmask(const uint8_t* secret_string,
|
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,
|
size_t secret_string_size,
|
||||||
uint8_t* buffer,
|
uint8_t* unmasked_data) {
|
||||||
size_t buffer_size) {
|
|
||||||
// No return code, so only check if parameters are valid.
|
// No return code, so only check if parameters are valid.
|
||||||
|
DCHECK(masked_data);
|
||||||
DCHECK(secret_string);
|
DCHECK(secret_string);
|
||||||
DCHECK(secret_string_size);
|
DCHECK(unmasked_data);
|
||||||
DCHECK(buffer);
|
|
||||||
DCHECK(buffer_size);
|
|
||||||
|
|
||||||
ApplyPattern(buffer, buffer_size, secret_string, secret_string_size, buffer);
|
for (size_t local_i = 0; local_i < size; local_i++) {
|
||||||
|
const size_t global_i = offset + local_i;
|
||||||
|
const uint8_t mask = secret_string[global_i % secret_string_size];
|
||||||
|
unmasked_data[local_i] = masked_data[global_i] ^ mask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user