Widevine MediaCas client code that works with Android R
This commit is contained in:
38
oemcrypto/test/Android.bp
Normal file
38
oemcrypto/test/Android.bp
Normal file
@@ -0,0 +1,38 @@
|
||||
cc_binary {
|
||||
name: "oemcrypto_cas_test",
|
||||
proprietary: true,
|
||||
srcs: [
|
||||
"oec_device_features.cpp",
|
||||
"oec_decrypt_fallback_chain.cpp",
|
||||
"oec_key_deriver.cpp",
|
||||
"oec_session_util.cpp",
|
||||
"oemcrypto_corpus_generator_helper.cpp",
|
||||
"oemcrypto_session_tests_helper.cpp",
|
||||
"oemcrypto_test.cpp",
|
||||
"oemcrypto_test_android.cpp",
|
||||
"oemcrypto_test_main.cpp",
|
||||
"wvcrc.cpp",
|
||||
"test_sleep.cpp",
|
||||
],
|
||||
header_libs: [
|
||||
"//vendor/widevine/libwvmediacas/oemcrypto:oemcastroheaders",
|
||||
"media_plugin_headers",
|
||||
],
|
||||
include_dirs: [
|
||||
"vendor/widevine/libwvmediacas/oemcrypto/odk/include",
|
||||
],
|
||||
static_libs: [
|
||||
"//vendor/widevine/libwvmediacas/wvutil:libcasutil",
|
||||
"//vendor/widevine/libwvmediacas/plugin:libwvcasplugins",
|
||||
"libgmock",
|
||||
"libgtest",
|
||||
"libwvcas_odk",
|
||||
"libwvcas_kdo",
|
||||
],
|
||||
shared_libs: [
|
||||
"//vendor/widevine/libwvmediacas/oemcrypto/ref:libcasoemcrypto",
|
||||
"libcrypto",
|
||||
"libutils",
|
||||
"liblog",
|
||||
],
|
||||
}
|
||||
23
oemcrypto/test/Android.mk
Normal file
23
oemcrypto/test/Android.mk
Normal file
@@ -0,0 +1,23 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
vendor/widevine/libwvdrmengine/cdm/util/include \
|
||||
|
||||
LOCAL_MODULE:=oemcrypto_test
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
LOCAL_MODULE_OWNER := widevine
|
||||
LOCAL_PROPRIETARY_MODULE := true
|
||||
|
||||
# When built, explicitly put it in the DATA/nativetest directory.
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
|
||||
|
||||
ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
|
||||
LOCAL_MODULE_TARGET_ARCH := arm x86 mips
|
||||
endif
|
||||
|
||||
include $(LOCAL_PATH)/common.mk
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
13
oemcrypto/test/XtsTest.mk
Normal file
13
oemcrypto/test/XtsTest.mk
Normal file
@@ -0,0 +1,13 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := XtsOEMCryptoTestCases
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)
|
||||
|
||||
LOCAL_XTS_TEST_PACKAGE := google.oemcrypto
|
||||
|
||||
include $(LOCAL_PATH)/common.mk
|
||||
|
||||
include $(BUILD_XTS_EXECUTABLE)
|
||||
53
oemcrypto/test/common.mk
Normal file
53
oemcrypto/test/common.mk
Normal file
@@ -0,0 +1,53 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
ifeq ($(filter mips mips64, $(TARGET_ARCH)),)
|
||||
# Tests need to be compatible with devices that do not support gnu hash-style
|
||||
LOCAL_LDFLAGS+=-Wl,--hash-style=both
|
||||
endif
|
||||
|
||||
# The unit tests can access v15 functions through the dynamic adapter:
|
||||
LOCAL_CFLAGS += -DTEST_OEMCRYPTO_V15
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
oec_device_features.cpp \
|
||||
oec_decrypt_fallback_chain.cpp \
|
||||
oec_key_deriver.cpp \
|
||||
oec_session_util.cpp \
|
||||
oemcrypto_corpus_generator_helper.cpp \
|
||||
oemcrypto_session_tests_helper.cpp \
|
||||
oemcrypto_test.cpp \
|
||||
oemcrypto_test_android.cpp \
|
||||
oemcrypto_test_main.cpp \
|
||||
wvcrc.cpp \
|
||||
../../cdm/util/test/test_sleep.cpp \
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH)/../include \
|
||||
$(LOCAL_PATH)/../odk/include \
|
||||
$(LOCAL_PATH)/../odk/kdo/include \
|
||||
$(LOCAL_PATH)/../ref/src \
|
||||
vendor/widevine/libwvdrmengine/cdm/core/include \
|
||||
vendor/widevine/libwvdrmengine/cdm/util/include \
|
||||
vendor/widevine/libwvdrmengine/cdm/util/test \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libcdm \
|
||||
libcdm_utils \
|
||||
libcrypto_static \
|
||||
libgtest \
|
||||
libgtest_main \
|
||||
libwvlevel3 \
|
||||
libcdm_protos \
|
||||
libcdm_utils \
|
||||
libwv_kdo \
|
||||
libwv_odk \
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbase \
|
||||
libdl \
|
||||
liblog \
|
||||
libmedia_omx \
|
||||
libprotobuf-cpp-lite \
|
||||
libstagefright_foundation \
|
||||
libutils \
|
||||
libz \
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
(c020:0d112d7ea200;
|
||||
@@ -0,0 +1 @@
|
||||
(e2!0;u
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202fb02570640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231180120002a0c313838363738373430350000
|
||||
@@ -0,0 +1 @@
|
||||
(2dea200;u
|
||||
@@ -0,0 +1 @@
|
||||
0a4c020:0d1190d79fef02570640bd22ef44b2d7e3912250a200
|
||||
@@ -0,0 +1 @@
|
||||
e2!0;u
|
||||
@@ -0,0 +1 @@
|
||||
e
|
||||
@@ -0,0 +1 @@
|
||||
(ea200;u
|
||||
@@ -0,0 +1 @@
|
||||
0a(c020:0d112d7ea200;
|
||||
@@ -0,0 +1 @@
|
||||
0a4c000000200:0101907d9ffde02570640bd22ef44b2d7e3912250a230a1407363534333231180120002a0c313838363738373430350000
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
0a4c000000220:01019dd79fef02570640bd22ef44b2d7e3912250a200
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
e;
|
||||
@@ -0,0 +1 @@
|
||||
0a4c000000200:010197d9ffde02570640bd22ef44b2d7e3912250a230a1407363534333231180120002a0c313838363738373430350000
|
||||
@@ -0,0 +1 @@
|
||||
0a4c00000020000101907d9ffde02570640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231180120002a0c313838363738373430350000
|
||||
@@ -0,0 +1 @@
|
||||
0a4c020:0d112d7e3912250a200;
|
||||
@@ -0,0 +1 @@
|
||||
0a4c08001248000000020000101907d9ffde02570640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231180120002a0c313838363738373430350000
|
||||
@@ -0,0 +1 @@
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
e2;
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231180120002a0c313838363738373430350000
|
||||
50
oemcrypto/test/fuzz_tests/README.md
Normal file
50
oemcrypto/test/fuzz_tests/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# OEMCRYPTO Fuzzing
|
||||
|
||||
## Objective
|
||||
|
||||
* Run fuzzing on OEMCrypto public APIs on linux using google
|
||||
supported clusterfuzz infrastructure to find security vulnerabilities.
|
||||
|
||||
## Generate Corpus
|
||||
|
||||
* Once the fuzzer scripts are ready and running continuously using clusterfuzz
|
||||
or android infrastructure, we can measure the efficiency of fuzzers by looking
|
||||
at code coverage and number of new features that have been discovered by fuzzer
|
||||
scripts here Fuzz script statistics.
|
||||
|
||||
A fuzzer which tries to start from random inputs and figure out intelligent
|
||||
inputs to crash the libraries can be time consuming and not effective.
|
||||
A way to make fuzzers more effective is by providing a set of valid
|
||||
and invalid inputs of the library so that fuzzer can use those as a starting point.
|
||||
These sets of valid and invalid inputs are called corpus.
|
||||
|
||||
The idea is to run OEMCrypto unit tests and read required data into binary corpus
|
||||
files before calling into respective OEMCrypto APIs under test. Writing corpus data
|
||||
to binary files is controlled by environment variable SHOULD_GENERATE_CORPUS.
|
||||
|
||||
|
||||
### Get OEMCrypto and Build OEMCrypto unit tests to generate corpus:
|
||||
|
||||
* Install Pre-requisites
|
||||
|
||||
```shell
|
||||
$ sudo apt-get install gyp ninja-build
|
||||
```
|
||||
|
||||
* download cdm source code (including ODK & OEMCrypto unit tests):
|
||||
|
||||
```shell
|
||||
$ git clone sso://widevine-internal/cdm
|
||||
```
|
||||
|
||||
* Build OEMCrypto unit tests and run with --generate_corpus flag to
|
||||
generate corpus files:
|
||||
|
||||
```shell
|
||||
$ cd /path/to/cdm/repo
|
||||
$ export CDM_DIR=/path/to/cdm/repo
|
||||
$ export PATH_TO_CDM_DIR=.
|
||||
$ gyp --format=ninja --depth=$(pwd) oemcrypto/oemcrypto_unittests.gyp
|
||||
$ ninja -C out/Default/
|
||||
$ ./out/Default/oemcrypto_unittests --generate_corpus
|
||||
```
|
||||
8
oemcrypto/test/fuzz_tests/oemcrypto_fuzz_helper.cc
Normal file
8
oemcrypto/test/fuzz_tests/oemcrypto_fuzz_helper.cc
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
|
||||
namespace wvoec {
|
||||
void RedirectStdoutToFile() { freopen("log.txt", "a", stdout); }
|
||||
} // namespace wvoec
|
||||
73
oemcrypto/test/fuzz_tests/oemcrypto_fuzz_helper.h
Normal file
73
oemcrypto/test/fuzz_tests/oemcrypto_fuzz_helper.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
#ifndef OEMCRYPTO_FUZZ_HELPER_H_
|
||||
#define OEMCRYPTO_FUZZ_HELPER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "OEMCryptoCAS.h"
|
||||
#include "oec_device_features.h"
|
||||
#include "oec_session_util.h"
|
||||
#include "oemcrypto_corpus_generator_helper.h"
|
||||
#include "oemcrypto_session_tests_helper.h"
|
||||
namespace wvoec {
|
||||
// Initial setup to create a valid OEMCrypto state such as initializing crypto
|
||||
// firmware/hardware, installing golden key box etc. in order to fuzz
|
||||
// OEMCrypto APIs.
|
||||
class InitializeFuzz : public SessionUtil {
|
||||
public:
|
||||
InitializeFuzz() {
|
||||
wvoec::global_features.Initialize();
|
||||
OEMCrypto_SetSandbox(kTestSandbox, sizeof(kTestSandbox));
|
||||
OEMCrypto_Initialize();
|
||||
EnsureTestKeys();
|
||||
}
|
||||
|
||||
~InitializeFuzz() { OEMCrypto_Terminate(); }
|
||||
};
|
||||
|
||||
class OEMCryptoLicenseAPIFuzz : public InitializeFuzz {
|
||||
public:
|
||||
OEMCryptoLicenseAPIFuzz() : license_messages_(&session_) {
|
||||
session_.open();
|
||||
InstallTestRSAKey(&session_);
|
||||
session_.GenerateNonce();
|
||||
}
|
||||
|
||||
~OEMCryptoLicenseAPIFuzz() {
|
||||
session_.close();
|
||||
}
|
||||
|
||||
LicenseRoundTrip& license_messages() { return license_messages_; }
|
||||
|
||||
private:
|
||||
Session session_;
|
||||
LicenseRoundTrip license_messages_;
|
||||
};
|
||||
|
||||
class OEMCryptoProvisioningAPIFuzz : public InitializeFuzz {
|
||||
public:
|
||||
OEMCryptoProvisioningAPIFuzz()
|
||||
: provisioning_messages_(&session_, encoded_rsa_key_) {
|
||||
// Opens a session and Generates Nonce.
|
||||
provisioning_messages_.PrepareSession(keybox_);
|
||||
}
|
||||
|
||||
~OEMCryptoProvisioningAPIFuzz() { session_.close(); }
|
||||
|
||||
ProvisioningRoundTrip& provisioning_messages() {
|
||||
return provisioning_messages_;
|
||||
}
|
||||
|
||||
private:
|
||||
Session session_;
|
||||
ProvisioningRoundTrip provisioning_messages_;
|
||||
};
|
||||
|
||||
// Redirect printf and log statements from oemcrypto functions to a file to
|
||||
// reduce noise
|
||||
void RedirectStdoutToFile();
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // OEMCRYPTO_FUZZ_HELPER_H_
|
||||
36
oemcrypto/test/fuzz_tests/oemcrypto_generate_signature.cc
Normal file
36
oemcrypto/test/fuzz_tests/oemcrypto_generate_signature.cc
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "properties.h"
|
||||
#include "oemcrypto_session_tests_helper.h"
|
||||
|
||||
using namespace wvoec;
|
||||
|
||||
static bool is_init = false;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
SessionUtil session_helper;
|
||||
if (!is_init) {
|
||||
wvoec::global_features.Initialize();
|
||||
wvoec::global_features.RestrictFilter("*");
|
||||
wvutil::Properties::Init();
|
||||
is_init = true;
|
||||
}
|
||||
|
||||
OEMCrypto_Initialize();
|
||||
session_helper.EnsureTestKeys();
|
||||
|
||||
Session s;
|
||||
s.open();
|
||||
s.GenerateDerivedKeysFromKeybox(session_helper.keybox_);
|
||||
|
||||
static const uint32_t SignatureBufferMaxLength = size;
|
||||
vector<uint8_t> signature(SignatureBufferMaxLength);
|
||||
size_t signature_length = signature.size();
|
||||
|
||||
OEMCryptoResult sts;
|
||||
sts = OEMCrypto_GenerateSignature(s.session_id(), data, size,
|
||||
&signature[0], &signature_length);
|
||||
|
||||
s.close();
|
||||
OEMCrypto_Terminate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
24
oemcrypto/test/fuzz_tests/oemcrypto_load_license_fuzz.cc
Normal file
24
oemcrypto/test/fuzz_tests/oemcrypto_load_license_fuzz.cc
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
|
||||
namespace wvoec {
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// Redirect printf and log statements from oemcrypto functions to a file to
|
||||
// reduce noise
|
||||
RedirectStdoutToFile();
|
||||
if (size < sizeof(ODK_ParsedLicense) + sizeof(MessageData)) {
|
||||
return 0;
|
||||
}
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
license_api_fuzz.license_messages().SignAndVerifyRequest();
|
||||
// Interpreting input fuzz data as unencrypted (core_response + license
|
||||
// message data) from license server.
|
||||
license_api_fuzz.license_messages().InjectFuzzedResponseData(data, size);
|
||||
license_api_fuzz.license_messages().EncryptAndSignResponse();
|
||||
license_api_fuzz.license_messages().LoadResponse();
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// Redirect printf and log statements from oemcrypto functions to a file to
|
||||
// reduce noise
|
||||
RedirectStdoutToFile();
|
||||
if (size < sizeof(ODK_ParsedProvisioning) + sizeof(RSAPrivateKeyMessage)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OEMCryptoProvisioningAPIFuzz provisioning_api_fuzz;
|
||||
provisioning_api_fuzz.provisioning_messages().SignAndVerifyRequest();
|
||||
// Interpreting input fuzz data as unencrypted(core_response + provisioning
|
||||
// message data) from provisioning server.
|
||||
provisioning_api_fuzz.provisioning_messages().InjectFuzzedResponseData(data,
|
||||
size);
|
||||
provisioning_api_fuzz.provisioning_messages().EncryptAndSignResponse();
|
||||
provisioning_api_fuzz.provisioning_messages().LoadResponse();
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
10
oemcrypto/test/fuzz_tests/sample_test.cc
Normal file
10
oemcrypto/test/fuzz_tests/sample_test.cc
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size > 0 && data[0] == 'H')
|
||||
if (size > 1 && data[1] == 'I')
|
||||
if (size > 2 && data[2] == '!')
|
||||
__builtin_trap();
|
||||
return 0;
|
||||
}
|
||||
178
oemcrypto/test/oec_decrypt_fallback_chain.cpp
Normal file
178
oemcrypto/test/oec_decrypt_fallback_chain.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "oec_decrypt_fallback_chain.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "oemcrypto_types.h"
|
||||
#include "string_conversions.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void advance_dest_buffer(OEMCrypto_DestBufferDesc* dest_buffer, size_t bytes) {
|
||||
switch (dest_buffer->type) {
|
||||
case OEMCrypto_BufferType_Clear:
|
||||
dest_buffer->buffer.clear.address += bytes;
|
||||
dest_buffer->buffer.clear.address_length -= bytes;
|
||||
break;
|
||||
|
||||
case OEMCrypto_BufferType_Secure:
|
||||
dest_buffer->buffer.secure.offset += bytes;
|
||||
break;
|
||||
|
||||
case OEMCrypto_BufferType_Direct:
|
||||
// Nothing to do for this buffer type.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void advance_iv_ctr(uint8_t (*subsample_iv)[wvoec::KEY_IV_SIZE], size_t bytes) {
|
||||
uint64_t counter;
|
||||
constexpr size_t half_iv_size = wvoec::KEY_IV_SIZE / 2;
|
||||
memcpy(&counter, &(*subsample_iv)[half_iv_size], half_iv_size);
|
||||
|
||||
const size_t increment =
|
||||
bytes / wvoec::AES_128_BLOCK_SIZE; // The truncation here is intentional
|
||||
counter = wvutil::htonll64(wvutil::ntohll64(counter) + increment);
|
||||
|
||||
memcpy(&(*subsample_iv)[half_iv_size], &counter, half_iv_size);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// Decrypts the given array of samples. Handles fallback behavior correctly if
|
||||
// the OEMCrypto implementation does not accept multiple samples.
|
||||
OEMCryptoResult DecryptFallbackChain::Decrypt(
|
||||
OEMCrypto_SESSION session_id, const OEMCrypto_SampleDescription* samples,
|
||||
size_t samples_length, OEMCryptoCipherMode cipher_mode,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern) {
|
||||
OEMCryptoResult sts =
|
||||
OEMCrypto_DecryptCENC(session_id, samples, samples_length, pattern);
|
||||
|
||||
// No need for a fallback. Abort early.
|
||||
if (sts != OEMCrypto_ERROR_BUFFER_TOO_LARGE) return sts;
|
||||
|
||||
// Fall back to decrypting individual samples.
|
||||
for (size_t i = 0; i < samples_length; ++i) {
|
||||
sts = DecryptSample(session_id, samples[i], cipher_mode, pattern);
|
||||
if (sts != OEMCrypto_SUCCESS) return sts;
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
// Decrypts the given sample. Handles fallback behavior correctly if the
|
||||
// OEMCrypto implementation does not accept full samples.
|
||||
OEMCryptoResult DecryptFallbackChain::DecryptSample(
|
||||
OEMCrypto_SESSION session_id, const OEMCrypto_SampleDescription& sample,
|
||||
OEMCryptoCipherMode cipher_mode,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern) {
|
||||
OEMCryptoResult sts = OEMCrypto_DecryptCENC(session_id, &sample, 1, pattern);
|
||||
|
||||
// No need for a fallback. Abort early.
|
||||
if (sts != OEMCrypto_ERROR_BUFFER_TOO_LARGE) return sts;
|
||||
|
||||
// Fall back to decrypting individual subsamples.
|
||||
OEMCrypto_SampleDescription fake_sample = sample;
|
||||
for (size_t i = 0; i < sample.subsamples_length; ++i) {
|
||||
const OEMCrypto_SubSampleDescription& subsample = sample.subsamples[i];
|
||||
|
||||
const size_t length =
|
||||
subsample.num_bytes_clear + subsample.num_bytes_encrypted;
|
||||
fake_sample.buffers.input_data_length = length;
|
||||
fake_sample.subsamples = &subsample;
|
||||
fake_sample.subsamples_length = 1;
|
||||
|
||||
sts = DecryptSubsample(session_id, fake_sample, pattern);
|
||||
if (sts != OEMCrypto_SUCCESS) return sts;
|
||||
|
||||
fake_sample.buffers.input_data += length;
|
||||
advance_dest_buffer(&fake_sample.buffers.output_descriptor, length);
|
||||
if (cipher_mode == OEMCrypto_CipherMode_CTR) {
|
||||
advance_iv_ctr(&fake_sample.iv,
|
||||
subsample.block_offset + subsample.num_bytes_encrypted);
|
||||
}
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
// Decrypts the given subsample. Handles fallback behavior correctly if the
|
||||
// OEMCrypto implementation does not accept full subsamples.
|
||||
OEMCryptoResult DecryptFallbackChain::DecryptSubsample(
|
||||
OEMCrypto_SESSION session_id, const OEMCrypto_SampleDescription& sample,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern) {
|
||||
OEMCryptoResult sts = OEMCrypto_DecryptCENC(session_id, &sample, 1, pattern);
|
||||
|
||||
// No need for a fallback. Abort early.
|
||||
if (sts != OEMCrypto_ERROR_BUFFER_TOO_LARGE) return sts;
|
||||
|
||||
// Fall back to decrypting individual subsample halves.
|
||||
const OEMCrypto_SubSampleDescription& subsample = sample.subsamples[0];
|
||||
OEMCrypto_SampleDescription fake_sample = sample;
|
||||
OEMCrypto_SubSampleDescription fake_subsample;
|
||||
fake_sample.subsamples = &fake_subsample;
|
||||
fake_sample.subsamples_length = 1;
|
||||
|
||||
if (subsample.num_bytes_clear > 0) {
|
||||
fake_sample.buffers.input_data_length = subsample.num_bytes_clear;
|
||||
fake_subsample.num_bytes_clear = subsample.num_bytes_clear;
|
||||
fake_subsample.num_bytes_encrypted = 0;
|
||||
fake_subsample.block_offset = 0;
|
||||
|
||||
fake_subsample.subsample_flags = 0;
|
||||
if (subsample.subsample_flags & OEMCrypto_FirstSubsample)
|
||||
fake_subsample.subsample_flags |= OEMCrypto_FirstSubsample;
|
||||
if (subsample.subsample_flags & OEMCrypto_LastSubsample &&
|
||||
subsample.num_bytes_encrypted == 0)
|
||||
fake_subsample.subsample_flags |= OEMCrypto_LastSubsample;
|
||||
|
||||
sts = DecryptSubsampleHalf(session_id, fake_sample, pattern);
|
||||
if (sts != OEMCrypto_SUCCESS) return sts;
|
||||
|
||||
// Advance the buffers for the other half, in case they're needed.
|
||||
fake_sample.buffers.input_data += subsample.num_bytes_clear;
|
||||
advance_dest_buffer(&fake_sample.buffers.output_descriptor,
|
||||
subsample.num_bytes_clear);
|
||||
}
|
||||
|
||||
if (subsample.num_bytes_encrypted > 0) {
|
||||
fake_sample.buffers.input_data_length = subsample.num_bytes_encrypted;
|
||||
fake_subsample.num_bytes_clear = 0;
|
||||
fake_subsample.num_bytes_encrypted = subsample.num_bytes_encrypted;
|
||||
fake_subsample.block_offset = subsample.block_offset;
|
||||
|
||||
fake_subsample.subsample_flags = 0;
|
||||
if (subsample.subsample_flags & OEMCrypto_FirstSubsample &&
|
||||
subsample.num_bytes_clear == 0)
|
||||
fake_subsample.subsample_flags |= OEMCrypto_FirstSubsample;
|
||||
if (subsample.subsample_flags & OEMCrypto_LastSubsample)
|
||||
fake_subsample.subsample_flags |= OEMCrypto_LastSubsample;
|
||||
|
||||
sts = DecryptSubsampleHalf(session_id, fake_sample, pattern);
|
||||
if (sts != OEMCrypto_SUCCESS) return sts;
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
// Decrypts the given subsample half. There is no fallback behavior after this;
|
||||
// an OEMCrypto_ERROR_BUFFER_TOO_LARGE produced here will be returned to the
|
||||
// caller.
|
||||
OEMCryptoResult DecryptFallbackChain::DecryptSubsampleHalf(
|
||||
OEMCrypto_SESSION session_id, const OEMCrypto_SampleDescription& sample,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern) {
|
||||
return OEMCrypto_DecryptCENC(session_id, &sample, 1, pattern);
|
||||
// In a real CDM, you would want some fallback here to handle the case where
|
||||
// the buffer is too big for the OEMCrypto implementation. But in the case of
|
||||
// the tests, we won't be passing a buffer that's too big unless we are trying
|
||||
// to test that failure condition, so there's no need to handle that case
|
||||
// here.
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
59
oemcrypto/test/oec_decrypt_fallback_chain.h
Normal file
59
oemcrypto/test/oec_decrypt_fallback_chain.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#ifndef CDM_OEC_DECRYPT_FALLBACK_CHAIN_H_
|
||||
#define CDM_OEC_DECRYPT_FALLBACK_CHAIN_H_
|
||||
|
||||
#include "OEMCryptoCAS.h"
|
||||
#include "disallow_copy_and_assign.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// This class groups static methods relating to providing proper fallback
|
||||
// behavior when calling DecryptCENC in OEMCrypto v16. Outside code can leverage
|
||||
// this behavior by passing the samples to be decrypted to Decrypt(), which will
|
||||
// set off the chain of fallback functions as needed.
|
||||
//
|
||||
// The behavior of this class is pathological. For each block of data, it will
|
||||
// greedily try every possible way of passing data to OEMCrypto until one works.
|
||||
// In the order tried, the ways to send data are:
|
||||
// 1) Multiple Samples at once
|
||||
// 2) Individual Samples one at a time
|
||||
// 3) Individual Subsamples one at a time
|
||||
// 4) Individual Half-Subsamples one at a time
|
||||
// On a device that only accepts half-subsamples, the way OEMCrypto v15 did,
|
||||
// this results in many needless roundtrips to OEMCrypto. This would be
|
||||
// inefficient behavior for a real CDM, but for the sake of testing, we want to
|
||||
// use the maximal way the OEMCrypto implementation will accept the data. And,
|
||||
// for implementations that do not accept multiple samples or subsamples per
|
||||
// call, we want to test that they correctly reject larger calls.
|
||||
class DecryptFallbackChain {
|
||||
public:
|
||||
static OEMCryptoResult Decrypt(
|
||||
OEMCrypto_SESSION session_id, const OEMCrypto_SampleDescription* samples,
|
||||
size_t samples_length, OEMCryptoCipherMode cipher_mode,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern);
|
||||
|
||||
private:
|
||||
static OEMCryptoResult DecryptSample(
|
||||
OEMCrypto_SESSION session_id, const OEMCrypto_SampleDescription& sample,
|
||||
OEMCryptoCipherMode cipher_mode,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern);
|
||||
|
||||
static OEMCryptoResult DecryptSubsample(
|
||||
OEMCrypto_SESSION session_id, const OEMCrypto_SampleDescription& sample,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern);
|
||||
|
||||
static OEMCryptoResult DecryptSubsampleHalf(
|
||||
OEMCrypto_SESSION session_id, const OEMCrypto_SampleDescription& sample,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern);
|
||||
|
||||
// There is no reason to have an instance of this class.
|
||||
DecryptFallbackChain() = delete;
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(DecryptFallbackChain);
|
||||
};
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_OEC_DECRYPT_FALLBACK_CHAIN_H_
|
||||
260
oemcrypto/test/oec_device_features.cpp
Normal file
260
oemcrypto/test/oec_device_features.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// OEMCrypto device features for unit tests
|
||||
//
|
||||
#include "oec_device_features.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "oec_test_data.h"
|
||||
#include "test_sleep.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
DeviceFeatures global_features;
|
||||
|
||||
void DeviceFeatures::Initialize() {
|
||||
if (initialized_) return;
|
||||
uses_keybox = false;
|
||||
loads_certificate = false;
|
||||
generic_crypto = false;
|
||||
usage_table = false;
|
||||
supports_rsa_3072 = false;
|
||||
api_version = 0;
|
||||
derive_key_method = NO_METHOD;
|
||||
OEMCrypto_SetSandbox(kTestSandbox, sizeof(kTestSandbox));
|
||||
if (OEMCrypto_SUCCESS != OEMCrypto_Initialize()) {
|
||||
printf("OEMCrypto_Initialize failed. All tests will fail.\n");
|
||||
return;
|
||||
}
|
||||
uint8_t buffer[1];
|
||||
uint8_t iv[16] = {};
|
||||
size_t size = 0;
|
||||
provisioning_method = OEMCrypto_GetProvisioningMethod();
|
||||
printf("provisioning_method = %s\n",
|
||||
ProvisioningMethodName(provisioning_method));
|
||||
uses_keybox =
|
||||
(OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_GetKeyData(buffer, &size));
|
||||
printf("uses_keybox = %s.\n", uses_keybox ? "true" : "false");
|
||||
OEMCrypto_SESSION session;
|
||||
OEMCryptoResult result = OEMCrypto_OpenSession(&session);
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
printf("--- ERROR: Could not open session: %d ----\n", result);
|
||||
}
|
||||
// If the device uses a keybox, check to see if loading a certificate is
|
||||
// installed.
|
||||
if (provisioning_method == OEMCrypto_Keybox ||
|
||||
provisioning_method == OEMCrypto_OEMCertificate) {
|
||||
// Devices with a keybox or OEM Certificate are required to support loading
|
||||
// a DRM certificate.
|
||||
loads_certificate = true;
|
||||
} else {
|
||||
// Other devices are either broken, or they have a baked in certificate.
|
||||
loads_certificate = false;
|
||||
}
|
||||
printf("loads_certificate = %s.\n", loads_certificate ? "true" : "false");
|
||||
generic_crypto =
|
||||
(OEMCrypto_ERROR_NOT_IMPLEMENTED !=
|
||||
OEMCrypto_Generic_Encrypt(session, buffer, 0, iv,
|
||||
OEMCrypto_AES_CBC_128_NO_PADDING, buffer));
|
||||
printf("generic_crypto = %s.\n", generic_crypto ? "true" : "false");
|
||||
OEMCrypto_CloseSession(session);
|
||||
api_version = OEMCrypto_APIVersion();
|
||||
printf("api_version = %d.\n", api_version);
|
||||
// These unit tests only work with new usage tables. We do not test v12
|
||||
// usage tables.
|
||||
if (api_version > 12) usage_table = OEMCrypto_SupportsUsageTable();
|
||||
printf("usage_table = %s.\n", usage_table ? "true" : "false");
|
||||
PickDerivedKey();
|
||||
if (api_version >= 13) {
|
||||
uint32_t supported_cert = OEMCrypto_SupportedCertificates();
|
||||
if (supported_cert & OEMCrypto_Supports_RSA_CAST) {
|
||||
cast_receiver = true;
|
||||
}
|
||||
if (supported_cert & OEMCrypto_Supports_RSA_3072bit) {
|
||||
supports_rsa_3072 = true;
|
||||
}
|
||||
}
|
||||
printf("cast_receiver = %s.\n", cast_receiver ? "true" : "false");
|
||||
resource_rating = OEMCrypto_ResourceRatingTier();
|
||||
printf("resource_rating = %d, security level %s.\n", resource_rating,
|
||||
OEMCrypto_SecurityLevel());
|
||||
uint32_t decrypt_hash_type = OEMCrypto_SupportsDecryptHash();
|
||||
supports_crc = (decrypt_hash_type == OEMCrypto_CRC_Clear_Buffer);
|
||||
if (supports_crc) {
|
||||
printf("Decrypt hashes will be tested.\n");
|
||||
} else {
|
||||
printf("Decrypt hashes will not be tested -- %s.\n",
|
||||
decrypt_hash_type == OEMCrypto_Hash_Not_Supported
|
||||
? "not supported"
|
||||
: "partner defined hash");
|
||||
}
|
||||
switch (derive_key_method) {
|
||||
case NO_METHOD:
|
||||
printf("NO_METHOD: Cannot derive known session keys.\n");
|
||||
// Note: cast_receiver left unchanged because set by user on command line.
|
||||
uses_keybox = false;
|
||||
loads_certificate = false;
|
||||
generic_crypto = false;
|
||||
usage_table = false;
|
||||
break;
|
||||
case LOAD_TEST_KEYBOX:
|
||||
printf("LOAD_TEST_KEYBOX: Call LoadTestKeybox before deriving keys.\n");
|
||||
break;
|
||||
case LOAD_TEST_RSA_KEY:
|
||||
printf("LOAD_TEST_RSA_KEY: Call LoadTestRSAKey before deriving keys.\n");
|
||||
break;
|
||||
case TEST_PROVISION_30:
|
||||
printf("TEST_PROVISION_30: Device provisioed with OEM Cert.\n");
|
||||
break;
|
||||
}
|
||||
std::string security_level = OEMCrypto_SecurityLevel();
|
||||
supports_level_1 = (security_level == "L1");
|
||||
printf("SecurityLevel is %s (%s)\n",
|
||||
supports_level_1 ? "Level 1" : "Not Level 1",
|
||||
security_level.c_str());
|
||||
CheckSecureBuffers();
|
||||
OEMCrypto_Terminate();
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
|
||||
std::string filter = initial_filter;
|
||||
// clang-format off
|
||||
if (!uses_keybox) FilterOut(&filter, "*KeyboxTest*");
|
||||
if (!loads_certificate) FilterOut(&filter, "OEMCryptoLoadsCert*");
|
||||
if (!generic_crypto) FilterOut(&filter, "*GenericCrypto*");
|
||||
if (!cast_receiver) FilterOut(&filter, "*CastReceiver*");
|
||||
if (!usage_table) FilterOut(&filter, "*UsageTable*");
|
||||
if (derive_key_method == NO_METHOD) FilterOut(&filter, "*SessionTest*");
|
||||
if (provisioning_method
|
||||
!= OEMCrypto_OEMCertificate) FilterOut(&filter, "*Prov30*");
|
||||
if (!supports_rsa_3072) FilterOut(&filter, "*RSAKey3072*");
|
||||
if (api_version < 9) FilterOut(&filter, "*API09*");
|
||||
if (api_version < 10) FilterOut(&filter, "*API10*");
|
||||
if (api_version < 11) FilterOut(&filter, "*API11*");
|
||||
if (api_version < 12) FilterOut(&filter, "*API12*");
|
||||
if (api_version < 13) FilterOut(&filter, "*API13*");
|
||||
if (api_version < 14) FilterOut(&filter, "*API14*");
|
||||
if (api_version < 15) FilterOut(&filter, "*API15*");
|
||||
if (api_version < 16) FilterOut(&filter, "*API16*");
|
||||
// clang-format on
|
||||
// Some tests may require root access. If user is not root, filter these tests
|
||||
// out.
|
||||
if (!wvutil::TestSleep::CanChangeSystemTime()) {
|
||||
printf("Filtering out TimeRollbackPrevention.\n");
|
||||
FilterOut(&filter, "*TimeRollbackPrevention*");
|
||||
} else {
|
||||
printf("Can change time. I will run TimeRollbackPrevention.\n");
|
||||
}
|
||||
// Performance tests take a long time. Filter them out if they are not
|
||||
// specifically requested.
|
||||
if (filter.find("Performance") == std::string::npos) {
|
||||
FilterOut(&filter, "*Performance*");
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
void DeviceFeatures::PickDerivedKey() {
|
||||
if (api_version >= 12) {
|
||||
switch (provisioning_method) {
|
||||
case OEMCrypto_OEMCertificate:
|
||||
derive_key_method = TEST_PROVISION_30;
|
||||
return;
|
||||
case OEMCrypto_DrmCertificate:
|
||||
if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestRSAKey()) {
|
||||
derive_key_method = LOAD_TEST_RSA_KEY;
|
||||
}
|
||||
return;
|
||||
case OEMCrypto_Keybox:
|
||||
// Fall through to api_version < 12 case.
|
||||
break;
|
||||
case OEMCrypto_ProvisioningError:
|
||||
printf(
|
||||
"ERROR: OEMCrypto_GetProvisioningMethod() returns "
|
||||
"OEMCrypto_ProvisioningError\n");
|
||||
// Then fall through to api_version < 12 case.
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (uses_keybox) {
|
||||
// If device uses a keybox, try to load the test keybox.
|
||||
if (OEMCrypto_ERROR_NOT_IMPLEMENTED !=
|
||||
OEMCrypto_LoadTestKeybox(nullptr, 0)) {
|
||||
derive_key_method = LOAD_TEST_KEYBOX;
|
||||
}
|
||||
} else if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestRSAKey()) {
|
||||
derive_key_method = LOAD_TEST_RSA_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceFeatures::CheckSecureBuffers() {
|
||||
output_types_.push_back({false, OEMCrypto_BufferType_Clear});
|
||||
output_types_.push_back({true, OEMCrypto_BufferType_Clear});
|
||||
test_secure_buffers = false;
|
||||
OEMCrypto_SESSION session;
|
||||
OEMCryptoResult result = OEMCrypto_OpenSession(&session);
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
printf("--- ERROR: Could not open session: %d ----\n", result);
|
||||
return;
|
||||
}
|
||||
OEMCrypto_DestBufferDesc output_descriptor;
|
||||
output_descriptor.type = OEMCrypto_BufferType_Secure;
|
||||
int secure_fd;
|
||||
result = OEMCrypto_AllocateSecureBuffer(session, 42, &output_descriptor,
|
||||
&secure_fd);
|
||||
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
||||
printf("Secure buffers will not be tested\n");
|
||||
return;
|
||||
}
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
printf("--- ERROR: Could not create secure buffer: %d ----\n", result);
|
||||
return;
|
||||
}
|
||||
result = OEMCrypto_FreeSecureBuffer(session, &output_descriptor, secure_fd);
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
printf("--- ERROR: Could not free secure buffer: %d ----\n", result);
|
||||
return;
|
||||
}
|
||||
printf("Secure buffers will be tested\n");
|
||||
output_types_.push_back({false, OEMCrypto_BufferType_Secure});
|
||||
test_secure_buffers = true;
|
||||
}
|
||||
|
||||
void DeviceFeatures::FilterOut(std::string* current_filter,
|
||||
const std::string& new_filter) {
|
||||
if (current_filter->find('-') == std::string::npos) {
|
||||
*current_filter += "-" + new_filter;
|
||||
} else {
|
||||
*current_filter += ":" + new_filter;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the list of output types for the decrypt tests.
|
||||
const std::vector<OutputType>& DeviceFeatures::GetOutputTypes() {
|
||||
if (!initialized_) {
|
||||
Initialize();
|
||||
}
|
||||
return output_types_;
|
||||
}
|
||||
|
||||
const char* ProvisioningMethodName(OEMCrypto_ProvisioningMethod method) {
|
||||
switch (method) {
|
||||
case OEMCrypto_ProvisioningError:
|
||||
return "OEMCrypto_ProvisioningError";
|
||||
case OEMCrypto_DrmCertificate:
|
||||
return "OEMCrypto_DrmCertificate";
|
||||
case OEMCrypto_Keybox:
|
||||
return "OEMCrypto_Keybox";
|
||||
case OEMCrypto_OEMCertificate:
|
||||
return "OEMCrypto_OEMCertificate";
|
||||
}
|
||||
// Not reachable
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
88
oemcrypto/test/oec_device_features.h
Normal file
88
oemcrypto/test/oec_device_features.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef CDM_OEC_DEVICE_FEATURES_H_
|
||||
#define CDM_OEC_DEVICE_FEATURES_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "OEMCryptoCAS.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// These tests are designed to work for this version:
|
||||
constexpr unsigned int kCurrentAPI = 16;
|
||||
// The API version when Core Messages were introduced.
|
||||
constexpr unsigned int kCoreMessagesAPI = 16;
|
||||
|
||||
// An output type for testing. The type field is secure, clear, or direct. If
|
||||
// the type is clear, then decrypt_inplace could be true. Otherwise,
|
||||
// decrypt_inplace is false.
|
||||
struct OutputType {
|
||||
bool decrypt_inplace;
|
||||
OEMCryptoBufferType type;
|
||||
};
|
||||
|
||||
// Keeps track of which features are supported by the version of OEMCrypto being
|
||||
// tested. See the integration guide for a list of optional features.
|
||||
class DeviceFeatures {
|
||||
public:
|
||||
// There are several possible methods used to derive a set of known session
|
||||
// keys. For example, the test can install a known test keybox, or it can
|
||||
// parse the OEM certificate.
|
||||
enum DeriveMethod { // Method to use derive session keys.
|
||||
NO_METHOD, // Cannot derive known session keys.
|
||||
LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys.
|
||||
LOAD_TEST_RSA_KEY, // Call LoadTestRSAKey before deriving keys.
|
||||
TEST_PROVISION_30, // Device has OEM Certificate installed.
|
||||
};
|
||||
|
||||
enum DeriveMethod derive_key_method;
|
||||
bool uses_keybox; // Device uses a keybox to derive session keys.
|
||||
bool loads_certificate; // Device can load a certificate from the server.
|
||||
bool generic_crypto; // Device supports generic crypto.
|
||||
bool cast_receiver; // Device supports alternate rsa signature padding.
|
||||
bool usage_table; // Device saves usage information.
|
||||
bool supports_rsa_3072; // Device supports 3072 bit RSA keys.
|
||||
bool supports_level_1; // Device supports Level 1 security.
|
||||
uint32_t resource_rating; // Device's resource rating tier.
|
||||
bool supports_crc; // Supported decrypt hash type CRC.
|
||||
bool test_secure_buffers; // If we can create a secure buffer for testing.
|
||||
uint32_t api_version;
|
||||
OEMCrypto_ProvisioningMethod provisioning_method;
|
||||
|
||||
// This should be called from the test program's main procedure.
|
||||
void Initialize();
|
||||
void set_cast_receiver(bool is_cast_receiver) {
|
||||
cast_receiver = is_cast_receiver;
|
||||
}
|
||||
// Generate a GTest filter of tests that should not be run. This should be
|
||||
// called after Initialize. Tests are filtered out based on which features
|
||||
// are not supported. For example, a device that uses Provisioning 3.0 will
|
||||
// have all keybox tests filtered out.
|
||||
std::string RestrictFilter(const std::string& initial_filter);
|
||||
|
||||
// Get a list of output types that should be tested.
|
||||
const std::vector<OutputType>& GetOutputTypes();
|
||||
|
||||
private:
|
||||
// Decide which method should be used to derive session keys, based on
|
||||
// supported featuers.
|
||||
void PickDerivedKey();
|
||||
// Decide if secure buffers can be created, and initialize output_types_.
|
||||
void CheckSecureBuffers();
|
||||
// Add a GTest filter restriction to the current filter.
|
||||
void FilterOut(std::string* current_filter, const std::string& new_filter);
|
||||
|
||||
// A list of possible output types.
|
||||
std::vector<OutputType> output_types_;
|
||||
bool initialized_ = false;
|
||||
};
|
||||
|
||||
// There is one global set of features for the version of OEMCrypto being
|
||||
// tested. This should be initialized in the test program's main procedure.
|
||||
extern DeviceFeatures global_features;
|
||||
const char* ProvisioningMethodName(OEMCrypto_ProvisioningMethod method);
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_OEC_DEVICE_FEATURES_H_
|
||||
168
oemcrypto/test/oec_key_deriver.cpp
Normal file
168
oemcrypto/test/oec_key_deriver.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// OEMCrypto unit tests
|
||||
//
|
||||
|
||||
#include "oec_session_util.h"
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/cmac.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509_vfy.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "OEMCryptoCAS.h"
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "log.h"
|
||||
#include "oec_device_features.h"
|
||||
#include "oec_test_data.h"
|
||||
#include "oemcrypto_types.h"
|
||||
#include "platform.h"
|
||||
#include "string_conversions.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
void Encryptor::set_enc_key(const std::vector<uint8_t>& enc_key) {
|
||||
enc_key_ = enc_key;
|
||||
}
|
||||
|
||||
void Encryptor::CBCEncrypt(const uint8_t* data, uint8_t* encrypted_data,
|
||||
size_t data_length,
|
||||
const uint8_t (&iv)[KEY_IV_SIZE]) const {
|
||||
ASSERT_EQ(enc_key_.size(), KEY_SIZE);
|
||||
ASSERT_NE(data, nullptr);
|
||||
ASSERT_NE(encrypted_data, nullptr);
|
||||
AES_KEY aes_key;
|
||||
static const int key_size = KEY_SIZE * 8; // in bits.
|
||||
AES_set_encrypt_key(enc_key_.data(), key_size, &aes_key);
|
||||
uint8_t iv_buffer[KEY_IV_SIZE];
|
||||
memcpy(iv_buffer, iv, KEY_IV_SIZE);
|
||||
AES_cbc_encrypt(data, encrypted_data, data_length, &aes_key, iv_buffer,
|
||||
AES_ENCRYPT);
|
||||
}
|
||||
|
||||
void Encryptor::PadAndEncryptProvisioningMessage(
|
||||
RSAPrivateKeyMessage* data, RSAPrivateKeyMessage* encrypted) const {
|
||||
EXPECT_EQ(1, GetRandBytes(data->rsa_key_iv, KEY_IV_SIZE));
|
||||
ASSERT_EQ(enc_key_.size(), KEY_SIZE);
|
||||
*encrypted = *data;
|
||||
size_t padding = AES_BLOCK_SIZE - (data->rsa_key_length % AES_BLOCK_SIZE);
|
||||
memset(data->rsa_key + data->rsa_key_length, static_cast<uint8_t>(padding),
|
||||
padding);
|
||||
encrypted->rsa_key_length = data->rsa_key_length + padding;
|
||||
AES_KEY aes_key;
|
||||
static const int key_size = KEY_SIZE * 8; // in bits.
|
||||
AES_set_encrypt_key(enc_key_.data(), key_size, &aes_key);
|
||||
uint8_t iv_buffer[KEY_IV_SIZE];
|
||||
memcpy(iv_buffer, &data->rsa_key_iv[0], KEY_IV_SIZE);
|
||||
AES_cbc_encrypt(&data->rsa_key[0], &encrypted->rsa_key[0],
|
||||
encrypted->rsa_key_length, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||
}
|
||||
|
||||
// This generates the data for deriving one key. If there are failures in
|
||||
// this function, then there is something wrong with the test program and its
|
||||
// dependency on BoringSSL.
|
||||
void KeyDeriver::DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
|
||||
int counter, vector<uint8_t>* out) {
|
||||
ASSERT_NE(key, nullptr);
|
||||
ASSERT_FALSE(context.empty());
|
||||
ASSERT_GE(4, counter);
|
||||
ASSERT_LE(1, counter);
|
||||
ASSERT_NE(out, nullptr);
|
||||
|
||||
const EVP_CIPHER* cipher = EVP_aes_128_cbc();
|
||||
CMAC_CTX* cmac_ctx = CMAC_CTX_new();
|
||||
ASSERT_NE(nullptr, cmac_ctx);
|
||||
|
||||
ASSERT_TRUE(CMAC_Init(cmac_ctx, key, KEY_SIZE, cipher, 0));
|
||||
|
||||
std::vector<uint8_t> message;
|
||||
message.push_back(static_cast<uint8_t>(counter));
|
||||
message.insert(message.end(), context.begin(), context.end());
|
||||
|
||||
ASSERT_TRUE(CMAC_Update(cmac_ctx, message.data(), message.size()));
|
||||
|
||||
size_t reslen;
|
||||
uint8_t res[128];
|
||||
ASSERT_TRUE(CMAC_Final(cmac_ctx, res, &reslen));
|
||||
|
||||
out->assign(res, res + reslen);
|
||||
CMAC_CTX_free(cmac_ctx);
|
||||
}
|
||||
|
||||
// This generates the data for deriving a set of keys. If there are failures in
|
||||
// this function, then there is something wrong with the test program and its
|
||||
// dependency on BoringSSL.
|
||||
void KeyDeriver::DeriveKeys(const uint8_t* master_key,
|
||||
const vector<uint8_t>& mac_key_context,
|
||||
const vector<uint8_t>& enc_key_context) {
|
||||
// Generate derived key for mac key
|
||||
std::vector<uint8_t> mac_key_part2;
|
||||
DeriveKey(master_key, mac_key_context, 1, &mac_key_server_);
|
||||
DeriveKey(master_key, mac_key_context, 2, &mac_key_part2);
|
||||
mac_key_server_.insert(mac_key_server_.end(), mac_key_part2.begin(),
|
||||
mac_key_part2.end());
|
||||
|
||||
DeriveKey(master_key, mac_key_context, 3, &mac_key_client_);
|
||||
DeriveKey(master_key, mac_key_context, 4, &mac_key_part2);
|
||||
mac_key_client_.insert(mac_key_client_.end(), mac_key_part2.begin(),
|
||||
mac_key_part2.end());
|
||||
|
||||
// Generate derived key for encryption key
|
||||
std::vector<uint8_t> enc_key;
|
||||
DeriveKey(master_key, enc_key_context, 1, &enc_key);
|
||||
set_enc_key(enc_key);
|
||||
}
|
||||
|
||||
void KeyDeriver::set_mac_keys(const uint8_t* mac_keys) {
|
||||
ASSERT_EQ(mac_key_server_.size(), MAC_KEY_SIZE);
|
||||
ASSERT_EQ(mac_key_client_.size(), MAC_KEY_SIZE);
|
||||
memcpy(mac_key_server_.data(), mac_keys, MAC_KEY_SIZE);
|
||||
memcpy(mac_key_client_.data(), mac_keys + MAC_KEY_SIZE, MAC_KEY_SIZE);
|
||||
}
|
||||
|
||||
void KeyDeriver::ServerSignBuffer(const uint8_t* data, size_t data_length,
|
||||
std::vector<uint8_t>* signature) const {
|
||||
ASSERT_EQ(mac_key_server_.size(), MAC_KEY_SIZE);
|
||||
signature->assign(SHA256_DIGEST_LENGTH, 0);
|
||||
unsigned int sig_len = SHA256_DIGEST_LENGTH;
|
||||
ASSERT_TRUE(HMAC(EVP_sha256(), mac_key_server_.data(), mac_key_server_.size(),
|
||||
data, data_length, signature->data(), &sig_len));
|
||||
}
|
||||
|
||||
void KeyDeriver::ClientSignBuffer(const vector<uint8_t>& buffer,
|
||||
std::vector<uint8_t>* signature) const {
|
||||
ASSERT_EQ(mac_key_client_.size(), MAC_KEY_SIZE);
|
||||
signature->assign(SHA256_DIGEST_LENGTH, 0);
|
||||
unsigned int sig_len = SHA256_DIGEST_LENGTH;
|
||||
ASSERT_TRUE(HMAC(EVP_sha256(), mac_key_client_.data(), mac_key_client_.size(),
|
||||
buffer.data(), buffer.size(), signature->data(), &sig_len));
|
||||
}
|
||||
|
||||
void KeyDeriver::ClientSignPstReport(const vector<uint8_t>& pst_report_buffer,
|
||||
std::vector<uint8_t>* signature) const {
|
||||
ASSERT_EQ(mac_key_client_.size(), MAC_KEY_SIZE);
|
||||
signature->assign(SHA_DIGEST_LENGTH, 0);
|
||||
unsigned int sig_len = SHA_DIGEST_LENGTH;
|
||||
ASSERT_TRUE(HMAC(EVP_sha1(), mac_key_client_.data(), mac_key_client_.size(),
|
||||
&pst_report_buffer[SHA_DIGEST_LENGTH],
|
||||
pst_report_buffer.size() - SHA_DIGEST_LENGTH,
|
||||
signature->data(), &sig_len));
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
93
oemcrypto/test/oec_key_deriver.h
Normal file
93
oemcrypto/test/oec_key_deriver.h
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
#ifndef CDM_OEC_KEY_DERIVER_H_
|
||||
#define CDM_OEC_KEY_DERIVER_H_
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "oec_device_features.h"
|
||||
#include "oemcrypto_types.h"
|
||||
#include "pst_report.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
constexpr size_t kMaxTestRSAKeyLength = 2000; // Rough estimate.
|
||||
constexpr size_t kMaxCoreProvRequest = 150; // Rough estimate.
|
||||
|
||||
// This structure will be signed to simulate a provisioning response from the
|
||||
// server.
|
||||
struct RSAPrivateKeyMessage {
|
||||
uint8_t rsa_key[kMaxTestRSAKeyLength];
|
||||
uint8_t rsa_key_iv[KEY_IV_SIZE];
|
||||
size_t rsa_key_length;
|
||||
uint8_t enc_message_key[kMaxTestRSAKeyLength];
|
||||
size_t enc_message_key_length;
|
||||
uint32_t nonce;
|
||||
};
|
||||
|
||||
// Holds an encryption key and can encrypt a provisioning message. It also can
|
||||
// encrypt short buffers using CBC, such as content keys in a license.
|
||||
class Encryptor {
|
||||
public:
|
||||
Encryptor() : enc_key_(KEY_SIZE, 0) {}
|
||||
Encryptor(const std::vector<uint8_t>& enc_key) { set_enc_key(enc_key); };
|
||||
Encryptor& operator=(const Encryptor&) = default;
|
||||
void set_enc_key(const std::vector<uint8_t>& enc_key);
|
||||
|
||||
// This encrypts an RSAPrivateKeyMessage with encryption_key so that it may be
|
||||
// loaded with OEMCrypto_LoadProvisioningResponse.
|
||||
// This modifies the clear data: it adds padding and generates a random iv.
|
||||
void PadAndEncryptProvisioningMessage(RSAPrivateKeyMessage* data,
|
||||
RSAPrivateKeyMessage* encrypted) const;
|
||||
|
||||
void CBCEncrypt(const uint8_t* data, uint8_t* encrypted_data,
|
||||
size_t data_length, const uint8_t (&iv)[KEY_IV_SIZE]) const;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> enc_key_;
|
||||
};
|
||||
|
||||
// Holds encryption and mac keys derived from a master key.
|
||||
// Can be used to sign a buffer as either a server or client.
|
||||
class KeyDeriver : public Encryptor {
|
||||
public:
|
||||
KeyDeriver()
|
||||
: mac_key_server_(MAC_KEY_SIZE, 0), mac_key_client_(MAC_KEY_SIZE, 0) {}
|
||||
KeyDeriver& operator=(const KeyDeriver&) = default;
|
||||
|
||||
// Generate mac and enc keys give the master key.
|
||||
void DeriveKeys(const uint8_t* master_key,
|
||||
const std::vector<uint8_t>& mac_key_context,
|
||||
const std::vector<uint8_t>& enc_key_context);
|
||||
// Sign the buffer with server's mac key.
|
||||
void ServerSignBuffer(const uint8_t* data, size_t data_length,
|
||||
std::vector<uint8_t>* signature) const;
|
||||
// Sign the buffer with client's known mac key. Known test keys must be
|
||||
// installed first. This uses HMAC with SHA256, so is suitable for a message.
|
||||
void ClientSignBuffer(const std::vector<uint8_t>& buffer,
|
||||
std::vector<uint8_t>* signature) const;
|
||||
// Sign the pst buffer with client's known mac key. Known test keys must be
|
||||
// installed first. This uses HMAC with SHA128, and skips the beginning of the
|
||||
// buffer, so is only suitable for a pst report.
|
||||
void ClientSignPstReport(const std::vector<uint8_t>& pst_report_buffer,
|
||||
std::vector<uint8_t>* signature) const;
|
||||
void set_mac_keys(const uint8_t* mac_keys);
|
||||
|
||||
private:
|
||||
// Internal utility function to derive key using CMAC-128
|
||||
void DeriveKey(const uint8_t* key, const std::vector<uint8_t>& context,
|
||||
int counter, std::vector<uint8_t>* out);
|
||||
|
||||
std::vector<uint8_t> mac_key_server_;
|
||||
std::vector<uint8_t> mac_key_client_;
|
||||
};
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_OEC_KEY_DERIVER_H_
|
||||
1512
oemcrypto/test/oec_session_util.cpp
Normal file
1512
oemcrypto/test/oec_session_util.cpp
Normal file
File diff suppressed because it is too large
Load Diff
608
oemcrypto/test/oec_session_util.h
Normal file
608
oemcrypto/test/oec_session_util.h
Normal file
@@ -0,0 +1,608 @@
|
||||
#ifndef CDM_OEC_SESSION_UTIL_H_
|
||||
#define CDM_OEC_SESSION_UTIL_H_
|
||||
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// OEMCrypto unit tests
|
||||
//
|
||||
#include <gtest/gtest.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core_message_deserialize.h"
|
||||
#include "core_message_serialize.h"
|
||||
#include "odk.h"
|
||||
#include "oec_device_features.h"
|
||||
#include "oec_key_deriver.h"
|
||||
#include "oemcrypto_types.h"
|
||||
#include "pst_report.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// GTest requires PrintTo to be in the same namespace as the thing it prints,
|
||||
// which is std::vector in this case.
|
||||
namespace std {
|
||||
|
||||
void PrintTo(const vector<uint8_t>& value, ostream* os);
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// Make sure this is larger than kMaxKeysPerSession, in oemcrypto_test.cpp
|
||||
constexpr size_t kMaxNumKeys = 30;
|
||||
|
||||
namespace {
|
||||
#if defined(TEST_SPEED_MULTIPLIER) // Can slow test time limits when
|
||||
// debugging is slowing everything.
|
||||
constexpr int kSpeedMultiplier = TEST_SPEED_MULTIPLIER;
|
||||
#else
|
||||
constexpr int kSpeedMultiplier = 1;
|
||||
#endif
|
||||
constexpr int kShortSleep = 1 * kSpeedMultiplier;
|
||||
constexpr int kLongSleep = 2 * kSpeedMultiplier;
|
||||
constexpr uint32_t kDuration = 2 * kSpeedMultiplier;
|
||||
constexpr uint32_t kLongDuration = 5 * kSpeedMultiplier;
|
||||
constexpr int32_t kTimeTolerance = 3 * kSpeedMultiplier;
|
||||
constexpr int64_t kUsageTableTimeTolerance = 10 * kSpeedMultiplier;
|
||||
} // namespace
|
||||
|
||||
typedef struct {
|
||||
uint8_t verification[4];
|
||||
uint32_t duration;
|
||||
uint32_t nonce;
|
||||
uint32_t control_bits;
|
||||
} KeyControlBlock;
|
||||
|
||||
// Note: The API does not specify a maximum key id length. We specify a
|
||||
// maximum just for these tests, so that we have a fixed message size.
|
||||
constexpr size_t kTestKeyIdMaxLength = 16;
|
||||
|
||||
// Most content will use a key id that is 16 bytes long.
|
||||
constexpr int kDefaultKeyIdLength = 16;
|
||||
constexpr size_t kMaxPSTLength = 255; // In specification.
|
||||
constexpr size_t kMaxCoreMessage = 200 * kMaxNumKeys + 200; // Rough estimate.
|
||||
|
||||
typedef struct {
|
||||
uint8_t key_id[kTestKeyIdMaxLength];
|
||||
size_t key_id_length;
|
||||
uint8_t key_data[MAC_KEY_SIZE];
|
||||
size_t key_data_length;
|
||||
uint8_t key_iv[KEY_IV_SIZE];
|
||||
uint8_t control_iv[KEY_IV_SIZE];
|
||||
KeyControlBlock control;
|
||||
// Note: cipher_mode may not be part of a real signed message. For these
|
||||
// tests, it is convenient to keep it in this structure anyway.
|
||||
OEMCryptoCipherMode cipher_mode;
|
||||
} MessageKeyData;
|
||||
|
||||
// This structure will be signed to simulate a message from the server.
|
||||
struct MessageData {
|
||||
MessageKeyData keys[kMaxNumKeys];
|
||||
uint8_t mac_key_iv[KEY_IV_SIZE];
|
||||
uint8_t padding[KEY_IV_SIZE];
|
||||
uint8_t mac_keys[2 * MAC_KEY_SIZE];
|
||||
uint8_t pst[kMaxPSTLength];
|
||||
SRM_Restriction_Data srm_restriction_data;
|
||||
};
|
||||
|
||||
struct Test_PST_Report {
|
||||
Test_PST_Report(const std::string& pst_in,
|
||||
OEMCrypto_Usage_Entry_Status status_in);
|
||||
|
||||
OEMCrypto_Usage_Entry_Status status;
|
||||
int64_t seconds_since_license_received;
|
||||
int64_t seconds_since_first_decrypt;
|
||||
int64_t seconds_since_last_decrypt;
|
||||
std::string pst;
|
||||
int64_t time_created;
|
||||
};
|
||||
|
||||
struct EntitledContentKeyData {
|
||||
uint8_t entitlement_key_id[kTestKeyIdMaxLength];
|
||||
size_t entitlement_key_id_length;
|
||||
uint8_t content_key_id[kTestKeyIdMaxLength];
|
||||
size_t content_key_id_length;
|
||||
uint8_t content_key_data_iv[KEY_IV_SIZE];
|
||||
uint8_t content_key_data[KEY_SIZE];
|
||||
uint8_t encrypted_content_key_data[KEY_SIZE];
|
||||
size_t key_index; // Index into the license's key array. Only for testing.
|
||||
};
|
||||
|
||||
// returns 1 on success, -1 if not supported, or 0 if other failure.
|
||||
int GetRandBytes(unsigned char* buf, int num);
|
||||
|
||||
void GenerateSimpleSampleDescription(const std::vector<uint8_t>& in,
|
||||
std::vector<uint8_t>& out,
|
||||
OEMCrypto_SampleDescription* sample,
|
||||
OEMCrypto_SubSampleDescription* subsample);
|
||||
|
||||
// Increment counter for AES-CTR. The CENC spec specifies we increment only
|
||||
// the low 64 bits of the IV counter, and leave the high 64 bits alone. This
|
||||
// is different from the OpenSSL implementation, so we implement the CTR loop
|
||||
// ourselves.
|
||||
void ctr128_inc64(int64_t increaseBy, uint8_t* iv);
|
||||
|
||||
// Some compilers don't like the macro htonl within an ASSERT_EQ.
|
||||
uint32_t htonl_fnc(uint32_t x);
|
||||
|
||||
// Prints error string from BoringSSL
|
||||
void dump_boringssl_error();
|
||||
|
||||
class Session;
|
||||
// The prototype of the OEMCrypto function to prepare and sign a request.
|
||||
typedef OEMCryptoResult (*PrepAndSignRequest_t)(
|
||||
OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
|
||||
size_t* core_message_length, uint8_t* signature, size_t* signature_length);
|
||||
|
||||
// A RoundTrip helps generate and verify a request message, helps generate the
|
||||
// corresponding response, and then helps verify loading the response.
|
||||
template <class CoreRequest, PrepAndSignRequest_t PrepAndSignRequest,
|
||||
class CoreResponse, class ResponseData>
|
||||
class RoundTrip {
|
||||
public:
|
||||
RoundTrip() = delete;
|
||||
RoundTrip(Session* session)
|
||||
: session_(session),
|
||||
core_request_(),
|
||||
core_response_(),
|
||||
response_data_(),
|
||||
encrypted_response_data_(),
|
||||
required_message_size_(0) {}
|
||||
virtual ~RoundTrip() {}
|
||||
|
||||
// Have OEMCrypto sign a request message and then verify the signature and the
|
||||
// core message.
|
||||
virtual void SignAndVerifyRequest();
|
||||
// Create a default |response_data| and |core_response|.
|
||||
virtual void CreateDefaultResponse() = 0;
|
||||
// Copy fields from |response_data| to |padded_response_data|, encrypting
|
||||
// those that should be encrypted. Serialize the core message. Then sign the
|
||||
// response.
|
||||
virtual void EncryptAndSignResponse() = 0;
|
||||
// Attempt to load the response and return the error. Short buffer errors are
|
||||
// handled by LoadResponse, not the caller. All other errors should be
|
||||
// handled by the caller.
|
||||
virtual OEMCryptoResult LoadResponse() { return LoadResponse(session_); }
|
||||
// As with LoadResponse, but load into a different session.
|
||||
virtual OEMCryptoResult LoadResponse(Session* session) = 0;
|
||||
|
||||
// Accessors are all read/write because tests modify default values.
|
||||
Session* session() { return session_; }
|
||||
void set_session(Session* session) { session_ = session; }
|
||||
CoreRequest& core_request() { return core_request_; }
|
||||
CoreResponse& core_response() { return core_response_; }
|
||||
ResponseData& response_data() { return response_data_; }
|
||||
std::vector<uint8_t>& encrypted_response_buffer() {
|
||||
return encrypted_response_;
|
||||
}
|
||||
|
||||
// Set the size of the buffer used the encrypted license.
|
||||
void set_message_size(size_t size) { required_message_size_ = size; }
|
||||
std::vector<uint8_t>& response_signature() { return response_signature_; }
|
||||
const std::string& serialized_core_message() const {
|
||||
return serialized_core_message_;
|
||||
}
|
||||
|
||||
protected:
|
||||
// ----------------------------------------------------------------------
|
||||
// Specialized functionality for each message type.
|
||||
|
||||
// Verify the signature of the request.
|
||||
virtual void VerifyRequestSignature(
|
||||
const vector<uint8_t>& data, const vector<uint8_t>& generated_signature,
|
||||
size_t core_message_length) = 0;
|
||||
// Verify the values of the core response.
|
||||
virtual void FillAndVerifyCoreRequest(
|
||||
const std::string& core_message_string) = 0;
|
||||
// Find the given pointer in the response_data_.
|
||||
virtual OEMCrypto_Substring FindSubstring(const void* pointer, size_t length);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Member variables.
|
||||
Session* session_;
|
||||
CoreRequest core_request_;
|
||||
CoreResponse core_response_;
|
||||
ResponseData response_data_, encrypted_response_data_;
|
||||
// Message buffers will be at least this big. Tests for loading and signing
|
||||
// messages will increase all buffers to this size.
|
||||
size_t required_message_size_;
|
||||
std::vector<uint8_t> response_signature_;
|
||||
std::string serialized_core_message_;
|
||||
std::vector<uint8_t> encrypted_response_;
|
||||
};
|
||||
|
||||
class ProvisioningRoundTrip
|
||||
: public RoundTrip<
|
||||
/* CoreRequest */ oemcrypto_core_message::ODK_ProvisioningRequest,
|
||||
OEMCrypto_PrepAndSignProvisioningRequest,
|
||||
/* CoreResponse */ ODK_ParsedProvisioning,
|
||||
/* ResponseData */ RSAPrivateKeyMessage> {
|
||||
public:
|
||||
ProvisioningRoundTrip(Session* session,
|
||||
const std::vector<uint8_t>& encoded_rsa_key)
|
||||
: RoundTrip(session),
|
||||
allowed_schemes_(kSign_RSASSA_PSS),
|
||||
encryptor_(),
|
||||
encoded_rsa_key_(encoded_rsa_key) {}
|
||||
// Prepare the session for signing the request.
|
||||
virtual void PrepareSession(const wvoec::WidevineKeybox& keybox);
|
||||
void CreateDefaultResponse() override;
|
||||
void EncryptAndSignResponse() override;
|
||||
OEMCryptoResult LoadResponse() override { return LoadResponse(session_); }
|
||||
OEMCryptoResult LoadResponse(Session* session) override;
|
||||
void VerifyLoadFailed();
|
||||
const std::vector<uint8_t>& encoded_rsa_key() { return encoded_rsa_key_; }
|
||||
const std::vector<uint8_t>& wrapped_rsa_key() { return wrapped_rsa_key_; }
|
||||
void set_allowed_schemes(uint32_t allowed_schemes) {
|
||||
allowed_schemes_ = allowed_schemes;
|
||||
}
|
||||
|
||||
protected:
|
||||
void VerifyRequestSignature(const vector<uint8_t>& data,
|
||||
const vector<uint8_t>& generated_signature,
|
||||
size_t core_message_length) override;
|
||||
// Verify the values of the core response.
|
||||
virtual void FillAndVerifyCoreRequest(
|
||||
const std::string& core_message_string) override;
|
||||
// Load the response, without the retry. Called by LoadResponse.
|
||||
OEMCryptoResult LoadResponseNoRetry(Session* session,
|
||||
size_t* wrapped_key_length);
|
||||
// This takes a pointer in the response_data_ and remaps it to the same
|
||||
// pointer within the encrypted message. This is used for backwards
|
||||
// compatibliity testing, so that a v15 oemcrypto will accept range checks.
|
||||
template <typename T>
|
||||
const T* RemapPointer(const T* response_pointer) const;
|
||||
|
||||
uint32_t allowed_schemes_;
|
||||
Encryptor encryptor_;
|
||||
// The message key used for Prov 3.0.
|
||||
std::vector<uint8_t> message_key_;
|
||||
std::vector<uint8_t> encrypted_message_key_;
|
||||
std::vector<uint8_t> encoded_rsa_key_;
|
||||
std::vector<uint8_t> wrapped_rsa_key_;
|
||||
};
|
||||
|
||||
class LicenseRoundTrip
|
||||
: public RoundTrip<
|
||||
/* CoreRequest */ oemcrypto_core_message::ODK_LicenseRequest,
|
||||
OEMCrypto_PrepAndSignLicenseRequest,
|
||||
/* CoreResponse */ ODK_ParsedLicense,
|
||||
/* ResponseData */ MessageData> {
|
||||
public:
|
||||
LicenseRoundTrip(Session* session)
|
||||
: RoundTrip(session),
|
||||
control_(wvoec::kControlNonceEnabled),
|
||||
num_keys_(4),
|
||||
pst_(""),
|
||||
minimum_srm_version_(0),
|
||||
update_mac_keys_(true),
|
||||
api_version_(kCurrentAPI),
|
||||
expect_request_has_correct_nonce_(true),
|
||||
license_type_(OEMCrypto_ContentLicense),
|
||||
request_hash_() {}
|
||||
void CreateDefaultResponse() override;
|
||||
// Create a license with four keys. Each key is responsible for one of generic
|
||||
// encrypt (key 0), decrypt (key 1), sign (key 2) and verify (key 3). Each key
|
||||
// is allowed only one type of operation.
|
||||
void CreateResponseWithGenericCryptoKeys();
|
||||
// Fill the |core_response| substrings.
|
||||
virtual void FillCoreResponseSubstrings();
|
||||
void EncryptAndSignResponse() override;
|
||||
OEMCryptoResult LoadResponse() override { return LoadResponse(session_); }
|
||||
OEMCryptoResult LoadResponse(Session* session) override;
|
||||
// Reload an offline license into a different session. This derives new mac
|
||||
// keys and then calls LoadResponse.
|
||||
OEMCryptoResult ReloadResponse(Session* session);
|
||||
void VerifyTestKeys(Session* session);
|
||||
// Set the default key control block for all keys. This is used in
|
||||
// CreateDefaultResponse. The key control block determines the restrictions
|
||||
// that OEMCrypto should place on a key's use. For example, it specifies the
|
||||
// minimum HDCP requirement and whether the key can only be used with a secure
|
||||
// video path. See the section "Key Control Block" in the document "Widevine
|
||||
// Modular DRM Security Integration Guide for CENC".
|
||||
void set_control(uint32_t control) { control_ = control; }
|
||||
uint32_t control() const { return control_; }
|
||||
// Set the number of keys to use in the license.
|
||||
void set_num_keys(uint32_t num_keys) { num_keys_ = num_keys; }
|
||||
uint32_t num_keys() const { return num_keys_; }
|
||||
// Get/Set the pst for the license and usage table entry.
|
||||
const std::string& pst() const { return pst_; }
|
||||
void set_pst(const std::string& pst) { pst_ = pst; }
|
||||
// Set the minimum SRM version for the license.
|
||||
void set_minimum_srm_version(uint32_t minimum_srm_version) {
|
||||
minimum_srm_version_ = minimum_srm_version;
|
||||
}
|
||||
// Change the hash of the core request. This should cause the response to be
|
||||
// rejected.
|
||||
void BreakRequestHash() { request_hash_[3] ^= 42; }
|
||||
// Set the API version for the license itself. This will be used in
|
||||
// CreateDefaultResponse.
|
||||
void set_api_version(uint32_t api_version) { api_version_ = api_version; }
|
||||
uint32_t api_version() const { return api_version_; }
|
||||
void set_update_mac_keys(bool update_mac_keys) {
|
||||
update_mac_keys_ = update_mac_keys;
|
||||
}
|
||||
void set_license_type(OEMCrypto_LicenseType license_type) {
|
||||
license_type_ = license_type;
|
||||
}
|
||||
// Skip the nonce check when verifying the license request.
|
||||
void skip_nonce_check() { expect_request_has_correct_nonce_ = false; }
|
||||
// This sets the key id of the specified key to the specified string.
|
||||
// This is used to test with different key id lengths.
|
||||
void SetKeyId(size_t index, const string& key_id);
|
||||
|
||||
protected:
|
||||
void VerifyRequestSignature(const vector<uint8_t>& data,
|
||||
const vector<uint8_t>& generated_signature,
|
||||
size_t core_message_length) override;
|
||||
// Verify the values of the core response.
|
||||
virtual void FillAndVerifyCoreRequest(
|
||||
const std::string& core_message_string) override;
|
||||
|
||||
// The default key control bits used with CreateDefaultResponse.
|
||||
uint32_t control_;
|
||||
// The number of keys in the license response.
|
||||
uint32_t num_keys_;
|
||||
// If non-empty, the license's provider session token.
|
||||
std::string pst_;
|
||||
// If non-zero, the minimum SRM version.
|
||||
uint32_t minimum_srm_version_;
|
||||
// If true, the license contains new mac keys for signing renewals.
|
||||
bool update_mac_keys_;
|
||||
// API version for the license itself. If this is 0 when the license request
|
||||
// is signed, it will be set to the same as OEMCrypto's API version. It may
|
||||
// be set to a lower value in order to test backwards compatibility.
|
||||
uint32_t api_version_;
|
||||
// If true, then we expect the nonce in the core request to match that in
|
||||
// session. This is usually true, but when we are testing how OEMCrypto
|
||||
// handles a bad nonce, we don't want to.
|
||||
bool expect_request_has_correct_nonce_;
|
||||
// Whether this is a content license or an entitlement license. Used in
|
||||
// CreateDefaultResponse.
|
||||
OEMCrypto_LicenseType license_type_;
|
||||
uint8_t request_hash_[ODK_SHA256_HASH_SIZE];
|
||||
};
|
||||
|
||||
class RenewalRoundTrip
|
||||
: public RoundTrip<
|
||||
/* CoreRequest */ oemcrypto_core_message::ODK_RenewalRequest,
|
||||
OEMCrypto_PrepAndSignRenewalRequest,
|
||||
// Renewal response info is same as request:
|
||||
/* CoreResponse */ oemcrypto_core_message::ODK_RenewalRequest,
|
||||
/* ResponseData */ MessageData> {
|
||||
public:
|
||||
RenewalRoundTrip(LicenseRoundTrip* license_messages)
|
||||
: RoundTrip(license_messages->session()),
|
||||
license_messages_(license_messages),
|
||||
refresh_object_(),
|
||||
renewal_duration_seconds_(
|
||||
license_messages->core_response()
|
||||
.timer_limits.initial_renewal_duration_seconds),
|
||||
is_release_(false) {}
|
||||
void CreateDefaultResponse() override;
|
||||
void EncryptAndSignResponse() override;
|
||||
OEMCryptoResult LoadResponse() override { return LoadResponse(session_); }
|
||||
OEMCryptoResult LoadResponse(Session* session) override;
|
||||
uint64_t renewal_duration_seconds() const {
|
||||
return renewal_duration_seconds_;
|
||||
}
|
||||
void set_renewal_duration_seconds(uint64_t renewal_duration_seconds) {
|
||||
renewal_duration_seconds_ = renewal_duration_seconds;
|
||||
}
|
||||
void set_is_release(bool is_release) { is_release_ = is_release; }
|
||||
|
||||
protected:
|
||||
void VerifyRequestSignature(const vector<uint8_t>& data,
|
||||
const vector<uint8_t>& generated_signature,
|
||||
size_t core_message_length) override;
|
||||
// Verify the values of the core response.
|
||||
virtual void FillAndVerifyCoreRequest(
|
||||
const std::string& core_message_string) override;
|
||||
LicenseRoundTrip* license_messages_;
|
||||
OEMCrypto_KeyRefreshObject refresh_object_;
|
||||
uint64_t renewal_duration_seconds_;
|
||||
bool is_release_; // If this is a license release, and not a real renewal.
|
||||
};
|
||||
|
||||
class EntitledMessage {
|
||||
public:
|
||||
EntitledMessage(LicenseRoundTrip* license_messages)
|
||||
: license_messages_(license_messages), num_keys_() {}
|
||||
void FillKeyArray();
|
||||
void MakeOneKey(size_t entitlement_key_index);
|
||||
void SetEntitledKeySession(uint32_t key_session) {
|
||||
key_session_ = key_session;
|
||||
}
|
||||
void LoadKeys(OEMCryptoResult expected_sts);
|
||||
void set_num_keys(uint32_t num_keys) { num_keys_ = num_keys; }
|
||||
uint32_t num_keys() const { return num_keys_; }
|
||||
void SetEntitlementKeyId(unsigned int index, const std::string& key_id);
|
||||
void SetContentKeyId(unsigned int index, const std::string& key_id);
|
||||
// Verify that key control blocks of the loaded keys.
|
||||
void VerifyEntitlementTestKeys();
|
||||
|
||||
private:
|
||||
// Find the offset of the give pointer, relative to |entitled_key_data_|.
|
||||
OEMCrypto_Substring FindSubstring(const void* ptr, size_t size);
|
||||
|
||||
LicenseRoundTrip* license_messages_;
|
||||
uint32_t num_keys_;
|
||||
// Clear Entitlement key data. This is the backing data for
|
||||
// |entitled_key_array_|.
|
||||
EntitledContentKeyData entitled_key_data_[kMaxNumKeys];
|
||||
// Entitled key object. Pointers are backed by |entitled_key_data_|.
|
||||
OEMCrypto_EntitledContentKeyObject entitled_key_array_[kMaxNumKeys];
|
||||
uint32_t key_session_;
|
||||
};
|
||||
|
||||
class Session {
|
||||
public:
|
||||
Session();
|
||||
~Session();
|
||||
|
||||
// Returns the most recently generated nonce.
|
||||
// Valid after call to GenerateNonce.
|
||||
uint32_t nonce() const { return nonce_; }
|
||||
// Valid after call to open().
|
||||
uint32_t session_id() const { return (uint32_t)session_id_; }
|
||||
// Call OEMCrypto_OpenSession, with GTest ASSERTs.
|
||||
void open();
|
||||
// Call OEMCrypto_CloseSession, with GTest ASSERTs.
|
||||
void close();
|
||||
// Artifically set session id without calling OEMCrypto_OpenSession. This is
|
||||
// used in core/test/generic_crypto_unittest.cpp.
|
||||
void SetSessionId(uint32_t session_id);
|
||||
uint32_t GetOecSessionId() { return session_id_; }
|
||||
// Generates one nonce. If error_counter is null, this will sleep 1 second
|
||||
// and try again if a nonce flood has been detected. If error_counter is
|
||||
// not null, it will be incremented when a nonce flood is detected.
|
||||
void GenerateNonce(int* error_counter = nullptr);
|
||||
// Fill the vectors with test context which generate known mac and enc keys.
|
||||
void FillDefaultContext(vector<uint8_t>* mac_context,
|
||||
vector<uint8_t>* enc_context);
|
||||
// Generate known mac and enc keys using OEMCrypto_GenerateDerivedKeys and
|
||||
// also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
||||
void GenerateDerivedKeysFromKeybox(const wvoec::WidevineKeybox& keybox);
|
||||
// Generate known mac and enc keys using OEMCrypto_DeriveKeysFromSessionKey
|
||||
// and also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
||||
void GenerateDerivedKeysFromSessionKey();
|
||||
// Encrypt a block of data using CTR mode.
|
||||
void EncryptCTR(const vector<uint8_t>& in_buffer, const uint8_t* key,
|
||||
const uint8_t* starting_iv, vector<uint8_t>* out_buffer);
|
||||
// Encrypt some data and pass to OEMCrypto_DecryptCENC to verify decryption.
|
||||
void TestDecryptCTR(bool select_key_first = true,
|
||||
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
|
||||
int key_index = 0);
|
||||
// Verify that an attempt to select an expired key either succeeds, or gives
|
||||
// an actionable error code.
|
||||
void TestSelectExpired(unsigned int key_index);
|
||||
// Calls OEMCrypto_GetOEMPublicCertificate and OEMCrypto_LoadOEMPrivateKey and
|
||||
// loads the OEM cert's public rsa key into public_rsa_.
|
||||
void LoadOEMCert(bool verify_cert = false);
|
||||
// Calls OEMCrypto_RewrapDeviceRSAKey with the given provisioning response
|
||||
// message. If force is true, we assert that the key loads successfully.
|
||||
void RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted,
|
||||
size_t message_size, const std::vector<uint8_t>& signature,
|
||||
vector<uint8_t>* wrapped_key, bool force);
|
||||
// Loads the specified RSA public key into public_rsa_. If rsa_key is null,
|
||||
// the default test key is loaded.
|
||||
void PreparePublicKey(const uint8_t* rsa_key = nullptr,
|
||||
size_t rsa_key_length = 0);
|
||||
// Verifies the given signature is from the given message and RSA key, pkey.
|
||||
static bool VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||
size_t message_length,
|
||||
const uint8_t* signature,
|
||||
size_t signature_length);
|
||||
// Verify that the message was signed by the private key associated with
|
||||
// |public_rsa_| using the specified padding scheme.
|
||||
void VerifyRSASignature(const vector<uint8_t>& message,
|
||||
const uint8_t* signature, size_t signature_length,
|
||||
RSA_Padding_Scheme padding_scheme);
|
||||
// Encrypts a known session key with public_rsa_ for use in future calls to
|
||||
// OEMCrypto_DeriveKeysFromSessionKey or OEMCrypto_RewrapDeviceRSAKey30.
|
||||
// The unencrypted session key is stored in session_key.
|
||||
bool GenerateRSASessionKey(vector<uint8_t>* session_key,
|
||||
vector<uint8_t>* enc_session_key);
|
||||
// Calls OEMCrypto_RewrapDeviceRSAKey30 with the given provisioning response
|
||||
// message. If force is true, we assert that the key loads successfully.
|
||||
void RewrapRSAKey30(const struct RSAPrivateKeyMessage& encrypted,
|
||||
const std::vector<uint8_t>& encrypted_message_key,
|
||||
vector<uint8_t>* wrapped_key, bool force);
|
||||
// Loads the specified wrapped_rsa_key into OEMCrypto, and then runs
|
||||
// GenerateDerivedKeysFromSessionKey to install known encryption and mac keys.
|
||||
void InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key);
|
||||
// Creates a new usage entry, and keeps track of the index.
|
||||
// If status is null, we expect success, otherwise status is set to the
|
||||
// return value.
|
||||
void CreateNewUsageEntry(OEMCryptoResult* status = nullptr);
|
||||
// Copy encrypted usage entry from other session, and then load it.
|
||||
// This session must already be open.
|
||||
void LoadUsageEntry(uint32_t index, const vector<uint8_t>& buffer);
|
||||
// Copy encrypted usage entry from other session.
|
||||
// This session must already be open.
|
||||
void LoadUsageEntry(const Session& other) {
|
||||
LoadUsageEntry(other.usage_entry_number(), other.encrypted_usage_entry());
|
||||
}
|
||||
// Reload previously used usage entry.
|
||||
void ReloadUsageEntry() { LoadUsageEntry(*this); }
|
||||
// Update the usage entry and save the header to the specified buffer.
|
||||
void UpdateUsageEntry(std::vector<uint8_t>* header_buffer);
|
||||
// The usage entry number for this session's usage entry.
|
||||
uint32_t usage_entry_number() const { return usage_entry_number_; }
|
||||
void set_usage_entry_number(uint32_t v) { usage_entry_number_ = v; }
|
||||
// The encrypted buffer holding the recently updated and saved usage entry.
|
||||
const vector<uint8_t>& encrypted_usage_entry() const {
|
||||
return encrypted_usage_entry_;
|
||||
}
|
||||
// Generates a usage report for the specified pst. If there is success,
|
||||
// the report's signature is verified, and several fields are given sanity
|
||||
// checks. If |other| is not null, then the mac keys are copied from other in
|
||||
// order to verify signatures.
|
||||
void GenerateReport(const std::string& pst,
|
||||
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
|
||||
Session* other = 0);
|
||||
// Move this usage entry to a new index.
|
||||
void MoveUsageEntry(uint32_t new_index, std::vector<uint8_t>* header_buffer,
|
||||
OEMCryptoResult expect_result = OEMCrypto_SUCCESS);
|
||||
// PST used in FillSimpleMesage.
|
||||
string pst() const { return pst_; }
|
||||
// Returns a pointer-like thing to the usage report generated by the previous
|
||||
// call to GenerateReport.
|
||||
wvutil::Unpacked_PST_Report pst_report() {
|
||||
return wvutil::Unpacked_PST_Report(&pst_report_buffer_[0]);
|
||||
}
|
||||
// Verify the values in the PST report. The signature should have been
|
||||
// verified in GenerateReport, above.
|
||||
void VerifyPST(const Test_PST_Report& report);
|
||||
// Verify the Usage Report. If any time is greater than 10 minutes, it is
|
||||
// assumed to be an absolute time, and time_since will be computed relative to
|
||||
// now.
|
||||
void VerifyReport(Test_PST_Report report,
|
||||
int64_t time_license_received = 0,
|
||||
int64_t time_first_decrypt = 0,
|
||||
int64_t time_last_decrypt = 0);
|
||||
// Create an entry in the old usage table based on the given report.
|
||||
void CreateOldEntry(const Test_PST_Report &report);
|
||||
// Create a new entry and copy the old entry into it. Then very the report
|
||||
// is right.
|
||||
void CopyAndVerifyOldEntry(const Test_PST_Report &report,
|
||||
std::vector<uint8_t>* header_buffer);
|
||||
|
||||
// The unencrypted license response or license renewal response.
|
||||
MessageData& license() { return license_; }
|
||||
|
||||
void set_license(const MessageData& license) { license_ = license; }
|
||||
|
||||
const KeyDeriver& key_deriver() const { return key_deriver_; }
|
||||
void set_mac_keys(const uint8_t* mac_keys) {
|
||||
key_deriver_.set_mac_keys(mac_keys);
|
||||
}
|
||||
|
||||
private:
|
||||
// This compares the actual result with the expected result. If OEMCrypto is
|
||||
// an older version, we allow it to report an equivalent error code.
|
||||
void TestDecryptResult(OEMCryptoResult expected_result,
|
||||
OEMCryptoResult actual_select_result,
|
||||
OEMCryptoResult actual_decryt_result);
|
||||
|
||||
bool open_;
|
||||
bool forced_session_id_;
|
||||
OEMCrypto_SESSION session_id_;
|
||||
KeyDeriver key_deriver_;
|
||||
uint32_t nonce_;
|
||||
RSA* public_rsa_;
|
||||
vector<uint8_t> pst_report_buffer_;
|
||||
MessageData license_;
|
||||
|
||||
vector<uint8_t> encrypted_usage_entry_;
|
||||
uint32_t usage_entry_number_;
|
||||
string pst_;
|
||||
};
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_OEC_SESSION_UTIL_H_
|
||||
688
oemcrypto/test/oec_test_data.h
Normal file
688
oemcrypto/test/oec_test_data.h
Normal file
@@ -0,0 +1,688 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Test data for OEMCrypto unit tests.
|
||||
//
|
||||
#ifndef CDM_OEC_TEST_DATA_H_
|
||||
#define CDM_OEC_TEST_DATA_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "OEMCryptoCAS.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// This is a test keybox. It will not be accepted by production systems. By
|
||||
// using a known keybox for these tests, the results for a given set of inputs
|
||||
// to a test are predictable and can be compared to the actual results.
|
||||
static const WidevineKeybox kTestKeybox = {
|
||||
// Sample keybox used for test vectors
|
||||
{
|
||||
// deviceID = WidevineTestOnlyKeybox000
|
||||
0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65,
|
||||
0x54, 0x65, 0x73, 0x74, 0x4f, 0x6e, 0x6c, 0x79,
|
||||
0x4b, 0x65, 0x79, 0x62, 0x6f, 0x78, 0x30, 0x30,
|
||||
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}, {
|
||||
// key
|
||||
0xe4, 0xff, 0x57, 0x4c, 0x32, 0x2e, 0xf5, 0x34,
|
||||
0x26, 0x21, 0x2c, 0xb3, 0xed, 0x37, 0xf3, 0x5e,
|
||||
}, {
|
||||
// data (system ID 7912 = 1EE8).
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x1e, 0xe8,
|
||||
0xca, 0x1e, 0x71, 0x7c, 0xfb, 0xe8, 0xa3, 0x94,
|
||||
0x52, 0x0a, 0x6b, 0x71, 0x37, 0xd2, 0x69, 0xfa,
|
||||
0x5a, 0xc6, 0xb5, 0x4c, 0x6b, 0x46, 0x63, 0x9b,
|
||||
0xbe, 0x80, 0x3d, 0xbb, 0x4f, 0xf7, 0x4c, 0x5f,
|
||||
0x6f, 0x55, 0x0e, 0x3d, 0x3d, 0x9a, 0xcf, 0x81,
|
||||
0x12, 0x5d, 0x52, 0xe0, 0x47, 0x8c, 0xda, 0x0b,
|
||||
0xf4, 0x31, 0x41, 0x13, 0xd0, 0xd5, 0x2d, 0xa0,
|
||||
0x5b, 0x20, 0x9a, 0xed, 0x51, 0x5d, 0x13, 0xd6,
|
||||
}, {
|
||||
// magic
|
||||
0x6b, 0x62, 0x6f, 0x78,
|
||||
}, {
|
||||
// Crc
|
||||
0x39, 0xf2, 0x94, 0xa7,
|
||||
}
|
||||
};
|
||||
|
||||
// A 2048 bit RSA key in PKCS#8 PrivateKeyInfo format
|
||||
// Used to verify the functions that manipulate RSA keys.
|
||||
static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = {
|
||||
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
||||
0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01,
|
||||
0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa7, 0x00,
|
||||
0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a,
|
||||
0x40, 0xb4, 0xe1, 0x15, 0x94, 0x58, 0x11, 0x4f,
|
||||
0x94, 0x58, 0xdd, 0xde, 0xa7, 0x1f, 0x3c, 0x2c,
|
||||
0xe0, 0x88, 0x09, 0x29, 0x61, 0x57, 0x67, 0x5e,
|
||||
0x56, 0x7e, 0xee, 0x27, 0x8f, 0x59, 0x34, 0x9a,
|
||||
0x2a, 0xaa, 0x9d, 0xb4, 0x4e, 0xfa, 0xa7, 0x6a,
|
||||
0xd4, 0xc9, 0x7a, 0x53, 0xc1, 0x4e, 0x9f, 0xe3,
|
||||
0x34, 0xf7, 0x3d, 0xb7, 0xc9, 0x10, 0x47, 0x4f,
|
||||
0x28, 0xda, 0x3f, 0xce, 0x31, 0x7b, 0xfd, 0x06,
|
||||
0x10, 0xeb, 0xf7, 0xbe, 0x92, 0xf9, 0xaf, 0xfb,
|
||||
0x3e, 0x68, 0xda, 0xee, 0x1a, 0x64, 0x4c, 0xf3,
|
||||
0x29, 0xf2, 0x73, 0x9e, 0x39, 0xd8, 0xf6, 0x6f,
|
||||
0xd8, 0xb2, 0x80, 0x82, 0x71, 0x8e, 0xb5, 0xa4,
|
||||
0xf2, 0xc2, 0x3e, 0xcd, 0x0a, 0xca, 0xb6, 0x04,
|
||||
0xcd, 0x9a, 0x13, 0x8b, 0x54, 0x73, 0x54, 0x25,
|
||||
0x54, 0x8c, 0xbe, 0x98, 0x7a, 0x67, 0xad, 0xda,
|
||||
0xb3, 0x4e, 0xb3, 0xfa, 0x82, 0xa8, 0x4a, 0x67,
|
||||
0x98, 0x56, 0x57, 0x54, 0x71, 0xcd, 0x12, 0x7f,
|
||||
0xed, 0xa3, 0x01, 0xc0, 0x6a, 0x8b, 0x24, 0x03,
|
||||
0x96, 0x88, 0xbe, 0x97, 0x66, 0x2a, 0xbc, 0x53,
|
||||
0xc9, 0x83, 0x06, 0x51, 0x5a, 0x88, 0x65, 0x13,
|
||||
0x18, 0xe4, 0x3a, 0xed, 0x6b, 0xf1, 0x61, 0x5b,
|
||||
0x4c, 0xc8, 0x1e, 0xf4, 0xc2, 0xae, 0x08, 0x5e,
|
||||
0x2d, 0x5f, 0xf8, 0x12, 0x7f, 0xa2, 0xfc, 0xbb,
|
||||
0x21, 0x18, 0x30, 0xda, 0xfe, 0x40, 0xfb, 0x01,
|
||||
0xca, 0x2e, 0x37, 0x0e, 0xce, 0xdd, 0x76, 0x87,
|
||||
0x82, 0x46, 0x0b, 0x3a, 0x77, 0x8f, 0xc0, 0x72,
|
||||
0x07, 0x2c, 0x7f, 0x9d, 0x1e, 0x86, 0x5b, 0xed,
|
||||
0x27, 0x29, 0xdf, 0x03, 0x97, 0x62, 0xef, 0x44,
|
||||
0xd3, 0x5b, 0x3d, 0xdb, 0x9c, 0x5e, 0x1b, 0x7b,
|
||||
0x39, 0xb4, 0x0b, 0x6d, 0x04, 0x6b, 0xbb, 0xbb,
|
||||
0x2c, 0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03,
|
||||
0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x5e,
|
||||
0x79, 0x65, 0x49, 0xa5, 0x76, 0x79, 0xf9, 0x05,
|
||||
0x45, 0x0f, 0xf4, 0x03, 0xbd, 0xa4, 0x7d, 0x29,
|
||||
0xd5, 0xde, 0x33, 0x63, 0xd8, 0xb8, 0xac, 0x97,
|
||||
0xeb, 0x3f, 0x5e, 0x55, 0xe8, 0x7d, 0xf3, 0xe7,
|
||||
0x3b, 0x5c, 0x2d, 0x54, 0x67, 0x36, 0xd6, 0x1d,
|
||||
0x46, 0xf5, 0xca, 0x2d, 0x8b, 0x3a, 0x7e, 0xdc,
|
||||
0x45, 0x38, 0x79, 0x7e, 0x65, 0x71, 0x5f, 0x1c,
|
||||
0x5e, 0x79, 0xb1, 0x40, 0xcd, 0xfe, 0xc5, 0xe1,
|
||||
0xc1, 0x6b, 0x78, 0x04, 0x4e, 0x8e, 0x79, 0xf9,
|
||||
0x0a, 0xfc, 0x79, 0xb1, 0x5e, 0xb3, 0x60, 0xe3,
|
||||
0x68, 0x7b, 0xc6, 0xef, 0xcb, 0x71, 0x4c, 0xba,
|
||||
0xa7, 0x79, 0x5c, 0x7a, 0x81, 0xd1, 0x71, 0xe7,
|
||||
0x00, 0x21, 0x13, 0xe2, 0x55, 0x69, 0x0e, 0x75,
|
||||
0xbe, 0x09, 0xc3, 0x4f, 0xa9, 0xc9, 0x68, 0x22,
|
||||
0x0e, 0x97, 0x8d, 0x89, 0x6e, 0xf1, 0xe8, 0x88,
|
||||
0x7a, 0xd1, 0xd9, 0x09, 0x5d, 0xd3, 0x28, 0x78,
|
||||
0x25, 0x0b, 0x1c, 0x47, 0x73, 0x25, 0xcc, 0x21,
|
||||
0xb6, 0xda, 0xc6, 0x24, 0x5a, 0xd0, 0x37, 0x14,
|
||||
0x46, 0xc7, 0x94, 0x69, 0xe4, 0x43, 0x6f, 0x47,
|
||||
0xde, 0x00, 0x33, 0x4d, 0x8f, 0x95, 0x72, 0xfa,
|
||||
0x68, 0x71, 0x17, 0x66, 0x12, 0x1a, 0x87, 0x27,
|
||||
0xf7, 0xef, 0x7e, 0xe0, 0x35, 0x58, 0xf2, 0x4d,
|
||||
0x6f, 0x35, 0x01, 0xaa, 0x96, 0xe2, 0x3d, 0x51,
|
||||
0x13, 0x86, 0x9c, 0x79, 0xd0, 0xb7, 0xb6, 0x64,
|
||||
0xe8, 0x86, 0x65, 0x50, 0xbf, 0xcc, 0x27, 0x53,
|
||||
0x1f, 0x51, 0xd4, 0xca, 0xbe, 0xf5, 0xdd, 0x77,
|
||||
0x70, 0x98, 0x0f, 0xee, 0xa8, 0x96, 0x07, 0x5f,
|
||||
0x45, 0x6a, 0x7a, 0x0d, 0x03, 0x9c, 0x4f, 0x29,
|
||||
0xf6, 0x06, 0xf3, 0x5d, 0x58, 0x6c, 0x47, 0xd0,
|
||||
0x96, 0xa9, 0x03, 0x17, 0xbb, 0x4e, 0xc9, 0x21,
|
||||
0xe0, 0xac, 0xcd, 0x78, 0x78, 0xb2, 0xfe, 0x81,
|
||||
0xb2, 0x51, 0x53, 0xa6, 0x1f, 0x98, 0x45, 0x02,
|
||||
0x81, 0x81, 0x00, 0xcf, 0x73, 0x8c, 0xbe, 0x6d,
|
||||
0x45, 0x2d, 0x0c, 0x0b, 0x5d, 0x5c, 0x6c, 0x75,
|
||||
0x78, 0xcc, 0x35, 0x48, 0xb6, 0x98, 0xf1, 0xb9,
|
||||
0x64, 0x60, 0x8c, 0x43, 0xeb, 0x85, 0xab, 0x04,
|
||||
0xb6, 0x7d, 0x1b, 0x71, 0x75, 0x06, 0xe2, 0xda,
|
||||
0x84, 0x68, 0x2e, 0x7f, 0x4c, 0xe3, 0x73, 0xb4,
|
||||
0xde, 0x51, 0x4b, 0xb6, 0x51, 0x86, 0x7b, 0xd0,
|
||||
0xe6, 0x4d, 0xf3, 0xd1, 0xcf, 0x1a, 0xfe, 0x7f,
|
||||
0x3a, 0x83, 0xba, 0xb3, 0xe1, 0xff, 0x54, 0x13,
|
||||
0x93, 0xd7, 0x9c, 0x27, 0x80, 0xb7, 0x1e, 0x64,
|
||||
0x9e, 0xf7, 0x32, 0x2b, 0x46, 0x29, 0xf7, 0xf8,
|
||||
0x18, 0x6c, 0xf7, 0x4a, 0xbe, 0x4b, 0xee, 0x96,
|
||||
0x90, 0x8f, 0xa2, 0x16, 0x22, 0x6a, 0xcc, 0x48,
|
||||
0x06, 0x74, 0x63, 0x43, 0x7f, 0x27, 0x22, 0x44,
|
||||
0x3c, 0x2d, 0x3b, 0x62, 0xf1, 0x1c, 0xb4, 0x27,
|
||||
0x33, 0x85, 0x26, 0x60, 0x48, 0x16, 0xcb, 0xef,
|
||||
0xf8, 0xcd, 0x37, 0x02, 0x81, 0x81, 0x00, 0xce,
|
||||
0x15, 0x43, 0x6e, 0x4b, 0x0f, 0xf9, 0x3f, 0x87,
|
||||
0xc3, 0x41, 0x45, 0x97, 0xb1, 0x49, 0xc2, 0x19,
|
||||
0x23, 0x87, 0xe4, 0x24, 0x1c, 0x64, 0xe5, 0x28,
|
||||
0xcb, 0x43, 0x10, 0x14, 0x14, 0x0e, 0x19, 0xcb,
|
||||
0xbb, 0xdb, 0xfd, 0x11, 0x9d, 0x17, 0x68, 0x78,
|
||||
0x6d, 0x61, 0x70, 0x63, 0x3a, 0xa1, 0xb3, 0xf3,
|
||||
0xa7, 0x5b, 0x0e, 0xff, 0xb7, 0x61, 0x11, 0x54,
|
||||
0x91, 0x99, 0xe5, 0x91, 0x32, 0x2d, 0xeb, 0x3f,
|
||||
0xd8, 0x3e, 0xf7, 0xd4, 0xcb, 0xd2, 0xa3, 0x41,
|
||||
0xc1, 0xee, 0xc6, 0x92, 0x13, 0xeb, 0x7f, 0x42,
|
||||
0x58, 0xf4, 0xd0, 0xb2, 0x74, 0x1d, 0x8e, 0x87,
|
||||
0x46, 0xcd, 0x14, 0xb8, 0x16, 0xad, 0xb5, 0xbd,
|
||||
0x0d, 0x6c, 0x95, 0x5a, 0x16, 0xbf, 0xe9, 0x53,
|
||||
0xda, 0xfb, 0xed, 0x83, 0x51, 0x67, 0xa9, 0x55,
|
||||
0xab, 0x54, 0x02, 0x95, 0x20, 0xa6, 0x68, 0x17,
|
||||
0x53, 0xa8, 0xea, 0x43, 0xe5, 0xb0, 0xa3, 0x02,
|
||||
0x81, 0x80, 0x67, 0x9c, 0x32, 0x83, 0x39, 0x57,
|
||||
0xff, 0x73, 0xb0, 0x89, 0x64, 0x8b, 0xd6, 0xf0,
|
||||
0x0a, 0x2d, 0xe2, 0xaf, 0x30, 0x1c, 0x2a, 0x97,
|
||||
0xf3, 0x90, 0x9a, 0xab, 0x9b, 0x0b, 0x1b, 0x43,
|
||||
0x79, 0xa0, 0xa7, 0x3d, 0xe7, 0xbe, 0x8d, 0x9c,
|
||||
0xeb, 0xdb, 0xad, 0x40, 0xdd, 0xa9, 0x00, 0x80,
|
||||
0xb8, 0xe1, 0xb3, 0xa1, 0x6c, 0x25, 0x92, 0xe4,
|
||||
0x33, 0xb2, 0xbe, 0xeb, 0x4d, 0x74, 0x26, 0x5f,
|
||||
0x37, 0x43, 0x9c, 0x6c, 0x17, 0x76, 0x0a, 0x81,
|
||||
0x20, 0x82, 0xa1, 0x48, 0x2c, 0x2d, 0x45, 0xdc,
|
||||
0x0f, 0x62, 0x43, 0x32, 0xbb, 0xeb, 0x59, 0x41,
|
||||
0xf9, 0xca, 0x58, 0xce, 0x4a, 0x66, 0x53, 0x54,
|
||||
0xc8, 0x28, 0x10, 0x1e, 0x08, 0x71, 0x16, 0xd8,
|
||||
0x02, 0x71, 0x41, 0x58, 0xd4, 0x56, 0xcc, 0xf5,
|
||||
0xb1, 0x31, 0xa3, 0xed, 0x00, 0x85, 0x09, 0xbf,
|
||||
0x35, 0x95, 0x41, 0x29, 0x40, 0x19, 0x83, 0x35,
|
||||
0x24, 0x69, 0x02, 0x81, 0x80, 0x55, 0x10, 0x0b,
|
||||
0xcc, 0x3b, 0xa9, 0x75, 0x3d, 0x16, 0xe1, 0xae,
|
||||
0x50, 0x76, 0x63, 0x94, 0x49, 0x4c, 0xad, 0x10,
|
||||
0xcb, 0x47, 0x68, 0x7c, 0xf0, 0xe5, 0xdc, 0xb8,
|
||||
0x6a, 0xab, 0x8e, 0xf7, 0x9f, 0x08, 0x2c, 0x1b,
|
||||
0x8a, 0xa2, 0xb9, 0x8f, 0xce, 0xec, 0x5e, 0x61,
|
||||
0xa8, 0xcd, 0x1c, 0x87, 0x60, 0x4a, 0xc3, 0x1a,
|
||||
0x5f, 0xdf, 0x87, 0x26, 0xc6, 0xcb, 0x7c, 0x69,
|
||||
0xe4, 0x8b, 0x01, 0x06, 0x59, 0x22, 0xfa, 0x34,
|
||||
0x4b, 0x81, 0x87, 0x3c, 0x03, 0x6d, 0x02, 0x0a,
|
||||
0x77, 0xe6, 0x15, 0xd8, 0xcf, 0xa7, 0x68, 0x26,
|
||||
0x6c, 0xfa, 0x2b, 0xd9, 0x83, 0x5a, 0x2d, 0x0c,
|
||||
0x3b, 0x70, 0x1c, 0xd4, 0x48, 0xbe, 0xa7, 0x0a,
|
||||
0xd9, 0xbe, 0xdc, 0xc3, 0x0c, 0x21, 0x33, 0xb3,
|
||||
0x66, 0xff, 0x1c, 0x1b, 0xc8, 0x96, 0x76, 0xe8,
|
||||
0x6f, 0x44, 0x74, 0xbc, 0x9b, 0x1c, 0x7d, 0xc8,
|
||||
0xac, 0x21, 0xa8, 0x6e, 0x37, 0x02, 0x81, 0x80,
|
||||
0x2c, 0x7c, 0xad, 0x1e, 0x75, 0xf6, 0x69, 0x1d,
|
||||
0xe7, 0xa6, 0xca, 0x74, 0x7d, 0x67, 0xc8, 0x65,
|
||||
0x28, 0x66, 0xc4, 0x43, 0xa6, 0xbd, 0x40, 0x57,
|
||||
0xae, 0xb7, 0x65, 0x2c, 0x52, 0xf9, 0xe4, 0xc7,
|
||||
0x81, 0x7b, 0x56, 0xa3, 0xd2, 0x0d, 0xe8, 0x33,
|
||||
0x70, 0xcf, 0x06, 0x84, 0xb3, 0x4e, 0x44, 0x50,
|
||||
0x75, 0x61, 0x96, 0x86, 0x4b, 0xb6, 0x2b, 0xad,
|
||||
0xf0, 0xad, 0x57, 0xd0, 0x37, 0x0d, 0x1d, 0x35,
|
||||
0x50, 0xcb, 0x69, 0x22, 0x39, 0x29, 0xb9, 0x3a,
|
||||
0xd3, 0x29, 0x23, 0x02, 0x60, 0xf7, 0xab, 0x30,
|
||||
0x40, 0xda, 0x8e, 0x4d, 0x45, 0x70, 0x26, 0xf4,
|
||||
0xa2, 0x0d, 0xd0, 0x64, 0x5d, 0x47, 0x3c, 0x18,
|
||||
0xf4, 0xd4, 0x52, 0x95, 0x00, 0xae, 0x84, 0x6b,
|
||||
0x47, 0xb2, 0x3c, 0x82, 0xd3, 0x72, 0x53, 0xde,
|
||||
0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18,
|
||||
0x56, 0xfe, 0x39, 0x28, 0x33, 0xe0, 0xdb, 0x03 };
|
||||
|
||||
// A 3072 bit RSA key in PKCS#8 PrivateKeyInfo format
|
||||
// Used to verify the functions that manipulate RSA keys.
|
||||
static const uint8_t kTestRSAPKCS8PrivateKeyInfo3_3072[] = {
|
||||
0x30, 0x82, 0x06, 0xfe, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
||||
0x06, 0xe8, 0x30, 0x82, 0x06, 0xe4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
|
||||
0x81, 0x00, 0xe3, 0x32, 0x2f, 0x0a, 0x94, 0x06, 0x46, 0x99, 0x0a, 0x58,
|
||||
0xda, 0xd0, 0x9b, 0x2b, 0xe4, 0x2a, 0x35, 0xdf, 0xb7, 0x9b, 0x5e, 0xbf,
|
||||
0xfb, 0xe5, 0x24, 0x47, 0x5a, 0x94, 0x06, 0x04, 0xe5, 0x43, 0xed, 0x37,
|
||||
0x33, 0x94, 0x09, 0xd0, 0xae, 0xad, 0x86, 0xb4, 0xc7, 0xc3, 0x56, 0x6f,
|
||||
0x88, 0x74, 0xfb, 0xab, 0xf7, 0xcf, 0xcb, 0xa6, 0x89, 0x48, 0x4a, 0x02,
|
||||
0x89, 0xcd, 0xfd, 0x83, 0x3d, 0x2a, 0x27, 0xc1, 0xa2, 0x99, 0x8e, 0xef,
|
||||
0xcf, 0x91, 0xd3, 0xb2, 0x96, 0xe7, 0x5f, 0x0c, 0xb3, 0x44, 0x6a, 0xcf,
|
||||
0xc1, 0x22, 0xb9, 0xe4, 0xd4, 0xc0, 0xf2, 0xc3, 0x8d, 0xe1, 0x43, 0x38,
|
||||
0x31, 0x9c, 0x56, 0x04, 0xd4, 0x9d, 0x41, 0x02, 0x31, 0xce, 0x7e, 0xc0,
|
||||
0x11, 0x24, 0x54, 0xb1, 0xa2, 0x99, 0x0e, 0xe2, 0x0c, 0x5b, 0x24, 0x94,
|
||||
0x85, 0xe8, 0x8c, 0x30, 0xbb, 0x12, 0x94, 0x74, 0x0f, 0x67, 0xe5, 0x69,
|
||||
0xa4, 0xc4, 0x59, 0xd6, 0x77, 0x96, 0xae, 0xc6, 0x00, 0xbe, 0xf5, 0xe6,
|
||||
0x1f, 0x71, 0x90, 0x6d, 0xdd, 0xfb, 0x7b, 0x42, 0xd0, 0xdf, 0x4b, 0x58,
|
||||
0xaf, 0x9c, 0xba, 0xcb, 0x35, 0x4b, 0xf3, 0x06, 0x3a, 0x20, 0x42, 0x97,
|
||||
0x96, 0x95, 0x47, 0xbe, 0x2d, 0xeb, 0x9a, 0xb6, 0xea, 0xe0, 0xc1, 0x1d,
|
||||
0x80, 0x61, 0x3e, 0x8e, 0x18, 0x66, 0xf4, 0x26, 0x77, 0xcf, 0x56, 0x27,
|
||||
0x8b, 0xde, 0x93, 0x94, 0x3e, 0x1d, 0xe4, 0x5f, 0x6d, 0xf2, 0x39, 0x03,
|
||||
0x15, 0x4f, 0x2e, 0x58, 0x59, 0x75, 0x19, 0xb9, 0x24, 0x87, 0xd4, 0xff,
|
||||
0x64, 0x82, 0x11, 0x10, 0x34, 0x30, 0x09, 0x39, 0x43, 0x9c, 0xd2, 0x3b,
|
||||
0x45, 0xdc, 0x85, 0x4f, 0x6d, 0xb7, 0xbb, 0x49, 0xda, 0x3b, 0x07, 0xa2,
|
||||
0x76, 0x56, 0xa0, 0xee, 0xa9, 0xa9, 0x52, 0xb7, 0xf1, 0xfd, 0xde, 0xa1,
|
||||
0x6f, 0x0e, 0x7f, 0x82, 0x3f, 0x9e, 0x3d, 0x46, 0xcd, 0x48, 0x55, 0xe8,
|
||||
0x59, 0x65, 0xd8, 0xc7, 0xe4, 0x6b, 0xe6, 0xc0, 0xdd, 0x6e, 0x5c, 0xb7,
|
||||
0x0c, 0xdb, 0x29, 0xad, 0x8e, 0xa4, 0x86, 0xe9, 0x4d, 0xad, 0x54, 0xf9,
|
||||
0x56, 0x06, 0x0e, 0xc4, 0x2b, 0x01, 0xd9, 0x86, 0x1f, 0x65, 0xbe, 0x0d,
|
||||
0x77, 0x8d, 0x9d, 0xff, 0x37, 0x97, 0x57, 0xc3, 0x06, 0x8a, 0x05, 0x80,
|
||||
0x78, 0xd3, 0xbd, 0x91, 0xa5, 0xc1, 0x11, 0x4d, 0x99, 0x1a, 0x83, 0xd7,
|
||||
0x30, 0x1c, 0x24, 0xac, 0xdf, 0x6c, 0xc1, 0x23, 0x60, 0x76, 0x54, 0xbf,
|
||||
0x2b, 0xac, 0x34, 0xf0, 0x35, 0x92, 0x0d, 0x36, 0x29, 0x09, 0x24, 0xd5,
|
||||
0x54, 0xe9, 0x68, 0x9c, 0x90, 0x07, 0x16, 0x86, 0xb1, 0xd0, 0x9b, 0xa5,
|
||||
0x86, 0x4e, 0xce, 0xbf, 0x30, 0x9d, 0x91, 0xd7, 0xd2, 0xa6, 0x4f, 0xbb,
|
||||
0xbb, 0x9d, 0x7c, 0x0f, 0x58, 0xaa, 0xf1, 0xd0, 0x90, 0x66, 0x20, 0x48,
|
||||
0x8f, 0x29, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x81, 0x00,
|
||||
0x88, 0x41, 0x28, 0x85, 0x27, 0x91, 0x3b, 0xf5, 0xbc, 0x86, 0xdd, 0x74,
|
||||
0x0e, 0x1b, 0x9c, 0x92, 0xd4, 0x0c, 0x7f, 0x88, 0xe6, 0xa2, 0x2c, 0xe7,
|
||||
0x97, 0x82, 0x53, 0x88, 0x42, 0xb3, 0xdc, 0xeb, 0x87, 0xf0, 0x7b, 0x36,
|
||||
0x65, 0x4c, 0x89, 0xf5, 0xf7, 0xbb, 0xa3, 0xb2, 0x3a, 0xbc, 0x59, 0x12,
|
||||
0x0f, 0x7d, 0x6a, 0xf9, 0x6c, 0x21, 0x4c, 0x63, 0xd6, 0x3e, 0xff, 0x76,
|
||||
0x52, 0x7b, 0xca, 0xca, 0xe5, 0x5c, 0xf3, 0xaf, 0x34, 0x52, 0x0e, 0x22,
|
||||
0x5e, 0xdb, 0xd4, 0x34, 0x9e, 0x84, 0x77, 0x5e, 0xa8, 0xd0, 0x3f, 0xfc,
|
||||
0x1b, 0x90, 0x69, 0x27, 0xee, 0x6f, 0xe9, 0x3f, 0x17, 0x99, 0x33, 0xe7,
|
||||
0x96, 0x8e, 0xff, 0x13, 0xf0, 0x50, 0xe8, 0x9d, 0xf6, 0xd6, 0x29, 0x71,
|
||||
0xa8, 0x79, 0x80, 0x12, 0x5b, 0x22, 0xa6, 0x56, 0x62, 0xf1, 0xcf, 0xfd,
|
||||
0x4f, 0x56, 0x4a, 0x5b, 0x32, 0x3d, 0x08, 0xa0, 0x3e, 0xad, 0xc4, 0xeb,
|
||||
0x1d, 0x15, 0xca, 0x52, 0xcc, 0x2e, 0x63, 0x74, 0x22, 0xf5, 0x08, 0x16,
|
||||
0x8b, 0x8f, 0xd8, 0x79, 0x61, 0xcb, 0x08, 0x89, 0x62, 0x1e, 0xa5, 0xf3,
|
||||
0x50, 0xf3, 0x5d, 0xdb, 0x56, 0xbc, 0x7d, 0x4f, 0xab, 0xa0, 0x4d, 0xe6,
|
||||
0xe9, 0x47, 0xdd, 0x32, 0x57, 0x6f, 0x2c, 0x1d, 0xee, 0xb3, 0x4a, 0xb3,
|
||||
0x07, 0x59, 0x20, 0xb9, 0x5d, 0xe3, 0x54, 0x27, 0x3c, 0x7c, 0x2b, 0x1d,
|
||||
0x07, 0xff, 0x49, 0x93, 0xe2, 0xe3, 0xb2, 0x65, 0xf3, 0x69, 0xc1, 0x1c,
|
||||
0x2a, 0x75, 0x80, 0x16, 0x37, 0xe6, 0x00, 0x5b, 0xd3, 0x1b, 0xac, 0xca,
|
||||
0x8b, 0x8b, 0x98, 0x77, 0x81, 0x67, 0xe3, 0xdc, 0xbb, 0xc4, 0x3a, 0x45,
|
||||
0x15, 0xec, 0xd9, 0xad, 0xdb, 0x60, 0xcf, 0xe5, 0xd8, 0xd9, 0xfc, 0xcf,
|
||||
0xbe, 0x76, 0x2f, 0x5b, 0x60, 0xdb, 0x06, 0x62, 0x5b, 0x80, 0x7e, 0x53,
|
||||
0xde, 0x74, 0xb1, 0xa3, 0xb6, 0x9b, 0x14, 0xd7, 0x09, 0x65, 0x21, 0x1d,
|
||||
0xd5, 0xd3, 0x34, 0xca, 0x89, 0xe7, 0xbc, 0xf4, 0x48, 0x81, 0x6a, 0xcf,
|
||||
0x28, 0xbe, 0x74, 0x8b, 0x40, 0xad, 0x86, 0xcd, 0xa5, 0xd6, 0xfa, 0x64,
|
||||
0x9b, 0xd2, 0xd4, 0x17, 0x20, 0xd6, 0x0d, 0xbe, 0x95, 0xd4, 0xaf, 0xa5,
|
||||
0xde, 0x31, 0x0d, 0x6a, 0x90, 0xc6, 0xd0, 0x59, 0xd4, 0x8c, 0x81, 0x2d,
|
||||
0x9d, 0x09, 0xf1, 0x22, 0xf5, 0x30, 0x2d, 0xdf, 0x85, 0x54, 0x34, 0x8a,
|
||||
0xde, 0x3c, 0xce, 0xdb, 0x36, 0x9f, 0xcf, 0x12, 0x61, 0x0e, 0x99, 0x87,
|
||||
0x70, 0x51, 0x04, 0x91, 0x74, 0xc6, 0x88, 0x22, 0x75, 0x02, 0x8f, 0x7e,
|
||||
0xb5, 0x79, 0x48, 0x2f, 0xf3, 0x3b, 0xb8, 0x82, 0x3e, 0x7e, 0x45, 0xe5,
|
||||
0xb2, 0xc8, 0x4c, 0x12, 0x73, 0xb8, 0x92, 0x04, 0xd1, 0x9a, 0xae, 0xaa,
|
||||
0x08, 0xd9, 0x23, 0x54, 0x19, 0x46, 0xc8, 0x56, 0x5f, 0x5e, 0x10, 0xa1,
|
||||
0x02, 0x81, 0xc1, 0x00, 0xf6, 0x38, 0x88, 0x31, 0x06, 0x85, 0xd9, 0x00,
|
||||
0xf0, 0x6b, 0xd8, 0x7d, 0x76, 0x08, 0xc0, 0x69, 0x6a, 0xfb, 0xa4, 0xc8,
|
||||
0xdc, 0x6b, 0x00, 0xaf, 0xae, 0x52, 0x82, 0xe6, 0xba, 0xc9, 0x5e, 0xc9,
|
||||
0xb7, 0x7f, 0xa1, 0xc4, 0xcb, 0xa0, 0xbc, 0x66, 0x3c, 0x55, 0x6a, 0xea,
|
||||
0x6e, 0x42, 0xf1, 0x6b, 0xbd, 0xc4, 0xf2, 0x6b, 0x91, 0x11, 0x82, 0x20,
|
||||
0xc2, 0xe6, 0x9e, 0x96, 0x5c, 0x9a, 0x7e, 0xb3, 0x57, 0x45, 0x9c, 0x42,
|
||||
0x60, 0x4c, 0x04, 0x4f, 0x47, 0xfb, 0xa7, 0x68, 0x4e, 0x15, 0x43, 0x5a,
|
||||
0x97, 0xb3, 0xfc, 0xd2, 0x91, 0x3c, 0x11, 0x5e, 0xaf, 0x57, 0x2a, 0xa1,
|
||||
0x45, 0xa5, 0x60, 0xf0, 0xbe, 0x31, 0xe8, 0xc4, 0x0b, 0x35, 0xe3, 0x42,
|
||||
0x9b, 0x22, 0x6b, 0xa3, 0x6c, 0x49, 0x71, 0x20, 0x34, 0x3f, 0x46, 0x0b,
|
||||
0x79, 0xc9, 0xb8, 0xb4, 0xbd, 0x9c, 0xad, 0xd3, 0xd8, 0x7e, 0x95, 0x9f,
|
||||
0x9a, 0xd4, 0x03, 0xe9, 0x5a, 0x54, 0x46, 0x94, 0x39, 0x55, 0xf1, 0x28,
|
||||
0x0d, 0xd1, 0xaa, 0xc9, 0xf8, 0x28, 0x58, 0xef, 0xb0, 0x62, 0xb6, 0x2d,
|
||||
0xc7, 0xd2, 0x09, 0x3a, 0x21, 0x0f, 0x7d, 0xa1, 0xb9, 0x59, 0xd5, 0xa7,
|
||||
0x43, 0xa9, 0x51, 0xb7, 0xbf, 0x9d, 0xf3, 0x85, 0xec, 0xb3, 0xfb, 0x51,
|
||||
0x61, 0xca, 0x81, 0x4d, 0xfa, 0xf1, 0xc3, 0x94, 0x37, 0x45, 0x91, 0xf0,
|
||||
0x4b, 0xfc, 0x8e, 0xff, 0x02, 0x81, 0xc1, 0x00, 0xec, 0x38, 0x37, 0x3b,
|
||||
0xba, 0x1b, 0x83, 0xaf, 0x3a, 0x00, 0xb9, 0x5e, 0x1f, 0xc8, 0xad, 0x57,
|
||||
0xcf, 0x7c, 0xe2, 0x94, 0x95, 0xf1, 0xec, 0x0a, 0x4b, 0x40, 0xc4, 0x48,
|
||||
0xfb, 0x47, 0x5f, 0x66, 0xc6, 0xf0, 0x70, 0x14, 0xe9, 0x08, 0xe4, 0x50,
|
||||
0x29, 0x0a, 0x24, 0x57, 0x93, 0x97, 0x21, 0xd9, 0xfb, 0xc5, 0x52, 0x0a,
|
||||
0x38, 0xb9, 0x68, 0xa3, 0x4f, 0x4b, 0xf8, 0xb8, 0x24, 0xef, 0x0c, 0x42,
|
||||
0xda, 0x57, 0x32, 0x77, 0xed, 0x9c, 0x78, 0xeb, 0x10, 0x3e, 0x70, 0x67,
|
||||
0xe9, 0x01, 0x03, 0x19, 0x19, 0xdb, 0x48, 0x9e, 0x1e, 0x52, 0x23, 0x88,
|
||||
0xb6, 0x87, 0xb8, 0x0d, 0x2d, 0x0c, 0xfc, 0x90, 0x31, 0x9f, 0xa6, 0x96,
|
||||
0x0a, 0xe1, 0x34, 0x72, 0x86, 0x0e, 0x49, 0x7c, 0xfe, 0x21, 0xaa, 0x25,
|
||||
0xdd, 0x36, 0xbb, 0x1f, 0x85, 0xfe, 0x34, 0x18, 0xc2, 0x36, 0xa2, 0x7d,
|
||||
0xee, 0xd9, 0x4f, 0x8e, 0xcb, 0x49, 0x8e, 0x7a, 0x43, 0x3c, 0x52, 0x73,
|
||||
0x18, 0x60, 0xf6, 0xb7, 0x7a, 0xc4, 0x7a, 0x8a, 0x1c, 0xf0, 0xc9, 0x2e,
|
||||
0xad, 0x54, 0xb1, 0x7b, 0x8e, 0xcb, 0x4d, 0xc2, 0xbc, 0x2a, 0x72, 0xfe,
|
||||
0x61, 0x01, 0xd8, 0xff, 0x0a, 0x22, 0x6c, 0x51, 0x7e, 0x06, 0x9e, 0x9e,
|
||||
0x3c, 0xe8, 0x31, 0x98, 0xf5, 0x08, 0x34, 0x7e, 0xfa, 0x08, 0xd1, 0x14,
|
||||
0xdf, 0xfd, 0x26, 0x2f, 0x1f, 0x5a, 0x89, 0xd7, 0x02, 0x81, 0xc0, 0x76,
|
||||
0xdd, 0xed, 0xe9, 0xf5, 0x23, 0x33, 0x13, 0x3f, 0xfe, 0x60, 0xa2, 0x99,
|
||||
0x14, 0x3a, 0x87, 0xea, 0x0d, 0x18, 0x8d, 0x9b, 0xd3, 0xd0, 0x9d, 0xff,
|
||||
0xc3, 0x77, 0xcc, 0x9a, 0x0a, 0x53, 0x47, 0x80, 0xde, 0x0e, 0x23, 0xea,
|
||||
0xc6, 0x6b, 0x8d, 0xd3, 0xbc, 0xcd, 0x03, 0xe6, 0x3d, 0x4d, 0x3d, 0xdd,
|
||||
0x7c, 0xb2, 0x27, 0xf9, 0xfe, 0x00, 0xdb, 0x7e, 0x1c, 0x46, 0x1d, 0x83,
|
||||
0x11, 0x56, 0xef, 0x8f, 0xc7, 0x5c, 0x5b, 0xb3, 0x0f, 0x9f, 0xd9, 0x02,
|
||||
0x80, 0x5c, 0x5e, 0x7f, 0xab, 0xc6, 0x3b, 0x7b, 0x17, 0x7a, 0x8b, 0xd1,
|
||||
0x6f, 0xb5, 0x57, 0x07, 0xc1, 0x46, 0x24, 0x5b, 0x72, 0x2e, 0xad, 0xaa,
|
||||
0xb4, 0x7f, 0x91, 0xfd, 0x73, 0x83, 0x86, 0x89, 0x4c, 0x81, 0xb8, 0x80,
|
||||
0xb3, 0xa7, 0xf8, 0x8b, 0x20, 0xac, 0xd9, 0x27, 0x6f, 0x9a, 0x4b, 0x2f,
|
||||
0x6a, 0xef, 0x84, 0x61, 0x75, 0x23, 0x18, 0xcd, 0x6f, 0x63, 0x80, 0x09,
|
||||
0x8a, 0xbc, 0x14, 0x1c, 0xe5, 0xff, 0xa9, 0x7d, 0x9a, 0x66, 0x20, 0x61,
|
||||
0x3c, 0x61, 0x4b, 0x3d, 0xd5, 0x39, 0xec, 0x3a, 0x16, 0x8d, 0x3b, 0xd1,
|
||||
0xf0, 0x1f, 0x8f, 0xae, 0xe2, 0xce, 0xc1, 0x94, 0x69, 0xae, 0xb8, 0xcd,
|
||||
0xba, 0x1c, 0x71, 0xe0, 0x47, 0x37, 0xa2, 0x1f, 0x5a, 0xdb, 0x37, 0xe1,
|
||||
0x59, 0x4c, 0x39, 0x46, 0xc1, 0xc0, 0x65, 0xc8, 0xd9, 0x61, 0xd3, 0x02,
|
||||
0x81, 0xc0, 0x2f, 0x63, 0xe7, 0xd0, 0xd7, 0xb9, 0x85, 0x65, 0xb6, 0x21,
|
||||
0x47, 0x0f, 0x17, 0x19, 0x4f, 0x8d, 0x7a, 0x56, 0xf7, 0xae, 0x0f, 0x97,
|
||||
0x05, 0x5f, 0xdb, 0x51, 0x17, 0x0f, 0xfd, 0x39, 0x88, 0x6e, 0x3a, 0x23,
|
||||
0x2a, 0x99, 0x47, 0x57, 0x3d, 0x56, 0xc7, 0xa4, 0xfd, 0x3d, 0x84, 0xa2,
|
||||
0xa1, 0x6b, 0xf6, 0x12, 0xd4, 0x2e, 0xb0, 0xca, 0xa1, 0xaf, 0x81, 0xcd,
|
||||
0x20, 0x0c, 0xf1, 0x7b, 0xf3, 0xdd, 0xc5, 0xa8, 0x10, 0xbb, 0xf6, 0xb3,
|
||||
0x99, 0x9e, 0xaf, 0x17, 0x97, 0xbd, 0x81, 0x05, 0x6e, 0xf5, 0xae, 0x36,
|
||||
0x4c, 0x0f, 0x4c, 0xcd, 0xf5, 0xcb, 0x0b, 0xb3, 0x96, 0xbd, 0x2d, 0xf8,
|
||||
0x99, 0x02, 0xe4, 0xb1, 0xbe, 0xde, 0x03, 0x38, 0xc3, 0x28, 0xe6, 0xb4,
|
||||
0x1f, 0x12, 0x30, 0x79, 0xd8, 0x84, 0xd8, 0x28, 0x8e, 0xc9, 0xf8, 0x3b,
|
||||
0xd3, 0x7f, 0xd4, 0x16, 0xd9, 0xea, 0xa1, 0xec, 0x7f, 0x05, 0x8a, 0xcb,
|
||||
0x2b, 0x06, 0x64, 0x4e, 0xc9, 0xcb, 0xc5, 0x6c, 0x4e, 0x92, 0xe8, 0xd2,
|
||||
0x5a, 0x33, 0x33, 0x33, 0x2b, 0x69, 0x6d, 0xe4, 0xbb, 0xe6, 0xa9, 0xf3,
|
||||
0x27, 0x9a, 0x95, 0xdd, 0x7e, 0x4c, 0x82, 0x71, 0xb8, 0x73, 0x12, 0x39,
|
||||
0x6d, 0xb9, 0xbb, 0xaa, 0xe0, 0x4f, 0xa6, 0xb0, 0x7e, 0xa2, 0xcd, 0x25,
|
||||
0xe4, 0x42, 0x45, 0x2f, 0x57, 0xa2, 0xf4, 0x7c, 0xf9, 0x18, 0x23, 0x16,
|
||||
0x2a, 0xe9, 0x02, 0x81, 0xc1, 0x00, 0xab, 0x35, 0x0d, 0x35, 0x94, 0x9d,
|
||||
0x96, 0xb2, 0xb7, 0x45, 0x16, 0xef, 0xb7, 0xea, 0xba, 0xa4, 0x32, 0xec,
|
||||
0x43, 0x05, 0xb0, 0x14, 0xbd, 0x9e, 0xd2, 0xbe, 0x0a, 0x0c, 0x4f, 0xca,
|
||||
0x4f, 0xf3, 0x11, 0xb3, 0x1f, 0xdc, 0x04, 0x18, 0x38, 0x9d, 0xb0, 0x09,
|
||||
0xb8, 0xf1, 0xcf, 0x7a, 0x89, 0x03, 0xd8, 0xed, 0x28, 0x30, 0xe8, 0xe6,
|
||||
0xbc, 0x7c, 0x1c, 0x59, 0x12, 0xf8, 0x95, 0x9b, 0x36, 0xad, 0xf2, 0xea,
|
||||
0x4a, 0x34, 0x00, 0xcf, 0x94, 0x3e, 0xeb, 0xff, 0xe2, 0x5b, 0x6c, 0x72,
|
||||
0xe3, 0x04, 0xd1, 0x10, 0x2e, 0xdd, 0x18, 0x8d, 0x9a, 0x84, 0x93, 0x55,
|
||||
0x4a, 0x80, 0x6c, 0xb5, 0x82, 0xc4, 0x16, 0x19, 0xc4, 0xba, 0xad, 0x2e,
|
||||
0x40, 0x76, 0xb3, 0xc9, 0xd4, 0x26, 0x5d, 0xc9, 0xb1, 0x05, 0x0f, 0x1f,
|
||||
0x7d, 0x59, 0x8c, 0x7b, 0xbe, 0x34, 0x09, 0x3e, 0x71, 0x0b, 0xc8, 0xf9,
|
||||
0xb3, 0x77, 0x4e, 0x4b, 0xfb, 0xbf, 0x81, 0x55, 0xa4, 0x5e, 0xc6, 0xe9,
|
||||
0xa1, 0xc3, 0x16, 0xff, 0xc8, 0x37, 0x88, 0xd5, 0x2d, 0xfb, 0x06, 0x98,
|
||||
0xe9, 0x82, 0x1b, 0x5e, 0x1e, 0xdd, 0x48, 0x5d, 0x6c, 0x59, 0xee, 0x7a,
|
||||
0xa6, 0xa4, 0x29, 0x41, 0x20, 0xb4, 0xcd, 0xf4, 0x58, 0x95, 0xfd, 0x7d,
|
||||
0xbf, 0xfc, 0x83, 0xf5, 0xe1, 0x5a, 0x5d, 0xa8, 0x08, 0x66, 0xd8, 0xa0,
|
||||
0x7f, 0xad, 0x7d, 0xcd, 0x22, 0x06
|
||||
};
|
||||
|
||||
// A 2048 bit RSA key in PKCS#8 PrivateKeyInfo format.
|
||||
// This is a different key from the one above.
|
||||
static const uint8_t kTestRSAPKCS8PrivateKeyInfo4_2048[] = {
|
||||
0x30, 0x82, 0x04, 0xbd, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
||||
0x04, 0xa7, 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
|
||||
0x01, 0x00, 0xc7, 0xfd, 0xa7, 0xca, 0x67, 0x15, 0xd1, 0x29, 0xea, 0xbc,
|
||||
0x42, 0x9b, 0x02, 0x37, 0xbb, 0xfb, 0xb4, 0x72, 0x86, 0x76, 0x05, 0x20,
|
||||
0x05, 0xcb, 0x94, 0x58, 0x79, 0x4a, 0x79, 0x68, 0xfe, 0xb4, 0x1d, 0x27,
|
||||
0x87, 0x97, 0x22, 0xeb, 0x13, 0xb2, 0xb6, 0xed, 0xda, 0xb3, 0xc0, 0x63,
|
||||
0x32, 0xd9, 0x31, 0x29, 0xb1, 0xb9, 0x97, 0x17, 0x67, 0x65, 0xd3, 0x9b,
|
||||
0x8d, 0xf2, 0x73, 0x1c, 0x70, 0x08, 0xe5, 0x64, 0x9f, 0xcf, 0x5b, 0x52,
|
||||
0x9e, 0x47, 0x51, 0xb0, 0xeb, 0x21, 0x81, 0xb4, 0x24, 0xc8, 0xd0, 0x42,
|
||||
0xf3, 0xd4, 0x77, 0x1e, 0x96, 0x12, 0x2f, 0x74, 0xab, 0x06, 0xb2, 0x2e,
|
||||
0xfa, 0xcd, 0x83, 0xcc, 0xbf, 0x02, 0x14, 0x34, 0x3c, 0x2c, 0x79, 0x7f,
|
||||
0x60, 0x60, 0xd0, 0x68, 0x7e, 0x70, 0x32, 0xd4, 0x34, 0x73, 0x0a, 0x42,
|
||||
0x7b, 0xbc, 0x69, 0xc0, 0xf8, 0xa6, 0xdc, 0x8f, 0x10, 0xda, 0x1c, 0xd4,
|
||||
0x9d, 0x59, 0x23, 0xb4, 0x05, 0x32, 0xac, 0xcc, 0x54, 0xff, 0x35, 0xb3,
|
||||
0x3f, 0x22, 0x1b, 0x8d, 0x9b, 0x6d, 0x76, 0xd7, 0xe5, 0xd1, 0xaa, 0x54,
|
||||
0x01, 0xd9, 0x53, 0x88, 0x40, 0xb4, 0x7a, 0x3c, 0x2b, 0x47, 0x09, 0xcc,
|
||||
0x50, 0xfa, 0x7a, 0x87, 0x56, 0x44, 0x28, 0x4b, 0x47, 0xc4, 0xee, 0x2e,
|
||||
0x2a, 0xaa, 0xe7, 0x7a, 0xd6, 0x7f, 0xd3, 0xc5, 0xf8, 0x70, 0x14, 0x97,
|
||||
0x64, 0x1c, 0x62, 0xdc, 0x42, 0xed, 0x90, 0x7d, 0x18, 0x36, 0xc2, 0xfa,
|
||||
0xd2, 0xdf, 0xd5, 0x23, 0x5c, 0x5a, 0xfb, 0x84, 0xe1, 0xe3, 0x5d, 0x3a,
|
||||
0x6a, 0x4e, 0x6a, 0x4b, 0xd9, 0x2d, 0xbd, 0xea, 0x88, 0x95, 0xc0, 0xb5,
|
||||
0xf2, 0xd3, 0x37, 0x1f, 0xfe, 0xc7, 0x0a, 0x62, 0x33, 0x5b, 0x98, 0x36,
|
||||
0x9d, 0x8d, 0x1a, 0x8e, 0x3a, 0xc5, 0x69, 0xe3, 0x2b, 0x95, 0x6e, 0xa6,
|
||||
0xf6, 0x00, 0xc0, 0x9d, 0xa7, 0x39, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
|
||||
0x82, 0x01, 0x00, 0x3e, 0x5b, 0x16, 0x80, 0x03, 0x58, 0x48, 0x19, 0x3b,
|
||||
0xb9, 0x6b, 0x43, 0x0d, 0x93, 0xf7, 0x26, 0xea, 0x02, 0x73, 0x6e, 0x44,
|
||||
0xf6, 0xd1, 0x17, 0xc2, 0xaf, 0x3b, 0x52, 0x3f, 0x3c, 0xbf, 0x7d, 0xc5,
|
||||
0x41, 0x58, 0x03, 0x85, 0xbd, 0xaa, 0x2c, 0xa4, 0xe0, 0xd0, 0xba, 0x0f,
|
||||
0x18, 0x5e, 0xf8, 0x5d, 0x5d, 0xd4, 0xae, 0x3b, 0x2f, 0xee, 0xeb, 0x4e,
|
||||
0xe9, 0x47, 0x7e, 0xfa, 0xe9, 0x38, 0xfd, 0x6d, 0x18, 0xcc, 0xc3, 0x48,
|
||||
0x84, 0x20, 0x19, 0xb8, 0x9c, 0xe3, 0x13, 0x55, 0x6f, 0xa7, 0xb0, 0x7d,
|
||||
0x4f, 0x02, 0xdb, 0x92, 0x30, 0x95, 0x36, 0x22, 0x59, 0xcc, 0x21, 0x90,
|
||||
0x59, 0x19, 0x96, 0x0e, 0xac, 0x3e, 0x3a, 0x15, 0xb6, 0x9b, 0xb4, 0x7a,
|
||||
0x45, 0x7e, 0xf5, 0x70, 0xc5, 0xc3, 0xf6, 0x93, 0xc2, 0x9a, 0x7f, 0xec,
|
||||
0x09, 0x02, 0xaf, 0xa2, 0x81, 0xaa, 0x85, 0xcc, 0x6b, 0x47, 0x23, 0x4d,
|
||||
0x65, 0x7e, 0xd7, 0xa9, 0x0c, 0x37, 0x48, 0x83, 0xc8, 0x40, 0x60, 0x88,
|
||||
0xfd, 0xeb, 0x31, 0xea, 0x65, 0xe3, 0xf6, 0xc5, 0x1d, 0x7b, 0xbd, 0xbc,
|
||||
0x4b, 0x60, 0x27, 0xcb, 0xf1, 0xe2, 0xd9, 0x09, 0x03, 0xf3, 0xfe, 0xd8,
|
||||
0x5c, 0xc1, 0x70, 0xdb, 0x0e, 0xdc, 0xc3, 0x7a, 0xb2, 0x41, 0x07, 0xf6,
|
||||
0x85, 0x26, 0x31, 0xed, 0xa3, 0x36, 0x80, 0x08, 0x4f, 0xf7, 0x02, 0x37,
|
||||
0x6e, 0x06, 0x9b, 0x1a, 0x76, 0x47, 0x62, 0x86, 0xdc, 0x33, 0xab, 0xcc,
|
||||
0x88, 0x77, 0x1c, 0x15, 0x43, 0xac, 0x72, 0x46, 0x73, 0x6e, 0x77, 0x28,
|
||||
0x82, 0x75, 0xa0, 0x2f, 0xd4, 0x96, 0x1b, 0x1e, 0x2e, 0x63, 0x66, 0x6c,
|
||||
0x75, 0x4f, 0xaa, 0xd0, 0x2c, 0xcc, 0xd3, 0x65, 0x85, 0xbe, 0x87, 0x6a,
|
||||
0x8e, 0x72, 0x65, 0x57, 0x64, 0xb5, 0x79, 0x71, 0x92, 0x7f, 0xe9, 0x80,
|
||||
0x08, 0xa3, 0xa3, 0x2d, 0xc0, 0x49, 0x89, 0x02, 0x81, 0x81, 0x00, 0xee,
|
||||
0x13, 0x86, 0xc3, 0x48, 0xb1, 0x4c, 0x7d, 0xe2, 0x31, 0x6c, 0x16, 0x37,
|
||||
0x72, 0x6f, 0x33, 0x9d, 0x17, 0xe4, 0x20, 0x91, 0xa3, 0x75, 0x42, 0x19,
|
||||
0xc1, 0xdb, 0x60, 0x90, 0x00, 0x4f, 0x04, 0x33, 0x88, 0xe1, 0xb8, 0x6f,
|
||||
0xdf, 0xde, 0x71, 0x34, 0xb1, 0xc8, 0x45, 0x16, 0x20, 0xac, 0x83, 0xd2,
|
||||
0xfe, 0x4c, 0x87, 0xb8, 0xdb, 0xfa, 0x42, 0x8e, 0xf5, 0x08, 0x03, 0x77,
|
||||
0xb3, 0x07, 0x17, 0xb2, 0x9b, 0xd1, 0x8c, 0xe8, 0xdc, 0x61, 0xb8, 0x82,
|
||||
0xf1, 0xe2, 0xa5, 0x46, 0xb1, 0xc1, 0x62, 0x1a, 0x9d, 0xf7, 0x44, 0x65,
|
||||
0xda, 0xe3, 0xa0, 0xe5, 0xd5, 0x30, 0xca, 0x28, 0x07, 0x2f, 0xd7, 0xba,
|
||||
0x99, 0x9f, 0x2a, 0x16, 0xc7, 0xe8, 0x98, 0x00, 0x7e, 0xd5, 0x53, 0x3c,
|
||||
0x29, 0x8a, 0x52, 0xd0, 0x93, 0xbe, 0xf7, 0xa9, 0x3a, 0x6e, 0x07, 0x28,
|
||||
0x44, 0x15, 0x6f, 0x20, 0x22, 0x52, 0xe3, 0x02, 0x81, 0x81, 0x00, 0xd7,
|
||||
0x0c, 0x1a, 0x8e, 0x0a, 0x11, 0x60, 0x12, 0xb0, 0x62, 0xfb, 0x71, 0x21,
|
||||
0xc0, 0x92, 0x65, 0x3d, 0xa4, 0x44, 0x1b, 0xbf, 0x17, 0x50, 0x45, 0xe6,
|
||||
0x19, 0x5f, 0x95, 0xda, 0x56, 0x12, 0x79, 0xc7, 0xcd, 0x8f, 0x07, 0x31,
|
||||
0x51, 0x93, 0xb7, 0x31, 0xd7, 0xc3, 0x09, 0x46, 0x8f, 0xfc, 0xd2, 0x1c,
|
||||
0xcd, 0x3c, 0xbc, 0x87, 0x54, 0x9d, 0xe8, 0xa4, 0xc1, 0xb6, 0xa4, 0x68,
|
||||
0x5e, 0xfd, 0x03, 0x78, 0xef, 0x69, 0xac, 0xd9, 0x0e, 0x00, 0x6f, 0x29,
|
||||
0xe8, 0x2b, 0x54, 0x62, 0x7f, 0x83, 0xe5, 0x5f, 0x9d, 0x83, 0xe2, 0x01,
|
||||
0x33, 0x33, 0x28, 0x39, 0x8f, 0x83, 0xaf, 0x6d, 0x60, 0xd5, 0x6f, 0xec,
|
||||
0xdb, 0x74, 0x5b, 0x87, 0x6e, 0x32, 0xe5, 0x51, 0x95, 0xbe, 0x08, 0xa5,
|
||||
0x8a, 0xf8, 0x92, 0x09, 0xe8, 0xae, 0xca, 0x95, 0x16, 0x44, 0x95, 0x84,
|
||||
0x52, 0xd8, 0x67, 0x1d, 0x31, 0x8c, 0x33, 0x02, 0x81, 0x81, 0x00, 0xe7,
|
||||
0x34, 0x05, 0x52, 0xce, 0xdc, 0x87, 0xf9, 0x54, 0x5a, 0x44, 0xaa, 0x8a,
|
||||
0xac, 0x52, 0x3b, 0xe0, 0x9a, 0x9c, 0x0b, 0xd9, 0x03, 0xd1, 0xd3, 0x20,
|
||||
0xaa, 0x77, 0xbe, 0x9d, 0xf9, 0xfe, 0xc2, 0x88, 0xbd, 0xac, 0xdf, 0x6d,
|
||||
0x9e, 0x0e, 0x2b, 0x08, 0x4e, 0x82, 0xbc, 0x3d, 0x11, 0xfc, 0x17, 0x85,
|
||||
0x27, 0x3a, 0xf1, 0x2f, 0x60, 0x49, 0xf8, 0xab, 0x56, 0x60, 0xb2, 0xe5,
|
||||
0x62, 0xf2, 0x47, 0x5c, 0x48, 0x20, 0x47, 0xe4, 0xb8, 0x69, 0x1a, 0x43,
|
||||
0xe8, 0x5d, 0xff, 0xbd, 0xd8, 0xd0, 0x81, 0xd2, 0x71, 0x87, 0xf9, 0x5f,
|
||||
0xa5, 0x24, 0x1c, 0x54, 0x37, 0x26, 0xcb, 0x9b, 0xf5, 0xe6, 0xcb, 0x6d,
|
||||
0x46, 0xd5, 0x20, 0x8d, 0xc1, 0x14, 0x2b, 0xd1, 0x87, 0x5a, 0xea, 0x1b,
|
||||
0x6a, 0x08, 0x10, 0x06, 0xc9, 0x04, 0xd3, 0x05, 0x00, 0x5e, 0x6c, 0x0a,
|
||||
0xf9, 0x9b, 0x8b, 0x30, 0xbc, 0xc4, 0x9b, 0x02, 0x81, 0x80, 0x20, 0x16,
|
||||
0x83, 0x43, 0xdc, 0x86, 0xb9, 0x32, 0x30, 0xb5, 0xa4, 0x55, 0x3e, 0x37,
|
||||
0x10, 0xe1, 0x20, 0x70, 0x89, 0x65, 0x26, 0x7f, 0x61, 0x0f, 0xfd, 0x04,
|
||||
0x9e, 0x39, 0xab, 0x09, 0x9a, 0xda, 0x27, 0x11, 0x2a, 0x1d, 0x65, 0xa3,
|
||||
0x89, 0x8a, 0x15, 0x5a, 0xdf, 0x94, 0x5b, 0xbe, 0x12, 0x78, 0x7b, 0xa9,
|
||||
0xb8, 0x3d, 0x5d, 0x68, 0x27, 0xe3, 0xd5, 0xe9, 0xbd, 0xca, 0x0c, 0x74,
|
||||
0xd8, 0x06, 0x13, 0x9e, 0x8d, 0xc3, 0x27, 0xe4, 0x29, 0xf6, 0x6c, 0x67,
|
||||
0x63, 0x47, 0xc5, 0x26, 0xc7, 0xd4, 0x8b, 0x0e, 0xe2, 0xe5, 0xef, 0x4d,
|
||||
0xe7, 0x7d, 0x42, 0x11, 0x83, 0x11, 0xc3, 0x1d, 0x66, 0xdb, 0xbb, 0x99,
|
||||
0x07, 0x64, 0xbc, 0xf1, 0x99, 0x90, 0x94, 0x3a, 0xe6, 0xcf, 0x3d, 0x7c,
|
||||
0x5e, 0x18, 0xd4, 0x77, 0xae, 0xd5, 0x35, 0xa7, 0xcb, 0xf6, 0x0f, 0x77,
|
||||
0x99, 0x28, 0xd1, 0xb7, 0x59, 0xf7, 0x02, 0x81, 0x80, 0x43, 0x4d, 0xf6,
|
||||
0xfe, 0x87, 0x20, 0xfb, 0x31, 0xc4, 0x00, 0x83, 0xa2, 0x66, 0x63, 0xa9,
|
||||
0xed, 0x4c, 0xff, 0x79, 0xd3, 0xdc, 0x5d, 0x9d, 0xad, 0xa2, 0x03, 0x66,
|
||||
0x1b, 0x97, 0xe0, 0x44, 0xd0, 0xc0, 0x5e, 0xf4, 0x5d, 0xe4, 0xc9, 0x2a,
|
||||
0xa0, 0x6e, 0x1d, 0x2e, 0xb0, 0x23, 0xf4, 0x7b, 0x1c, 0xaa, 0x5d, 0x86,
|
||||
0xb9, 0xf1, 0x93, 0xf8, 0x32, 0x09, 0x74, 0x53, 0xfe, 0x90, 0x24, 0xfc,
|
||||
0x35, 0x1e, 0x7a, 0x0e, 0x4a, 0x3b, 0x1e, 0x58, 0x49, 0x3e, 0x7e, 0xc8,
|
||||
0x8a, 0xb1, 0x1c, 0xb0, 0xe1, 0x35, 0x1b, 0x9e, 0xc5, 0x59, 0x7c, 0x32,
|
||||
0x3a, 0xab, 0x24, 0x5a, 0xb7, 0x70, 0x27, 0xf9, 0x62, 0x4b, 0x89, 0x35,
|
||||
0x20, 0x0d, 0x10, 0xea, 0x76, 0x24, 0x91, 0xe6, 0x64, 0x02, 0xbc, 0xba,
|
||||
0xf7, 0x59, 0x16, 0xc7, 0x41, 0xc0, 0xb7, 0xa4, 0x6d, 0xa4, 0xb9, 0xe6,
|
||||
0x61, 0x66, 0x42, 0xbf, 0xf0};
|
||||
|
||||
// This is an RSA key where e*d != 1 mod phi. Instead, it uses the carmicahel
|
||||
// totient. That means e*d = 1 mod lambda, where lambda = lcm(p-1, q-1).
|
||||
static const uint8_t kTestKeyRSACarmichael_2048[] = {
|
||||
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
||||
0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
|
||||
0x01, 0x00, 0xa7, 0x00, 0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a,
|
||||
0x40, 0xb4, 0xe1, 0x15, 0x94, 0x58, 0x11, 0x4f, 0x94, 0x58, 0xdd, 0xde,
|
||||
0xa7, 0x1f, 0x3c, 0x2c, 0xe0, 0x88, 0x09, 0x29, 0x61, 0x57, 0x67, 0x5e,
|
||||
0x56, 0x7e, 0xee, 0x27, 0x8f, 0x59, 0x34, 0x9a, 0x2a, 0xaa, 0x9d, 0xb4,
|
||||
0x4e, 0xfa, 0xa7, 0x6a, 0xd4, 0xc9, 0x7a, 0x53, 0xc1, 0x4e, 0x9f, 0xe3,
|
||||
0x34, 0xf7, 0x3d, 0xb7, 0xc9, 0x10, 0x47, 0x4f, 0x28, 0xda, 0x3f, 0xce,
|
||||
0x31, 0x7b, 0xfd, 0x06, 0x10, 0xeb, 0xf7, 0xbe, 0x92, 0xf9, 0xaf, 0xfb,
|
||||
0x3e, 0x68, 0xda, 0xee, 0x1a, 0x64, 0x4c, 0xf3, 0x29, 0xf2, 0x73, 0x9e,
|
||||
0x39, 0xd8, 0xf6, 0x6f, 0xd8, 0xb2, 0x80, 0x82, 0x71, 0x8e, 0xb5, 0xa4,
|
||||
0xf2, 0xc2, 0x3e, 0xcd, 0x0a, 0xca, 0xb6, 0x04, 0xcd, 0x9a, 0x13, 0x8b,
|
||||
0x54, 0x73, 0x54, 0x25, 0x54, 0x8c, 0xbe, 0x98, 0x7a, 0x67, 0xad, 0xda,
|
||||
0xb3, 0x4e, 0xb3, 0xfa, 0x82, 0xa8, 0x4a, 0x67, 0x98, 0x56, 0x57, 0x54,
|
||||
0x71, 0xcd, 0x12, 0x7f, 0xed, 0xa3, 0x01, 0xc0, 0x6a, 0x8b, 0x24, 0x03,
|
||||
0x96, 0x88, 0xbe, 0x97, 0x66, 0x2a, 0xbc, 0x53, 0xc9, 0x83, 0x06, 0x51,
|
||||
0x5a, 0x88, 0x65, 0x13, 0x18, 0xe4, 0x3a, 0xed, 0x6b, 0xf1, 0x61, 0x5b,
|
||||
0x4c, 0xc8, 0x1e, 0xf4, 0xc2, 0xae, 0x08, 0x5e, 0x2d, 0x5f, 0xf8, 0x12,
|
||||
0x7f, 0xa2, 0xfc, 0xbb, 0x21, 0x18, 0x30, 0xda, 0xfe, 0x40, 0xfb, 0x01,
|
||||
0xca, 0x2e, 0x37, 0x0e, 0xce, 0xdd, 0x76, 0x87, 0x82, 0x46, 0x0b, 0x3a,
|
||||
0x77, 0x8f, 0xc0, 0x72, 0x07, 0x2c, 0x7f, 0x9d, 0x1e, 0x86, 0x5b, 0xed,
|
||||
0x27, 0x29, 0xdf, 0x03, 0x97, 0x62, 0xef, 0x44, 0xd3, 0x5b, 0x3d, 0xdb,
|
||||
0x9c, 0x5e, 0x1b, 0x7b, 0x39, 0xb4, 0x0b, 0x6d, 0x04, 0x6b, 0xbb, 0xbb,
|
||||
0x2c, 0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
|
||||
0x82, 0x01, 0x00, 0x0a, 0xf9, 0x4a, 0x19, 0x72, 0x88, 0x1b, 0x4e, 0xd8,
|
||||
0x2f, 0xef, 0x99, 0x93, 0x32, 0xda, 0x51, 0x21, 0x2e, 0x14, 0x06, 0xf4,
|
||||
0xe9, 0x65, 0x1c, 0xf9, 0xd4, 0xcf, 0x1a, 0x51, 0x53, 0xcd, 0x48, 0x33,
|
||||
0x8c, 0x30, 0xed, 0xdd, 0x53, 0x6f, 0x29, 0x82, 0xf9, 0xe0, 0x74, 0xde,
|
||||
0xb1, 0x13, 0x01, 0x88, 0x8f, 0xce, 0x14, 0xc1, 0x3b, 0x90, 0xb7, 0xcc,
|
||||
0x6c, 0xdf, 0x35, 0xa1, 0xf2, 0x1a, 0x3d, 0xbe, 0x19, 0xd7, 0x0a, 0xe4,
|
||||
0x67, 0x75, 0xbb, 0xfa, 0x87, 0xf4, 0x03, 0xb5, 0x7f, 0x69, 0xe4, 0x0b,
|
||||
0x6a, 0xdc, 0x92, 0x82, 0x54, 0x64, 0x1a, 0x94, 0x2d, 0xe4, 0x63, 0x40,
|
||||
0xb2, 0xb4, 0x85, 0x6b, 0xc8, 0x34, 0xba, 0xa2, 0x14, 0x30, 0x47, 0x1a,
|
||||
0xeb, 0x90, 0x62, 0x30, 0x43, 0x44, 0x02, 0xc7, 0x0c, 0x30, 0xc0, 0x7f,
|
||||
0xa9, 0x47, 0xae, 0xde, 0x68, 0x27, 0x92, 0xaa, 0x11, 0x95, 0xf5, 0x6f,
|
||||
0xfc, 0x19, 0x8b, 0x49, 0xa0, 0x77, 0x9d, 0xc6, 0x13, 0x5d, 0x73, 0xff,
|
||||
0x45, 0xa2, 0x4c, 0x3b, 0xf3, 0xe1, 0x2d, 0xd7, 0xc4, 0x70, 0xe2, 0x6c,
|
||||
0x37, 0x99, 0x4c, 0x7a, 0xa9, 0x27, 0xf8, 0x3a, 0xd6, 0xfd, 0xc5, 0xd8,
|
||||
0xfa, 0x2d, 0x0e, 0x71, 0x4b, 0x85, 0x7e, 0xce, 0xcb, 0x1c, 0x79, 0x71,
|
||||
0xbd, 0xff, 0x63, 0x03, 0x6b, 0x58, 0x68, 0xe0, 0x14, 0xca, 0x5e, 0x85,
|
||||
0xfd, 0xd0, 0xb7, 0xe0, 0x68, 0x14, 0xff, 0x2c, 0x82, 0x22, 0x26, 0x8a,
|
||||
0x3f, 0xbf, 0xb0, 0x2a, 0x90, 0xff, 0xc7, 0x72, 0xfc, 0x66, 0x51, 0x3e,
|
||||
0x51, 0x9f, 0x82, 0x68, 0x0e, 0xf3, 0x65, 0x74, 0x88, 0xab, 0xb7, 0xe5,
|
||||
0x97, 0x5f, 0x0f, 0x3e, 0xe5, 0x3a, 0xbc, 0xa4, 0xa1, 0x50, 0xdd, 0x5c,
|
||||
0x94, 0x4b, 0x0c, 0x70, 0x71, 0x48, 0x4e, 0xd0, 0xec, 0x46, 0x8f, 0xdf,
|
||||
0xa2, 0x9a, 0xfe, 0xd8, 0x35, 0x1a, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xcf,
|
||||
0x73, 0x8c, 0xbe, 0x6d, 0x45, 0x2d, 0x0c, 0x0b, 0x5d, 0x5c, 0x6c, 0x75,
|
||||
0x78, 0xcc, 0x35, 0x48, 0xb6, 0x98, 0xf1, 0xb9, 0x64, 0x60, 0x8c, 0x43,
|
||||
0xeb, 0x85, 0xab, 0x04, 0xb6, 0x7d, 0x1b, 0x71, 0x75, 0x06, 0xe2, 0xda,
|
||||
0x84, 0x68, 0x2e, 0x7f, 0x4c, 0xe3, 0x73, 0xb4, 0xde, 0x51, 0x4b, 0xb6,
|
||||
0x51, 0x86, 0x7b, 0xd0, 0xe6, 0x4d, 0xf3, 0xd1, 0xcf, 0x1a, 0xfe, 0x7f,
|
||||
0x3a, 0x83, 0xba, 0xb3, 0xe1, 0xff, 0x54, 0x13, 0x93, 0xd7, 0x9c, 0x27,
|
||||
0x80, 0xb7, 0x1e, 0x64, 0x9e, 0xf7, 0x32, 0x2b, 0x46, 0x29, 0xf7, 0xf8,
|
||||
0x18, 0x6c, 0xf7, 0x4a, 0xbe, 0x4b, 0xee, 0x96, 0x90, 0x8f, 0xa2, 0x16,
|
||||
0x22, 0x6a, 0xcc, 0x48, 0x06, 0x74, 0x63, 0x43, 0x7f, 0x27, 0x22, 0x44,
|
||||
0x3c, 0x2d, 0x3b, 0x62, 0xf1, 0x1c, 0xb4, 0x27, 0x33, 0x85, 0x26, 0x60,
|
||||
0x48, 0x16, 0xcb, 0xef, 0xf8, 0xcd, 0x37, 0x02, 0x81, 0x81, 0x00, 0xce,
|
||||
0x15, 0x43, 0x6e, 0x4b, 0x0f, 0xf9, 0x3f, 0x87, 0xc3, 0x41, 0x45, 0x97,
|
||||
0xb1, 0x49, 0xc2, 0x19, 0x23, 0x87, 0xe4, 0x24, 0x1c, 0x64, 0xe5, 0x28,
|
||||
0xcb, 0x43, 0x10, 0x14, 0x14, 0x0e, 0x19, 0xcb, 0xbb, 0xdb, 0xfd, 0x11,
|
||||
0x9d, 0x17, 0x68, 0x78, 0x6d, 0x61, 0x70, 0x63, 0x3a, 0xa1, 0xb3, 0xf3,
|
||||
0xa7, 0x5b, 0x0e, 0xff, 0xb7, 0x61, 0x11, 0x54, 0x91, 0x99, 0xe5, 0x91,
|
||||
0x32, 0x2d, 0xeb, 0x3f, 0xd8, 0x3e, 0xf7, 0xd4, 0xcb, 0xd2, 0xa3, 0x41,
|
||||
0xc1, 0xee, 0xc6, 0x92, 0x13, 0xeb, 0x7f, 0x42, 0x58, 0xf4, 0xd0, 0xb2,
|
||||
0x74, 0x1d, 0x8e, 0x87, 0x46, 0xcd, 0x14, 0xb8, 0x16, 0xad, 0xb5, 0xbd,
|
||||
0x0d, 0x6c, 0x95, 0x5a, 0x16, 0xbf, 0xe9, 0x53, 0xda, 0xfb, 0xed, 0x83,
|
||||
0x51, 0x67, 0xa9, 0x55, 0xab, 0x54, 0x02, 0x95, 0x20, 0xa6, 0x68, 0x17,
|
||||
0x53, 0xa8, 0xea, 0x43, 0xe5, 0xb0, 0xa3, 0x02, 0x81, 0x80, 0x67, 0x9c,
|
||||
0x32, 0x83, 0x39, 0x57, 0xff, 0x73, 0xb0, 0x89, 0x64, 0x8b, 0xd6, 0xf0,
|
||||
0x0a, 0x2d, 0xe2, 0xaf, 0x30, 0x1c, 0x2a, 0x97, 0xf3, 0x90, 0x9a, 0xab,
|
||||
0x9b, 0x0b, 0x1b, 0x43, 0x79, 0xa0, 0xa7, 0x3d, 0xe7, 0xbe, 0x8d, 0x9c,
|
||||
0xeb, 0xdb, 0xad, 0x40, 0xdd, 0xa9, 0x00, 0x80, 0xb8, 0xe1, 0xb3, 0xa1,
|
||||
0x6c, 0x25, 0x92, 0xe4, 0x33, 0xb2, 0xbe, 0xeb, 0x4d, 0x74, 0x26, 0x5f,
|
||||
0x37, 0x43, 0x9c, 0x6c, 0x17, 0x76, 0x0a, 0x81, 0x20, 0x82, 0xa1, 0x48,
|
||||
0x2c, 0x2d, 0x45, 0xdc, 0x0f, 0x62, 0x43, 0x32, 0xbb, 0xeb, 0x59, 0x41,
|
||||
0xf9, 0xca, 0x58, 0xce, 0x4a, 0x66, 0x53, 0x54, 0xc8, 0x28, 0x10, 0x1e,
|
||||
0x08, 0x71, 0x16, 0xd8, 0x02, 0x71, 0x41, 0x58, 0xd4, 0x56, 0xcc, 0xf5,
|
||||
0xb1, 0x31, 0xa3, 0xed, 0x00, 0x85, 0x09, 0xbf, 0x35, 0x95, 0x41, 0x29,
|
||||
0x40, 0x19, 0x83, 0x35, 0x24, 0x69, 0x02, 0x81, 0x80, 0x55, 0x10, 0x0b,
|
||||
0xcc, 0x3b, 0xa9, 0x75, 0x3d, 0x16, 0xe1, 0xae, 0x50, 0x76, 0x63, 0x94,
|
||||
0x49, 0x4c, 0xad, 0x10, 0xcb, 0x47, 0x68, 0x7c, 0xf0, 0xe5, 0xdc, 0xb8,
|
||||
0x6a, 0xab, 0x8e, 0xf7, 0x9f, 0x08, 0x2c, 0x1b, 0x8a, 0xa2, 0xb9, 0x8f,
|
||||
0xce, 0xec, 0x5e, 0x61, 0xa8, 0xcd, 0x1c, 0x87, 0x60, 0x4a, 0xc3, 0x1a,
|
||||
0x5f, 0xdf, 0x87, 0x26, 0xc6, 0xcb, 0x7c, 0x69, 0xe4, 0x8b, 0x01, 0x06,
|
||||
0x59, 0x22, 0xfa, 0x34, 0x4b, 0x81, 0x87, 0x3c, 0x03, 0x6d, 0x02, 0x0a,
|
||||
0x77, 0xe6, 0x15, 0xd8, 0xcf, 0xa7, 0x68, 0x26, 0x6c, 0xfa, 0x2b, 0xd9,
|
||||
0x83, 0x5a, 0x2d, 0x0c, 0x3b, 0x70, 0x1c, 0xd4, 0x48, 0xbe, 0xa7, 0x0a,
|
||||
0xd9, 0xbe, 0xdc, 0xc3, 0x0c, 0x21, 0x33, 0xb3, 0x66, 0xff, 0x1c, 0x1b,
|
||||
0xc8, 0x96, 0x76, 0xe8, 0x6f, 0x44, 0x74, 0xbc, 0x9b, 0x1c, 0x7d, 0xc8,
|
||||
0xac, 0x21, 0xa8, 0x6e, 0x37, 0x02, 0x81, 0x80, 0x2c, 0x7c, 0xad, 0x1e,
|
||||
0x75, 0xf6, 0x69, 0x1d, 0xe7, 0xa6, 0xca, 0x74, 0x7d, 0x67, 0xc8, 0x65,
|
||||
0x28, 0x66, 0xc4, 0x43, 0xa6, 0xbd, 0x40, 0x57, 0xae, 0xb7, 0x65, 0x2c,
|
||||
0x52, 0xf9, 0xe4, 0xc7, 0x81, 0x7b, 0x56, 0xa3, 0xd2, 0x0d, 0xe8, 0x33,
|
||||
0x70, 0xcf, 0x06, 0x84, 0xb3, 0x4e, 0x44, 0x50, 0x75, 0x61, 0x96, 0x86,
|
||||
0x4b, 0xb6, 0x2b, 0xad, 0xf0, 0xad, 0x57, 0xd0, 0x37, 0x0d, 0x1d, 0x35,
|
||||
0x50, 0xcb, 0x69, 0x22, 0x39, 0x29, 0xb9, 0x3a, 0xd3, 0x29, 0x23, 0x02,
|
||||
0x60, 0xf7, 0xab, 0x30, 0x40, 0xda, 0x8e, 0x4d, 0x45, 0x70, 0x26, 0xf4,
|
||||
0xa2, 0x0d, 0xd0, 0x64, 0x5d, 0x47, 0x3c, 0x18, 0xf4, 0xd4, 0x52, 0x95,
|
||||
0x00, 0xae, 0x84, 0x6b, 0x47, 0xb2, 0x3c, 0x82, 0xd3, 0x72, 0x53, 0xde,
|
||||
0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18, 0x56, 0xfe, 0x39, 0x28,
|
||||
0x33, 0xe0, 0xdb, 0x03,
|
||||
};
|
||||
|
||||
// This is the same key as above, except the private key was chosen using the
|
||||
// Euler totient.
|
||||
static const uint8_t kTestKeyRSAEuler_2048[] = {
|
||||
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
||||
0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
|
||||
0x01, 0x00, 0xa7, 0x00, 0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a,
|
||||
0x40, 0xb4, 0xe1, 0x15, 0x94, 0x58, 0x11, 0x4f, 0x94, 0x58, 0xdd, 0xde,
|
||||
0xa7, 0x1f, 0x3c, 0x2c, 0xe0, 0x88, 0x09, 0x29, 0x61, 0x57, 0x67, 0x5e,
|
||||
0x56, 0x7e, 0xee, 0x27, 0x8f, 0x59, 0x34, 0x9a, 0x2a, 0xaa, 0x9d, 0xb4,
|
||||
0x4e, 0xfa, 0xa7, 0x6a, 0xd4, 0xc9, 0x7a, 0x53, 0xc1, 0x4e, 0x9f, 0xe3,
|
||||
0x34, 0xf7, 0x3d, 0xb7, 0xc9, 0x10, 0x47, 0x4f, 0x28, 0xda, 0x3f, 0xce,
|
||||
0x31, 0x7b, 0xfd, 0x06, 0x10, 0xeb, 0xf7, 0xbe, 0x92, 0xf9, 0xaf, 0xfb,
|
||||
0x3e, 0x68, 0xda, 0xee, 0x1a, 0x64, 0x4c, 0xf3, 0x29, 0xf2, 0x73, 0x9e,
|
||||
0x39, 0xd8, 0xf6, 0x6f, 0xd8, 0xb2, 0x80, 0x82, 0x71, 0x8e, 0xb5, 0xa4,
|
||||
0xf2, 0xc2, 0x3e, 0xcd, 0x0a, 0xca, 0xb6, 0x04, 0xcd, 0x9a, 0x13, 0x8b,
|
||||
0x54, 0x73, 0x54, 0x25, 0x54, 0x8c, 0xbe, 0x98, 0x7a, 0x67, 0xad, 0xda,
|
||||
0xb3, 0x4e, 0xb3, 0xfa, 0x82, 0xa8, 0x4a, 0x67, 0x98, 0x56, 0x57, 0x54,
|
||||
0x71, 0xcd, 0x12, 0x7f, 0xed, 0xa3, 0x01, 0xc0, 0x6a, 0x8b, 0x24, 0x03,
|
||||
0x96, 0x88, 0xbe, 0x97, 0x66, 0x2a, 0xbc, 0x53, 0xc9, 0x83, 0x06, 0x51,
|
||||
0x5a, 0x88, 0x65, 0x13, 0x18, 0xe4, 0x3a, 0xed, 0x6b, 0xf1, 0x61, 0x5b,
|
||||
0x4c, 0xc8, 0x1e, 0xf4, 0xc2, 0xae, 0x08, 0x5e, 0x2d, 0x5f, 0xf8, 0x12,
|
||||
0x7f, 0xa2, 0xfc, 0xbb, 0x21, 0x18, 0x30, 0xda, 0xfe, 0x40, 0xfb, 0x01,
|
||||
0xca, 0x2e, 0x37, 0x0e, 0xce, 0xdd, 0x76, 0x87, 0x82, 0x46, 0x0b, 0x3a,
|
||||
0x77, 0x8f, 0xc0, 0x72, 0x07, 0x2c, 0x7f, 0x9d, 0x1e, 0x86, 0x5b, 0xed,
|
||||
0x27, 0x29, 0xdf, 0x03, 0x97, 0x62, 0xef, 0x44, 0xd3, 0x5b, 0x3d, 0xdb,
|
||||
0x9c, 0x5e, 0x1b, 0x7b, 0x39, 0xb4, 0x0b, 0x6d, 0x04, 0x6b, 0xbb, 0xbb,
|
||||
0x2c, 0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
|
||||
0x82, 0x01, 0x00, 0x5e, 0x79, 0x65, 0x49, 0xa5, 0x76, 0x79, 0xf9, 0x05,
|
||||
0x45, 0x0f, 0xf4, 0x03, 0xbd, 0xa4, 0x7d, 0x29, 0xd5, 0xde, 0x33, 0x63,
|
||||
0xd8, 0xb8, 0xac, 0x97, 0xeb, 0x3f, 0x5e, 0x55, 0xe8, 0x7d, 0xf3, 0xe7,
|
||||
0x3b, 0x5c, 0x2d, 0x54, 0x67, 0x36, 0xd6, 0x1d, 0x46, 0xf5, 0xca, 0x2d,
|
||||
0x8b, 0x3a, 0x7e, 0xdc, 0x45, 0x38, 0x79, 0x7e, 0x65, 0x71, 0x5f, 0x1c,
|
||||
0x5e, 0x79, 0xb1, 0x40, 0xcd, 0xfe, 0xc5, 0xe1, 0xc1, 0x6b, 0x78, 0x04,
|
||||
0x4e, 0x8e, 0x79, 0xf9, 0x0a, 0xfc, 0x79, 0xb1, 0x5e, 0xb3, 0x60, 0xe3,
|
||||
0x68, 0x7b, 0xc6, 0xef, 0xcb, 0x71, 0x4c, 0xba, 0xa7, 0x79, 0x5c, 0x7a,
|
||||
0x81, 0xd1, 0x71, 0xe7, 0x00, 0x21, 0x13, 0xe2, 0x55, 0x69, 0x0e, 0x75,
|
||||
0xbe, 0x09, 0xc3, 0x4f, 0xa9, 0xc9, 0x68, 0x22, 0x0e, 0x97, 0x8d, 0x89,
|
||||
0x6e, 0xf1, 0xe8, 0x88, 0x7a, 0xd1, 0xd9, 0x09, 0x5d, 0xd3, 0x28, 0x78,
|
||||
0x25, 0x0b, 0x1c, 0x47, 0x73, 0x25, 0xcc, 0x21, 0xb6, 0xda, 0xc6, 0x24,
|
||||
0x5a, 0xd0, 0x37, 0x14, 0x46, 0xc7, 0x94, 0x69, 0xe4, 0x43, 0x6f, 0x47,
|
||||
0xde, 0x00, 0x33, 0x4d, 0x8f, 0x95, 0x72, 0xfa, 0x68, 0x71, 0x17, 0x66,
|
||||
0x12, 0x1a, 0x87, 0x27, 0xf7, 0xef, 0x7e, 0xe0, 0x35, 0x58, 0xf2, 0x4d,
|
||||
0x6f, 0x35, 0x01, 0xaa, 0x96, 0xe2, 0x3d, 0x51, 0x13, 0x86, 0x9c, 0x79,
|
||||
0xd0, 0xb7, 0xb6, 0x64, 0xe8, 0x86, 0x65, 0x50, 0xbf, 0xcc, 0x27, 0x53,
|
||||
0x1f, 0x51, 0xd4, 0xca, 0xbe, 0xf5, 0xdd, 0x77, 0x70, 0x98, 0x0f, 0xee,
|
||||
0xa8, 0x96, 0x07, 0x5f, 0x45, 0x6a, 0x7a, 0x0d, 0x03, 0x9c, 0x4f, 0x29,
|
||||
0xf6, 0x06, 0xf3, 0x5d, 0x58, 0x6c, 0x47, 0xd0, 0x96, 0xa9, 0x03, 0x17,
|
||||
0xbb, 0x4e, 0xc9, 0x21, 0xe0, 0xac, 0xcd, 0x78, 0x78, 0xb2, 0xfe, 0x81,
|
||||
0xb2, 0x51, 0x53, 0xa6, 0x1f, 0x98, 0x45, 0x02, 0x81, 0x81, 0x00, 0xcf,
|
||||
0x73, 0x8c, 0xbe, 0x6d, 0x45, 0x2d, 0x0c, 0x0b, 0x5d, 0x5c, 0x6c, 0x75,
|
||||
0x78, 0xcc, 0x35, 0x48, 0xb6, 0x98, 0xf1, 0xb9, 0x64, 0x60, 0x8c, 0x43,
|
||||
0xeb, 0x85, 0xab, 0x04, 0xb6, 0x7d, 0x1b, 0x71, 0x75, 0x06, 0xe2, 0xda,
|
||||
0x84, 0x68, 0x2e, 0x7f, 0x4c, 0xe3, 0x73, 0xb4, 0xde, 0x51, 0x4b, 0xb6,
|
||||
0x51, 0x86, 0x7b, 0xd0, 0xe6, 0x4d, 0xf3, 0xd1, 0xcf, 0x1a, 0xfe, 0x7f,
|
||||
0x3a, 0x83, 0xba, 0xb3, 0xe1, 0xff, 0x54, 0x13, 0x93, 0xd7, 0x9c, 0x27,
|
||||
0x80, 0xb7, 0x1e, 0x64, 0x9e, 0xf7, 0x32, 0x2b, 0x46, 0x29, 0xf7, 0xf8,
|
||||
0x18, 0x6c, 0xf7, 0x4a, 0xbe, 0x4b, 0xee, 0x96, 0x90, 0x8f, 0xa2, 0x16,
|
||||
0x22, 0x6a, 0xcc, 0x48, 0x06, 0x74, 0x63, 0x43, 0x7f, 0x27, 0x22, 0x44,
|
||||
0x3c, 0x2d, 0x3b, 0x62, 0xf1, 0x1c, 0xb4, 0x27, 0x33, 0x85, 0x26, 0x60,
|
||||
0x48, 0x16, 0xcb, 0xef, 0xf8, 0xcd, 0x37, 0x02, 0x81, 0x81, 0x00, 0xce,
|
||||
0x15, 0x43, 0x6e, 0x4b, 0x0f, 0xf9, 0x3f, 0x87, 0xc3, 0x41, 0x45, 0x97,
|
||||
0xb1, 0x49, 0xc2, 0x19, 0x23, 0x87, 0xe4, 0x24, 0x1c, 0x64, 0xe5, 0x28,
|
||||
0xcb, 0x43, 0x10, 0x14, 0x14, 0x0e, 0x19, 0xcb, 0xbb, 0xdb, 0xfd, 0x11,
|
||||
0x9d, 0x17, 0x68, 0x78, 0x6d, 0x61, 0x70, 0x63, 0x3a, 0xa1, 0xb3, 0xf3,
|
||||
0xa7, 0x5b, 0x0e, 0xff, 0xb7, 0x61, 0x11, 0x54, 0x91, 0x99, 0xe5, 0x91,
|
||||
0x32, 0x2d, 0xeb, 0x3f, 0xd8, 0x3e, 0xf7, 0xd4, 0xcb, 0xd2, 0xa3, 0x41,
|
||||
0xc1, 0xee, 0xc6, 0x92, 0x13, 0xeb, 0x7f, 0x42, 0x58, 0xf4, 0xd0, 0xb2,
|
||||
0x74, 0x1d, 0x8e, 0x87, 0x46, 0xcd, 0x14, 0xb8, 0x16, 0xad, 0xb5, 0xbd,
|
||||
0x0d, 0x6c, 0x95, 0x5a, 0x16, 0xbf, 0xe9, 0x53, 0xda, 0xfb, 0xed, 0x83,
|
||||
0x51, 0x67, 0xa9, 0x55, 0xab, 0x54, 0x02, 0x95, 0x20, 0xa6, 0x68, 0x17,
|
||||
0x53, 0xa8, 0xea, 0x43, 0xe5, 0xb0, 0xa3, 0x02, 0x81, 0x80, 0x67, 0x9c,
|
||||
0x32, 0x83, 0x39, 0x57, 0xff, 0x73, 0xb0, 0x89, 0x64, 0x8b, 0xd6, 0xf0,
|
||||
0x0a, 0x2d, 0xe2, 0xaf, 0x30, 0x1c, 0x2a, 0x97, 0xf3, 0x90, 0x9a, 0xab,
|
||||
0x9b, 0x0b, 0x1b, 0x43, 0x79, 0xa0, 0xa7, 0x3d, 0xe7, 0xbe, 0x8d, 0x9c,
|
||||
0xeb, 0xdb, 0xad, 0x40, 0xdd, 0xa9, 0x00, 0x80, 0xb8, 0xe1, 0xb3, 0xa1,
|
||||
0x6c, 0x25, 0x92, 0xe4, 0x33, 0xb2, 0xbe, 0xeb, 0x4d, 0x74, 0x26, 0x5f,
|
||||
0x37, 0x43, 0x9c, 0x6c, 0x17, 0x76, 0x0a, 0x81, 0x20, 0x82, 0xa1, 0x48,
|
||||
0x2c, 0x2d, 0x45, 0xdc, 0x0f, 0x62, 0x43, 0x32, 0xbb, 0xeb, 0x59, 0x41,
|
||||
0xf9, 0xca, 0x58, 0xce, 0x4a, 0x66, 0x53, 0x54, 0xc8, 0x28, 0x10, 0x1e,
|
||||
0x08, 0x71, 0x16, 0xd8, 0x02, 0x71, 0x41, 0x58, 0xd4, 0x56, 0xcc, 0xf5,
|
||||
0xb1, 0x31, 0xa3, 0xed, 0x00, 0x85, 0x09, 0xbf, 0x35, 0x95, 0x41, 0x29,
|
||||
0x40, 0x19, 0x83, 0x35, 0x24, 0x69, 0x02, 0x81, 0x80, 0x55, 0x10, 0x0b,
|
||||
0xcc, 0x3b, 0xa9, 0x75, 0x3d, 0x16, 0xe1, 0xae, 0x50, 0x76, 0x63, 0x94,
|
||||
0x49, 0x4c, 0xad, 0x10, 0xcb, 0x47, 0x68, 0x7c, 0xf0, 0xe5, 0xdc, 0xb8,
|
||||
0x6a, 0xab, 0x8e, 0xf7, 0x9f, 0x08, 0x2c, 0x1b, 0x8a, 0xa2, 0xb9, 0x8f,
|
||||
0xce, 0xec, 0x5e, 0x61, 0xa8, 0xcd, 0x1c, 0x87, 0x60, 0x4a, 0xc3, 0x1a,
|
||||
0x5f, 0xdf, 0x87, 0x26, 0xc6, 0xcb, 0x7c, 0x69, 0xe4, 0x8b, 0x01, 0x06,
|
||||
0x59, 0x22, 0xfa, 0x34, 0x4b, 0x81, 0x87, 0x3c, 0x03, 0x6d, 0x02, 0x0a,
|
||||
0x77, 0xe6, 0x15, 0xd8, 0xcf, 0xa7, 0x68, 0x26, 0x6c, 0xfa, 0x2b, 0xd9,
|
||||
0x83, 0x5a, 0x2d, 0x0c, 0x3b, 0x70, 0x1c, 0xd4, 0x48, 0xbe, 0xa7, 0x0a,
|
||||
0xd9, 0xbe, 0xdc, 0xc3, 0x0c, 0x21, 0x33, 0xb3, 0x66, 0xff, 0x1c, 0x1b,
|
||||
0xc8, 0x96, 0x76, 0xe8, 0x6f, 0x44, 0x74, 0xbc, 0x9b, 0x1c, 0x7d, 0xc8,
|
||||
0xac, 0x21, 0xa8, 0x6e, 0x37, 0x02, 0x81, 0x80, 0x2c, 0x7c, 0xad, 0x1e,
|
||||
0x75, 0xf6, 0x69, 0x1d, 0xe7, 0xa6, 0xca, 0x74, 0x7d, 0x67, 0xc8, 0x65,
|
||||
0x28, 0x66, 0xc4, 0x43, 0xa6, 0xbd, 0x40, 0x57, 0xae, 0xb7, 0x65, 0x2c,
|
||||
0x52, 0xf9, 0xe4, 0xc7, 0x81, 0x7b, 0x56, 0xa3, 0xd2, 0x0d, 0xe8, 0x33,
|
||||
0x70, 0xcf, 0x06, 0x84, 0xb3, 0x4e, 0x44, 0x50, 0x75, 0x61, 0x96, 0x86,
|
||||
0x4b, 0xb6, 0x2b, 0xad, 0xf0, 0xad, 0x57, 0xd0, 0x37, 0x0d, 0x1d, 0x35,
|
||||
0x50, 0xcb, 0x69, 0x22, 0x39, 0x29, 0xb9, 0x3a, 0xd3, 0x29, 0x23, 0x02,
|
||||
0x60, 0xf7, 0xab, 0x30, 0x40, 0xda, 0x8e, 0x4d, 0x45, 0x70, 0x26, 0xf4,
|
||||
0xa2, 0x0d, 0xd0, 0x64, 0x5d, 0x47, 0x3c, 0x18, 0xf4, 0xd4, 0x52, 0x95,
|
||||
0x00, 0xae, 0x84, 0x6b, 0x47, 0xb2, 0x3c, 0x82, 0xd3, 0x72, 0x53, 0xde,
|
||||
0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18, 0x56, 0xfe, 0x39, 0x28,
|
||||
0x33, 0xe0, 0xdb, 0x03,
|
||||
};
|
||||
|
||||
static const uint8_t kTestSandbox[] = { 0x01, 0x02, 0x03 };
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_OEC_TEST_DATA_H_
|
||||
34
oemcrypto/test/oemcrypto_corpus_generator_helper.cpp
Normal file
34
oemcrypto/test/oemcrypto_corpus_generator_helper.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */
|
||||
/* source code may only be used and distributed under the Widevine Master */
|
||||
/* License Agreement. */
|
||||
#include "oemcrypto_corpus_generator_helper.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
namespace wvoec {
|
||||
bool g_generate_corpus;
|
||||
|
||||
void AppendToFile(const std::string& file_name, const char* message,
|
||||
const size_t message_size) {
|
||||
std::ofstream filebuf(file_name.c_str(), std::ios::app | std::ios::binary);
|
||||
if (!filebuf) {
|
||||
std::cout << "Cannot open file " << file_name.c_str() << std::endl;
|
||||
}
|
||||
filebuf.write(message, message_size);
|
||||
filebuf.close();
|
||||
}
|
||||
|
||||
std::string GetFileName(const char* directory) {
|
||||
std::string file_name(PATH_TO_CORPUS);
|
||||
file_name += directory;
|
||||
file_name += "/";
|
||||
file_name += std::to_string(rand());
|
||||
return file_name;
|
||||
}
|
||||
|
||||
void SetGenerateCorpus(bool should_generate_corpus) {
|
||||
g_generate_corpus = should_generate_corpus;
|
||||
}
|
||||
bool ShouldGenerateCorpus() { return g_generate_corpus; }
|
||||
} // namespace wvoec
|
||||
25
oemcrypto/test/oemcrypto_corpus_generator_helper.h
Normal file
25
oemcrypto/test/oemcrypto_corpus_generator_helper.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary */
|
||||
/* source code may only be used and distributed under the Widevine Master */
|
||||
/* License Agreement. */
|
||||
#ifndef CDM_OEMCRYPTO_CORPUS_GENERATOR_HELPER_H_
|
||||
#define CDM_OEMCRYPTO_CORPUS_GENERATOR_HELPER_H_
|
||||
|
||||
#define PATH_TO_CORPUS "./oemcrypto/test/fuzz_tests/corpus/"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
|
||||
namespace wvoec {
|
||||
void AppendToFile(const std::string& file_name, const char* message,
|
||||
const size_t message_size);
|
||||
|
||||
std::string GetFileName(const char* directory);
|
||||
|
||||
void SetGenerateCorpus(bool should_generate_corpus);
|
||||
// Output of this function decides if binary data needs to be written
|
||||
// to corpus files or not. Controlled by --generate_corpus flag.
|
||||
bool ShouldGenerateCorpus();
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_OEMCRYPTO_CORPUS_GENERATOR_HELPER_H_
|
||||
86
oemcrypto/test/oemcrypto_session_tests_helper.cpp
Normal file
86
oemcrypto/test/oemcrypto_session_tests_helper.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "oemcrypto_session_tests_helper.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "oec_test_data.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace wvoec;
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// Make this function available when in Fuzz mode because we are not inheriting
|
||||
// from OEMCryptoClientTest.
|
||||
const uint8_t* find(const vector<uint8_t>& message,
|
||||
const vector<uint8_t>& substring) {
|
||||
vector<uint8_t>::const_iterator pos = search(
|
||||
message.begin(), message.end(), substring.begin(), substring.end());
|
||||
if (pos == message.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &(*pos);
|
||||
}
|
||||
|
||||
// This creates a wrapped RSA key.
|
||||
void SessionUtil::CreateWrappedRSAKey() {
|
||||
Session s;
|
||||
ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_);
|
||||
provisioning_messages.PrepareSession(keybox_);
|
||||
ASSERT_NO_FATAL_FAILURE(provisioning_messages.SignAndVerifyRequest());
|
||||
ASSERT_NO_FATAL_FAILURE(provisioning_messages.CreateDefaultResponse());
|
||||
ASSERT_NO_FATAL_FAILURE(provisioning_messages.EncryptAndSignResponse());
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, provisioning_messages.LoadResponse());
|
||||
wrapped_rsa_key_ = provisioning_messages.wrapped_rsa_key();
|
||||
}
|
||||
|
||||
void SessionUtil::InstallKeybox(const wvoec::WidevineKeybox& keybox,
|
||||
bool good) {
|
||||
uint8_t wrapped[sizeof(wvoec::WidevineKeybox)];
|
||||
size_t length = sizeof(wvoec::WidevineKeybox);
|
||||
keybox_ = keybox;
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_WrapKeybox(reinterpret_cast<const uint8_t*>(&keybox),
|
||||
sizeof(keybox), wrapped, &length, nullptr, 0));
|
||||
OEMCryptoResult sts = OEMCrypto_InstallKeybox(wrapped, sizeof(keybox));
|
||||
if (good) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
} else {
|
||||
// Can return error now, or return error on IsKeyboxValid.
|
||||
}
|
||||
}
|
||||
|
||||
void SessionUtil::EnsureTestKeys() {
|
||||
switch (global_features.derive_key_method) {
|
||||
case DeviceFeatures::LOAD_TEST_KEYBOX:
|
||||
keybox_ = kTestKeybox;
|
||||
ASSERT_EQ(
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_LoadTestKeybox(reinterpret_cast<const uint8_t*>(&keybox_),
|
||||
sizeof(keybox_)));
|
||||
break;
|
||||
case DeviceFeatures::LOAD_TEST_RSA_KEY:
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey());
|
||||
break;
|
||||
case DeviceFeatures::TEST_PROVISION_30:
|
||||
// Can use oem certificate to install test rsa key.
|
||||
break;
|
||||
default:
|
||||
FAIL() << "Cannot run test without test keybox or RSA key installed.";
|
||||
}
|
||||
}
|
||||
|
||||
// This makes sure that the derived keys (encryption key and two mac keys)
|
||||
// are installed in OEMCrypto and in the test session.
|
||||
void SessionUtil::InstallTestRSAKey(Session* s) {
|
||||
if (global_features.loads_certificate) {
|
||||
if (wrapped_rsa_key_.size() == 0) {
|
||||
// If we don't have a wrapped key yet, create one.
|
||||
// This wrapped key will be shared by all sessions in the test.
|
||||
ASSERT_NO_FATAL_FAILURE(CreateWrappedRSAKey());
|
||||
}
|
||||
// Load the wrapped rsa test key.
|
||||
ASSERT_NO_FATAL_FAILURE(s->InstallRSASessionTestKey(wrapped_rsa_key_));
|
||||
}
|
||||
// Test RSA key should be loaded.
|
||||
ASSERT_NO_FATAL_FAILURE(s->PreparePublicKey());
|
||||
}
|
||||
} // namespace wvoec
|
||||
38
oemcrypto/test/oemcrypto_session_tests_helper.h
Normal file
38
oemcrypto/test/oemcrypto_session_tests_helper.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "oec_session_util.h"
|
||||
#include "oec_test_data.h"
|
||||
#include "OEMCryptoCAS.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
class SessionUtil {
|
||||
public:
|
||||
SessionUtil()
|
||||
: encoded_rsa_key_(kTestRSAPKCS8PrivateKeyInfo2_2048,
|
||||
kTestRSAPKCS8PrivateKeyInfo2_2048 +
|
||||
sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048)) {}
|
||||
|
||||
// Create a new wrapped DRM Certificate.
|
||||
void CreateWrappedRSAKey();
|
||||
|
||||
// This is used to force installation of a keybox. This overwrites the
|
||||
// production keybox -- it does NOT use OEMCrypto_LoadTestKeybox.
|
||||
void InstallKeybox(const wvoec::WidevineKeybox& keybox, bool good);
|
||||
|
||||
// This loads the test keybox or the test RSA key, using LoadTestKeybox or
|
||||
// LoadTestRSAKey as needed.
|
||||
void EnsureTestKeys();
|
||||
|
||||
void InstallTestRSAKey(Session* s);
|
||||
|
||||
std::vector<uint8_t> encoded_rsa_key_;
|
||||
std::vector<uint8_t> wrapped_rsa_key_;
|
||||
wvoec::WidevineKeybox keybox_;
|
||||
};
|
||||
|
||||
} // namespace wvoec
|
||||
6645
oemcrypto/test/oemcrypto_test.cpp
Normal file
6645
oemcrypto/test/oemcrypto_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
161
oemcrypto/test/oemcrypto_test_android.cpp
Normal file
161
oemcrypto/test/oemcrypto_test_android.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// OEMCrypto unit tests - extra tests required for Android platform.
|
||||
//
|
||||
// The Widevine CDM system can be built on many platforms, with different
|
||||
// capabilities. For example, some platforms do not require usage tables,
|
||||
// and some can have a pre-installed certificate and do not need a keybox.
|
||||
// On Android, these features are not optional. This set of unit tests
|
||||
// verify that these features are implemented.
|
||||
//
|
||||
// In the file oemcrypto_test.cpp, the unit tests only verify correct
|
||||
// functionality for functions that are implemented. Android devices must pass
|
||||
// unit tests in both files.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "oec_test_data.h"
|
||||
#include "OEMCryptoCAS.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// These tests are required for LollyPop Android devices.
|
||||
class OEMCryptoAndroidLMPTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
OEMCrypto_SetSandbox(kTestSandbox, sizeof(kTestSandbox));
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize());
|
||||
}
|
||||
|
||||
void TearDown() override { OEMCrypto_Terminate(); }
|
||||
};
|
||||
|
||||
// Android devices must have a keybox, or use provisioning 3.0.
|
||||
TEST_F(OEMCryptoAndroidLMPTest, GetKeyDataImplemented) {
|
||||
uint8_t key_data[256];
|
||||
size_t key_data_len = sizeof(key_data);
|
||||
if (OEMCrypto_Keybox == OEMCrypto_GetProvisioningMethod()) {
|
||||
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_GetKeyData(key_data, &key_data_len));
|
||||
} else {
|
||||
ASSERT_EQ(OEMCrypto_OEMCertificate, OEMCrypto_GetProvisioningMethod());
|
||||
}
|
||||
}
|
||||
|
||||
// Android devices must have a valid keybox.
|
||||
TEST_F(OEMCryptoAndroidLMPTest, ValidKeybox) {
|
||||
if (OEMCrypto_GetProvisioningMethod() == OEMCrypto_Keybox) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoAndroidLMPTest, MinVersionNumber9) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_LE(9u, version);
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoAndroidLMPTest, ValidKeyboxTest) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoAndroidLMPTest, RewrapDeviceRSAKeyImplemented) {
|
||||
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_LoadProvisioning(0, nullptr, 0, 0, nullptr, 0, nullptr,
|
||||
nullptr));
|
||||
}
|
||||
|
||||
// The Generic Crypto API functions are required for Android.
|
||||
TEST_F(OEMCryptoAndroidLMPTest, GenericCryptoImplemented) {
|
||||
ASSERT_NE(
|
||||
OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_Generic_Encrypt(0, nullptr, 0, nullptr,
|
||||
OEMCrypto_AES_CBC_128_NO_PADDING, nullptr));
|
||||
ASSERT_NE(
|
||||
OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_Generic_Decrypt(0, nullptr, 0, nullptr,
|
||||
OEMCrypto_AES_CBC_128_NO_PADDING, nullptr));
|
||||
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_Generic_Sign(0, nullptr, 0, OEMCrypto_HMAC_SHA256,
|
||||
nullptr, nullptr));
|
||||
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_Generic_Verify(0, nullptr, 0, OEMCrypto_HMAC_SHA256,
|
||||
nullptr, 0));
|
||||
}
|
||||
|
||||
// Android requires support of usage table. The usage table is used for Secure
|
||||
// Stops and for offline licenses.
|
||||
TEST_F(OEMCryptoAndroidLMPTest, SupportsUsageTable) {
|
||||
ASSERT_TRUE(OEMCrypto_SupportsUsageTable());
|
||||
}
|
||||
|
||||
// Android devices require L1 OEMCrypto.
|
||||
TEST_F(OEMCryptoAndroidLMPTest, Level1Required) {
|
||||
const char* char_level = OEMCrypto_SecurityLevel();
|
||||
std::string security_level(char_level ? char_level : "");
|
||||
EXPECT_EQ("L1", security_level)
|
||||
<< "The security level is " << security_level << ". but we expect L1.\n"
|
||||
<< "If you are testing a device that should be L3 or L2, please\n"
|
||||
<< "repeat the tests with the flag --gtest_filter=\"*-*Level1Required\"";
|
||||
}
|
||||
|
||||
// These tests are required for M Android devices.
|
||||
class OEMCryptoAndroidMNCTest : public OEMCryptoAndroidLMPTest {};
|
||||
|
||||
TEST_F(OEMCryptoAndroidMNCTest, MinVersionNumber10) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_GE(version, 10u);
|
||||
}
|
||||
|
||||
// Android devices using Provisioning 2.0 must be able to load a test keybox.
|
||||
// If they are not using Provisioning 2.0, then they must use Provisioning 3.0.
|
||||
TEST_F(OEMCryptoAndroidMNCTest, LoadsTestKeyboxImplemented) {
|
||||
if (OEMCrypto_Keybox == OEMCrypto_GetProvisioningMethod()) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestKeybox(
|
||||
reinterpret_cast<const uint8_t*>(&kTestKeybox),
|
||||
sizeof(kTestKeybox)));
|
||||
} else {
|
||||
// Android should use keybox or provisioning 3.0.
|
||||
ASSERT_EQ(OEMCrypto_OEMCertificate, OEMCrypto_GetProvisioningMethod());
|
||||
}
|
||||
}
|
||||
|
||||
// Android requires implementation of these functions.
|
||||
TEST_F(OEMCryptoAndroidMNCTest, NumberOfSessionsImplemented) {
|
||||
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_GetNumberOfOpenSessions(nullptr));
|
||||
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_GetMaxNumberOfSessions(nullptr));
|
||||
}
|
||||
|
||||
// Android requires implementation of these functions.
|
||||
TEST_F(OEMCryptoAndroidMNCTest, QueryKeyControlImplemented) {
|
||||
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
|
||||
OEMCrypto_QueryKeyControl(0, nullptr, 0, nullptr, nullptr));
|
||||
}
|
||||
|
||||
// These tests are required for N Android devices.
|
||||
class OEMCryptoAndroidNYCTest : public OEMCryptoAndroidMNCTest {};
|
||||
|
||||
TEST_F(OEMCryptoAndroidNYCTest, MinVersionNumber11) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_GE(version, 11u);
|
||||
}
|
||||
|
||||
// These tests are required for O MR1 Android devices.
|
||||
class OEMCryptoAndroidOCTest : public OEMCryptoAndroidNYCTest {};
|
||||
|
||||
TEST_F(OEMCryptoAndroidOCTest, MinVersionNumber13) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_GE(version, 13u);
|
||||
}
|
||||
|
||||
// These tests are required for Q Android devices.
|
||||
class OEMCryptoAndroidQTest : public OEMCryptoAndroidOCTest {};
|
||||
|
||||
TEST_F(OEMCryptoAndroidQTest, MinVersionNumber14) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_GE(version, 15u);
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
59
oemcrypto/test/oemcrypto_test_main.cpp
Normal file
59
oemcrypto/test/oemcrypto_test_main.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "OEMCryptoCAS.h"
|
||||
#include "log.h"
|
||||
#include "oec_device_features.h"
|
||||
#include "oemcrypto_corpus_generator_helper.h"
|
||||
#include "test_sleep.h"
|
||||
|
||||
static void acknowledge_cast() {
|
||||
std::cout
|
||||
<< "==================================================================\n"
|
||||
<< "= This device is expected to load x509 certs as a cast receiver. =\n"
|
||||
<< "==================================================================\n";
|
||||
}
|
||||
|
||||
// This special main procedure is used instead of the standard GTest main,
|
||||
// because we need to initialize the list of features supported by the device.
|
||||
// Also, the test filter is updated based on the feature list.
|
||||
int main(int argc, char** argv) {
|
||||
bool is_cast_receiver = false;
|
||||
bool filter_tests = true;
|
||||
int verbosity = 0;
|
||||
// Skip the first element, which is the program name.
|
||||
const std::vector<std::string> args(argv + 1, argv + argc);
|
||||
for (const std::string& arg : args) {
|
||||
if (arg == "--generate_corpus") {
|
||||
wvoec::SetGenerateCorpus(true);
|
||||
}
|
||||
if (arg == "--verbose" || arg == "-v") {
|
||||
++verbosity;
|
||||
} else if (arg == "--cast") {
|
||||
acknowledge_cast();
|
||||
is_cast_receiver = true;
|
||||
}
|
||||
if (arg == "--force_load_test_keybox") {
|
||||
std::cerr << "The argument --force_load_test_keybox is obsolete.\n";
|
||||
return 1;
|
||||
}
|
||||
if (arg == "--no_filter") {
|
||||
filter_tests = false;
|
||||
}
|
||||
if (arg == "--fake_sleep") {
|
||||
wvutil::TestSleep::set_real_sleep(false);
|
||||
}
|
||||
}
|
||||
wvutil::g_cutoff = static_cast<wvutil::LogPriority>(verbosity);
|
||||
wvoec::global_features.Initialize();
|
||||
wvoec::global_features.set_cast_receiver(is_cast_receiver);
|
||||
// Init GTest after device properties has been initialized.
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
// If the user requests --no_filter, we don't change the filter, otherwise, we
|
||||
// filter out features that are not supported.
|
||||
if (filter_tests) {
|
||||
::testing::GTEST_FLAG(filter) =
|
||||
wvoec::global_features.RestrictFilter(::testing::GTEST_FLAG(filter));
|
||||
}
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
148
oemcrypto/test/test_sleep.cpp
Normal file
148
oemcrypto/test/test_sleep.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "test_sleep.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "clock.h"
|
||||
#include "log.h"
|
||||
|
||||
namespace wvutil {
|
||||
|
||||
bool TestSleep::real_sleep_ = true;
|
||||
TestSleep::CallBack* TestSleep::callback_ = nullptr;
|
||||
int TestSleep::total_clock_rollback_ = 0;
|
||||
|
||||
void TestSleep::Sleep(unsigned int seconds) {
|
||||
int64_t milliseconds = 1000 * seconds;
|
||||
if (real_sleep_) {
|
||||
// This next bit of logic is to avoid slow drift apart of the real clock and
|
||||
// the fake clock. We compute how far from the real clock has advanced in
|
||||
// total since the start, and then compare to a running total of sleep
|
||||
// calls. We sleep for approximately x second, and then advance the clock by
|
||||
// the amount of time that has actually passed.
|
||||
static auto start_real = std::chrono::system_clock().now();
|
||||
static int64_t fake_clock = 0;
|
||||
sleep(seconds);
|
||||
auto now_real = std::chrono::system_clock().now();
|
||||
int64_t total_real = (now_real - start_real) / std::chrono::milliseconds(1);
|
||||
// We want to advance the fake clock by the difference between the real
|
||||
// clock, and the previous value on the fake clock.
|
||||
milliseconds = total_real - fake_clock;
|
||||
fake_clock += milliseconds;
|
||||
}
|
||||
if (callback_ != nullptr) callback_->ElapseTime(milliseconds);
|
||||
}
|
||||
|
||||
void TestSleep::SyncFakeClock() {
|
||||
// Syncing can be done by sleeping 0 seconds.
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
bool TestSleep::RollbackSystemTime(int seconds) {
|
||||
if (real_sleep_) {
|
||||
#ifdef _WIN32
|
||||
// See remarks from this for why this series is used.
|
||||
// https://msdn.microsoft.com/en-us/f77cdf86-0f97-4a89-b565-95b46fa7d65b
|
||||
SYSTEMTIME time;
|
||||
GetSystemTime(&time);
|
||||
FILETIME file_time;
|
||||
if (!SystemTimeToFileTime(time, &file_time)) return false;
|
||||
uint64_t long_time =
|
||||
static_cast<uint64_t>(file_time.dwLowDateTime) |
|
||||
(static_cast<uint64_t>(file_time.dwHighDateTime) << 32);
|
||||
long_time += static_cast<uint64_t>(delta_seconds) *
|
||||
1e7; // long_time is in 100-nanosecond intervals.
|
||||
file_time.dwLowDateTime = long_time & ((1ull << 32) - 1);
|
||||
file_time.dwHighDateTime = long_time >> 32;
|
||||
if (!FileTimeToSystemTime(&file_time, &time)) return false;
|
||||
if (!SetSystemTime(&time)) return false;
|
||||
#else
|
||||
auto time = std::chrono::system_clock::now();
|
||||
auto modified_time = time - std::chrono::seconds(seconds);
|
||||
;
|
||||
timespec time_spec;
|
||||
time_spec.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
modified_time.time_since_epoch())
|
||||
.count();
|
||||
time_spec.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
modified_time.time_since_epoch())
|
||||
.count() %
|
||||
(1000 * 1000 * 1000);
|
||||
if (clock_settime(CLOCK_REALTIME, &time_spec)) {
|
||||
LOGE("Error setting clock: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
} // end if(real_sleep_)...
|
||||
|
||||
// For both real and fake sleep we still update the callback and we still keep
|
||||
// track of the total amount of time slept.
|
||||
total_clock_rollback_ += seconds;
|
||||
if (callback_ != nullptr) callback_->ElapseTime(-1000 * seconds);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestSleep::CanChangeSystemTime() {
|
||||
// If we are using a fake clock, then we can move the clock backwards by
|
||||
// just going backwards.
|
||||
// ElapseTime.
|
||||
if (!real_sleep_) {
|
||||
return true;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
LUID desired_id;
|
||||
if (!LookupPrivilegeValue(nullptr, SE_SYSTEMTIME_NAME, &desired_id)) {
|
||||
LOGE("Win32 time rollback: no SYSTEMTIME permission.");
|
||||
return false;
|
||||
}
|
||||
HANDLE token;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)) {
|
||||
LOGE("Win32 time rollback: cannot access process token.");
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<void, decltype(&CloseHandle)> safe_token(token, &CloseHandle);
|
||||
|
||||
// This queries all the permissions given to the token to determine if we can
|
||||
// change the system time. Note this is subtly different from PrivilegeCheck
|
||||
// as that only checks "enabled" privileges; even with admin rights, the
|
||||
// privilege is default disabled, even when granted.
|
||||
|
||||
DWORD size = 0;
|
||||
// Determine how big we need to allocate first.
|
||||
GetTokenInformation(token, TokenPrivileges, nullptr, 0, &size);
|
||||
// Since TOKEN_PRIVILEGES uses a variable-length array, we need to use malloc
|
||||
std::unique_ptr<TOKEN_PRIVILEGES, decltype(&free)> privileges(
|
||||
(TOKEN_PRIVILEGES*)malloc(size), &free);
|
||||
if (privileges && GetTokenInformation(token, TokenPrivileges,
|
||||
privileges.get(), size, &size)) {
|
||||
for (int i = 0; i < privileges->PrivilegeCount; i++) {
|
||||
if (privileges->Privileges[i].Luid.HighPart == desired_id.HighPart &&
|
||||
privileges->Privileges[i].Luid.LowPart == desired_id.LowPart) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGE("Win32 time rollback: cannot set system time.");
|
||||
return false;
|
||||
#else
|
||||
// Otherwise, the test needs to be run as root.
|
||||
const uid_t uid = getuid();
|
||||
if (uid == 0) return true;
|
||||
LOGE("Unix time rollback: not running as root (uid=%u.", uid);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
} // namespace wvutil
|
||||
75
oemcrypto/test/test_sleep.h
Normal file
75
oemcrypto/test/test_sleep.h
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// TestSleep - Controls sleep and clock adjustment during tests.
|
||||
//
|
||||
#ifndef WVCAS_UTIL_TEST_SLEEP_H_
|
||||
#define WVCAS_UTIL_TEST_SLEEP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace wvutil {
|
||||
|
||||
class TestSleep {
|
||||
public:
|
||||
// The callback is called when the clock should be advanced.
|
||||
class CallBack {
|
||||
public:
|
||||
virtual void ElapseTime(int64_t milliseconds) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~CallBack(){};
|
||||
};
|
||||
|
||||
// If real_sleep_ is true, then this sleeps for |seconds| of time. If
|
||||
// real_sleep_ is false, then the fake clock is advanced by |seconds|. If the
|
||||
// callback exists, this calls the callback.
|
||||
static void Sleep(unsigned int seconds);
|
||||
|
||||
// If we are using a real clock and a fake clock, then the real clock advances
|
||||
// a little while we are doing work, but the fake one only advances when we
|
||||
// sleep. This function advances the fake clock to be in sync with the real
|
||||
// clock. This function should be called to prevent a slow flaky test from
|
||||
// failing due to this drift.
|
||||
static void SyncFakeClock();
|
||||
|
||||
// Roll the system clock back by |seconds|. Returns true on success. A well
|
||||
// mannered test will call CanChangeSystemTime before attempting to call this
|
||||
// function and then assert that this is true. This function should *NOT* roll
|
||||
// back the clock used by OEMCrypto -- in fact, there are several tests that
|
||||
// verify this function does not roll back the clock used by OEMCrypto.
|
||||
static bool RollbackSystemTime(int seconds);
|
||||
|
||||
// Roll the system clock forward to undo all previous calls to
|
||||
// RollBackSystemTime. Returns true on success.
|
||||
static bool ResetRollback() {
|
||||
return total_clock_rollback_ == 0 ||
|
||||
RollbackSystemTime(-total_clock_rollback_);
|
||||
}
|
||||
|
||||
// Returns true if the system time can be rolled back. This is true on some
|
||||
// devices if the tests are run as root. It is also true when using a fake
|
||||
// clock with the reference version of OEMCrypto. This function is about the
|
||||
// system clock, *NOT* the clock used by OEMCrypto.
|
||||
static bool CanChangeSystemTime();
|
||||
|
||||
static void set_real_sleep(bool real_sleep) { real_sleep_ = real_sleep; }
|
||||
static bool real_sleep() { return real_sleep_; }
|
||||
|
||||
// The callback is notified whenever sleep is called.
|
||||
static void set_callback(CallBack* callback) { callback_ = callback; }
|
||||
|
||||
private:
|
||||
// Controls if the test sleep should use real sleep.
|
||||
static bool real_sleep_;
|
||||
// Called when the clock should advance.
|
||||
static CallBack* callback_;
|
||||
// The sum of all calls to RollBackSystemTime. Kept so we can undo all changes
|
||||
// at the end of a test.
|
||||
static int total_clock_rollback_;
|
||||
};
|
||||
|
||||
} // namespace wvutil
|
||||
|
||||
#endif // WVCAS_UTIL_TEST_SLEEP_H_
|
||||
108
oemcrypto/test/wvcrc.cpp
Normal file
108
oemcrypto/test/wvcrc.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Compute CRC32 Checksum. Needed for verification of WV Keybox.
|
||||
//
|
||||
#include "platform.h"
|
||||
#include "wvcrc32.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
#define INIT_CRC32 0xffffffff
|
||||
|
||||
uint32_t wvrunningcrc32(const uint8_t* p_begin, int i_count, uint32_t i_crc) {
|
||||
static uint32_t CRC32[256] = {
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
|
||||
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
|
||||
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
|
||||
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
|
||||
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
|
||||
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
|
||||
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
|
||||
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
|
||||
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
|
||||
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
|
||||
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
|
||||
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
|
||||
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
|
||||
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
|
||||
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
|
||||
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
|
||||
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
|
||||
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
|
||||
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
|
||||
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
|
||||
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
|
||||
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
|
||||
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
|
||||
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
|
||||
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
|
||||
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
|
||||
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
|
||||
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
|
||||
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
|
||||
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
|
||||
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
|
||||
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
|
||||
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
|
||||
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
|
||||
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
|
||||
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
|
||||
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
|
||||
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
|
||||
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
|
||||
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
|
||||
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
|
||||
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
|
||||
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
|
||||
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
|
||||
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
|
||||
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
|
||||
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
|
||||
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
|
||||
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
|
||||
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
|
||||
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
|
||||
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
|
||||
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
|
||||
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
||||
};
|
||||
|
||||
/* Calculate the CRC */
|
||||
while (i_count > 0) {
|
||||
i_crc = (i_crc << 8) ^ CRC32[(i_crc >> 24) ^ ((uint32_t) * p_begin)];
|
||||
p_begin++;
|
||||
i_count--;
|
||||
}
|
||||
|
||||
return(i_crc);
|
||||
}
|
||||
|
||||
uint32_t wvcrc32(const uint8_t* p_begin, int i_count) {
|
||||
return(wvrunningcrc32(p_begin, i_count, INIT_CRC32));
|
||||
}
|
||||
|
||||
uint32_t wvcrc32Init() {
|
||||
return INIT_CRC32;
|
||||
}
|
||||
|
||||
uint32_t wvcrc32Cont(const uint8_t* p_begin, int i_count, uint32_t prev_crc) {
|
||||
return(wvrunningcrc32(p_begin, i_count, prev_crc));
|
||||
}
|
||||
|
||||
uint32_t wvcrc32n(const uint8_t* p_begin, int i_count) {
|
||||
return htonl(wvrunningcrc32(p_begin, i_count, INIT_CRC32));
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
23
oemcrypto/test/wvcrc32.h
Normal file
23
oemcrypto/test/wvcrc32.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Compute CRC32 Checksum. Needed for verification of WV Keybox.
|
||||
//
|
||||
#ifndef CDM_WVCRC32_H_
|
||||
#define CDM_WVCRC32_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
uint32_t wvcrc32(const uint8_t* p_begin, int i_count);
|
||||
uint32_t wvcrc32Init();
|
||||
uint32_t wvcrc32Cont(const uint8_t* p_begin, int i_count, uint32_t prev_crc);
|
||||
|
||||
// Convert to network byte order
|
||||
uint32_t wvcrc32n(const uint8_t* p_begin, int i_count);
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_WVCRC32_H_
|
||||
Reference in New Issue
Block a user