OEMCrypto v14 Docs

This has the released version of the OEMCrypto API v14 documentation.

This patch also includes sample code and unit tests.
This commit is contained in:
Fred Gylys-Colwell
2018-01-23 09:29:28 -08:00
parent b124164fb8
commit 7b71a449d0
62 changed files with 20783 additions and 0 deletions

View File

@@ -0,0 +1,227 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// OEMCrypto device features for unit tests
//
#include "oec_device_features.h"
#include <stdio.h>
#include <cstring>
#include "oec_test_data.h"
namespace wvoec {
DeviceFeatures global_features;
void DeviceFeatures::Initialize(bool is_cast_receiver,
bool force_load_test_keybox) {
cast_receiver = is_cast_receiver;
uses_keybox = false;
uses_certificate = false;
loads_certificate = false;
generic_crypto = false;
usage_table = false;
supports_rsa_3072 = false;
api_version = 0;
derive_key_method = NO_METHOD;
if (OEMCrypto_SUCCESS != OEMCrypto_Initialize()) {
printf("OEMCrypto_Initialize failed. All tests will fail.\n");
return;
}
uint32_t nonce = 0;
uint8_t buffer[1];
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) {
loads_certificate =
(OEMCrypto_ERROR_NOT_IMPLEMENTED !=
OEMCrypto_RewrapDeviceRSAKey(session, buffer, 0, buffer, 0, &nonce,
buffer, 0, buffer, buffer, &size));
} else if (provisioning_method == OEMCrypto_OEMCertificate) {
// If the device says it uses Provisioning 3.0, then it should be able to
// load a DRM certificate. These devices must support RewrapDeviceRSAKey30.
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");
uses_certificate = (OEMCrypto_ERROR_NOT_IMPLEMENTED !=
OEMCrypto_GenerateRSASignature(session, buffer, 0, buffer,
&size, kSign_RSASSA_PSS));
printf("uses_certificate = %s.\n", uses_certificate ? "true" : "false");
generic_crypto =
(OEMCrypto_ERROR_NOT_IMPLEMENTED !=
OEMCrypto_Generic_Encrypt(session, buffer, 0, buffer,
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");
if (force_load_test_keybox) {
derive_key_method = FORCE_TEST_KEYBOX;
} else {
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");
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;
uses_certificate = 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 EXISTING_TEST_KEYBOX:
printf("EXISTING_TEST_KEYBOX: Keybox is already the test keybox.\n");
break;
case FORCE_TEST_KEYBOX:
printf("FORCE_TEST_KEYBOX: User requested calling InstallKeybox.\n");
break;
case TEST_PROVISION_30:
printf("TEST_PROVISION_30: Device provisioed with OEM Cert.\n");
break;
}
OEMCrypto_Terminate();
}
std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
std::string filter = initial_filter;
if (!uses_keybox) FilterOut(&filter, "*KeyboxTest*");
if (derive_key_method
!= FORCE_TEST_KEYBOX) FilterOut(&filter, "*ForceKeybox*");
if (!uses_certificate) FilterOut(&filter, "OEMCrypto*Cert*");
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*");
// 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.
// TODO(jfore): Update to pass in parameters.
if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestKeybox(NULL, 0)) {
derive_key_method = LOAD_TEST_KEYBOX;
} else if (IsTestKeyboxInstalled()) {
derive_key_method = EXISTING_TEST_KEYBOX;
}
} else if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestRSAKey()) {
derive_key_method = LOAD_TEST_RSA_KEY;
}
}
bool DeviceFeatures::IsTestKeyboxInstalled() {
uint8_t key_data[256];
size_t key_data_len = sizeof(key_data);
if (OEMCrypto_GetKeyData(key_data, &key_data_len) != OEMCrypto_SUCCESS)
return false;
if (key_data_len != sizeof(kTestKeybox.data_)) return false;
if (memcmp(key_data, kTestKeybox.data_, key_data_len)) return false;
uint8_t dev_id[128] = {0};
size_t dev_id_len = 128;
if (OEMCrypto_GetDeviceID(dev_id, &dev_id_len) != OEMCrypto_SUCCESS)
return false;
// We use strncmp instead of memcmp because we don't really care about the
// multiple '\0' characters at the end of the device id.
return 0 == strncmp(reinterpret_cast<const char*>(dev_id),
reinterpret_cast<const char*>(kTestKeybox.device_id_),
sizeof(kTestKeybox.device_id_));
}
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;
}
}
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

View File

@@ -0,0 +1,47 @@
#ifndef CDM_OEC_DEVICE_FEATURES_H_
#define CDM_OEC_DEVICE_FEATURES_H_
#include <string>
#include "OEMCryptoCENC.h"
#include "wv_keybox.h"
namespace wvoec {
class DeviceFeatures {
public:
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.
EXISTING_TEST_KEYBOX, // Keybox is already the test keybox.
FORCE_TEST_KEYBOX, // User requested calling InstallKeybox.
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 uses_certificate; // Device uses a certificate 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.
uint32_t api_version;
OEMCrypto_ProvisioningMethod provisioning_method;
void Initialize(bool is_cast_receiver, bool force_load_test_keybox);
std::string RestrictFilter(const std::string& initial_filter);
private:
void PickDerivedKey();
bool IsTestKeyboxInstalled();
void FilterOut(std::string* current_filter, const std::string& new_filter);
};
extern DeviceFeatures global_features;
const char* ProvisioningMethodName(OEMCrypto_ProvisioningMethod method);
} // namespace wvoec
#endif // CDM_OEC_DEVICE_FEATURES_H_

1284
test/oec_session_util.cpp Normal file

File diff suppressed because it is too large Load Diff

412
test/oec_session_util.h Normal file
View File

@@ -0,0 +1,412 @@
#ifndef CDM_OEC_SESSION_UTIL_H_
#define CDM_OEC_SESSION_UTIL_H_
// Copyright 2016 Google Inc. All Rights Reserved.
//
// OEMCrypto unit tests
//
#include <openssl/rsa.h>
#include <string>
#include <vector>
#include "oec_device_features.h"
#include "pst_report.h"
#include "wv_cdm_constants.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 {
const size_t kMaxNumKeys = 20;
namespace {
#if defined(TEST_SPEED_MULTIPLIER) // Can slow test time limits when
// debugging is slowing everything.
const int kSpeedMultiplier = TEST_SPEED_MULTIPLIER;
#else
const int kSpeedMultiplier = 1;
#endif
const int kShortSleep = 1 * kSpeedMultiplier;
const int kLongSleep = 2 * kSpeedMultiplier;
const uint32_t kDuration = 2 * kSpeedMultiplier;
const uint32_t kLongDuration = 5 * kSpeedMultiplier;
const int32_t kTimeTolerance = 3 * kSpeedMultiplier;
const time_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.
const size_t kTestKeyIdMaxLength = 16;
// Most content will use a key id that is 16 bytes long.
const int kDefaultKeyIdLength = 16;
const size_t kMaxTestRSAKeyLength = 2000; // Rough estimate.
const size_t kMaxPSTLength = 255; // In specification.
const size_t kMaxMessageSize = 8 * 1024; // In specification.
const size_t kMaxDecryptSize = 100 * 1024; // In specification.
typedef struct {
uint8_t key_id[kTestKeyIdMaxLength];
size_t key_id_length;
uint8_t key_data[wvcdm::MAC_KEY_SIZE];
size_t key_data_length;
uint8_t key_iv[wvcdm::KEY_IV_SIZE];
uint8_t control_iv[wvcdm::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[wvcdm::KEY_IV_SIZE];
uint8_t mac_keys[2 * wvcdm::MAC_KEY_SIZE];
uint8_t pst[kMaxPSTLength];
};
// 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[wvcdm::KEY_IV_SIZE];
size_t rsa_key_length;
uint32_t nonce;
};
struct Test_PST_Report {
Test_PST_Report(const std::string& pst_in,
OEMCrypto_Usage_Entry_Status status_in)
: status(status_in), pst(pst_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;
};
struct EntitledContentKeyData {
uint8_t entitlement_key_id[wvcdm::KEY_SIZE];
uint8_t content_key_id[wvcdm::KEY_SIZE];
uint8_t content_key_data_iv[wvcdm::KEY_SIZE];
uint8_t content_key_data[wvcdm::KEY_SIZE];
};
// 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 {
public:
Session();
~Session();
// Returns the most recently generated nonce.
// Valid after call to GenerateNonce.
uint32_t get_nonce() { return nonce_; }
// Valid after call to open().
uint32_t session_id() { 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 = NULL);
// 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_mock::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();
// Loads and verifies the keys in the message pointed to by message_ptr()
// using OEMCrypto_LoadKeys. This message should have already been created
// by FillSimpleMessage, modified if needed, and then encrypted and signed by
// the server's mac key in EncryptAndSign.
void LoadTestKeys(const std::string& pst = "", bool new_mac_keys = true);
// Loads the entitlement keys in the message pointed to by message_ptr()
// using OEMCrypto_LoadKeys. This message should have already been created
// by FillSimpleEntitlementMessage, modified if needed, and then encrypted
// and signed by the server's mac key in EncryptAndSign.
void LoadEnitlementTestKeys(const std::string& pst = "",
bool new_mac_keys = true,
OEMCryptoResult expected_sts = OEMCrypto_SUCCESS);
// Fills an OEMCrypto_EntitledContentKeyObject using the information from
// the license_ and randomly generated content keys. This method should be
// called after LoadEnitlementTestKeys.
void FillEntitledKeyArray();
// Encrypts and loads the entitled content keys via
// OEMCrypto_LoadEntitledContentKeys.
void LoadEntitledContentKeys(
OEMCryptoResult expected_sts = OEMCrypto_SUCCESS);
// This uses OEMCrypto_QueryKeyControl to check that the keys in OEMCrypto
// have the correct key control data.
void VerifyTestKeys();
// This uses OEMCrypto_QueryKeyControl to check that the keys in OEMCrypto
// have the correct key control data.
void VerifyEntitlementTestKeys();
// This creates a refresh key or license renewal message, signs it with the
// server's mac key, and calls OEMCrypto_RefreshKeys.
void RefreshTestKeys(const size_t key_count, uint32_t control_bits,
uint32_t nonce, OEMCryptoResult expected_result);
// This sets the key id in the current message data to the specified string.
// This is used to test with different key id lengths.
void SetKeyId(int index, const string& key_id);
// This fills the data structure license_ with key information. This data
// can be modified, and then should be encrypted and signed in EncryptAndSign
// before being loaded in LoadTestKeys.
void FillSimpleMessage(uint32_t duration, uint32_t control, uint32_t nonce,
const std::string& pst = "");
// This fills the data structure license_ with entitlement key information.
// This data can be modified, and then should be encrypted and signed in
// EncryptAndSign before being loaded in LoadEnitlementTestKeys.
void FillSimpleEntitlementMessage(
uint32_t duration, uint32_t control,
uint32_t nonce, const std::string& pst = "");
// Like FillSimpleMessage, this fills encrypted_license_ with data. The name
// is a little misleading: the license renewal message is not encrypted, it
// is just signed. The signature is computed in RefreshTestKeys, above.
void FillRefreshMessage(size_t key_count, uint32_t control_bits,
uint32_t nonce);
// This copies data from license_ to encrypted_license_, and then encrypts
// each field in the key array appropriately. It then signes the buffer with
// the server mac keys. It then fills out the key_array_ so that pointers in
// that array point to the locations in the encrypted message.
void EncryptAndSign();
// This encrypts an RSAPrivateKeyMessage with encryption_key so that it may be
// loaded with OEMCrypto_RewrapDeviceRSAKey.
void EncryptProvisioningMessage(RSAPrivateKeyMessage* data,
RSAPrivateKeyMessage* encrypted,
const vector<uint8_t>& encryption_key);
// Sign the buffer with server's mac key.
void ServerSignBuffer(const uint8_t* data, size_t data_length,
std::vector<uint8_t>* signature);
// Sign the buffer with client's known mac key. Known test keys must be
// installed first.
void ClientSignMessage(const vector<uint8_t>& data,
std::vector<uint8_t>* signature);
// This checks the signature generated by OEMCrypto_GenerateSignature against
// that generaged by ClientSignMessage.
void VerifyClientSignature(size_t data_length = 400);
// Set the pointers in key_array[*] to point values inside data. This is
// needed to satisfy range checks in OEMCrypto_LoadKeys.
void FillKeyArray(const MessageData& data, OEMCrypto_KeyObject* key_array);
// As in FillKeyArray but for the license renewal message passed to
// OEMCrypto_RefreshKeys.
void FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array,
size_t key_count);
// 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);
// 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_result);
// 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 loads the OEM cert's public
// rsa key into public_rsa_.
void LoadOEMCert(bool verify_cert = false);
// Creates RSAPrivateKeyMessage for the specified rsa_key, encrypts it with
// the specified encryption key, and then signs it with the server's mac key.
// If encryption_key is null, use the session's enc_key_.
void MakeRSACertificate(struct RSAPrivateKeyMessage* encrypted,
size_t message_size, std::vector<uint8_t>* signature,
uint32_t allowed_schemes,
const vector<uint8_t>& rsa_key,
const vector<uint8_t>* encryption_key = NULL);
// 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 = NULL,
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.
void CreateNewUsageEntry();
// 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);
// Deactivate this session's usage entry.
void DeactivateUsageEntry(const std::string& pst);
// 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.
wvcdm::Unpacked_PST_Report pst_report() {
return wvcdm::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);
// Generate and 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 GenerateVerifyReport(const std::string& pst,
OEMCrypto_Usage_Entry_Status status,
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_; }
// The encrypted license response or license renewal response.
MessageData& encrypted_license() { return padded_message_; }
// A pointer to the buffer holding encrypted_license.
const uint8_t* message_ptr();
// An array of key objects for use in LoadKeys.
OEMCrypto_KeyObject* key_array() { return key_array_; }
// The last signature generated with the server's mac key.
std::vector<uint8_t>& signature() { return signature_; }
// Set the number of keys to use in the license(), encrypted_license()
// and key_array().
void set_num_keys(int num_keys) { num_keys_ = num_keys; }
// The current number of keys to use in the license(), encrypted_license()
// and key_array().
unsigned int num_keys() const { return num_keys_; }
// Set the size of the buffer used the encrypted license.
// Must be between sizeof(MessageData) and kMaxMessageSize.
void set_message_size(size_t size);
// The size of the encrypted message.
size_t message_size() { return message_size_; }
private:
// Generate mac and enc keys give the master key.
void DeriveKeys(const uint8_t* master_key,
const vector<uint8_t>& mac_key_context,
const vector<uint8_t>& enc_key_context);
// Internal utility function to derive key using CMAC-128
void DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
int counter, vector<uint8_t>* out);
bool open_;
bool forced_session_id_;
OEMCrypto_SESSION session_id_;
vector<uint8_t> mac_key_server_;
vector<uint8_t> mac_key_client_;
vector<uint8_t> enc_key_;
uint32_t nonce_;
RSA* public_rsa_;
vector<uint8_t> pst_report_buffer_;
MessageData license_;
struct PaddedMessageData : public MessageData {
uint8_t padding[kMaxMessageSize - sizeof(MessageData)];
} padded_message_;
size_t message_size_; // How much of the padded message to use.
OEMCrypto_KeyObject key_array_[kMaxNumKeys];
std::vector<uint8_t> signature_;
unsigned int num_keys_;
vector<uint8_t> encrypted_usage_entry_;
uint32_t usage_entry_number_;
string pst_;
// 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];
};
} // namespace wvoec
#endif // CDM_OEC_SESSION_UTIL_H_

465
test/oec_test_data.h Normal file
View File

@@ -0,0 +1,465 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Test data for OEMCrypto unit tests.
//
#ifndef CDM_OEC_TEST_DATA_H_
#define CDM_OEC_TEST_DATA_H_
#include <string>
#include "OEMCryptoCENC.h"
#include "wv_keybox.h"
namespace wvoec {
// These are test keyboxes. They will not be accepted by production systems.
// By using known keyboxes for these tests, the results for a given set of
// inputs to a test are predictable and can be compared to the actual results.
// The first keybox, kTestKeybox, with deviceID "TestKey01" is used for most of
// the tests. It should be loaded by OEMCrypto when OEMCrypto_LoadTestKeybox
// is called.
static const wvoec_mock::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).
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,
}
};
// These are old test keyboxes. The first keybox can be used to update an
// older OEMCrypto because it is the same keybox that was previously used in
// unit tests.
static const wvoec_mock::WidevineKeybox kValidKeybox01 = {
// Sample keybox used for test vectors
{
// deviceID
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey01
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
}, {
// key
0xfb, 0xda, 0x04, 0x89, 0xa1, 0x58, 0x16, 0x0e,
0xa4, 0x02, 0xe9, 0x29, 0xe3, 0xb6, 0x8f, 0x04,
}, {
// data
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1,
0x22, 0x67, 0x80, 0x53, 0x36, 0x21, 0x36, 0xbd,
0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4, 0xc2, 0xd8,
0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64,
0x6e, 0x58, 0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8,
0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a, 0x14, 0xa8,
0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64,
0x0b, 0xd2, 0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39,
}, {
// magic
0x6b, 0x62, 0x6f, 0x78,
}, {
// Crc
0x0a, 0x7a, 0x2c, 0x35,
}
};
static const wvoec_mock::WidevineKeybox kValidKeybox02 = {
// Sample keybox used for test vectors
{
// deviceID
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey02
0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
}, {
// key
0x76, 0x5d, 0xce, 0x01, 0x04, 0x89, 0xb3, 0xd0,
0xdf, 0xce, 0x54, 0x8a, 0x49, 0xda, 0xdc, 0xb6,
}, {
// data
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
0x92, 0x27, 0x0b, 0x1f, 0x1a, 0xd5, 0xc6, 0x93,
0x19, 0x3f, 0xaa, 0x74, 0x1f, 0xdd, 0x5f, 0xb4,
0xe9, 0x40, 0x2f, 0x34, 0xa4, 0x92, 0xf4, 0xae,
0x9a, 0x52, 0x39, 0xbc, 0xb7, 0x24, 0x38, 0x13,
0xab, 0xf4, 0x92, 0x96, 0xc4, 0x81, 0x60, 0x33,
0xd8, 0xb8, 0x09, 0xc7, 0x55, 0x0e, 0x12, 0xfa,
0xa8, 0x98, 0x62, 0x8a, 0xec, 0xea, 0x74, 0x8a,
0x4b, 0xfa, 0x5a, 0x9e, 0xb6, 0x49, 0x0d, 0x80,
}, {
// magic
0x6b, 0x62, 0x6f, 0x78,
}, {
// Crc
0x2a, 0x3b, 0x3e, 0xe4,
}
};
static const wvoec_mock::WidevineKeybox kValidKeybox03 = {
// Sample keybox used for test vectors
{
// deviceID
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey03
0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
}, {
// key
0x25, 0xe5, 0x2a, 0x02, 0x29, 0x68, 0x04, 0xa2,
0x92, 0xfd, 0x7c, 0x67, 0x0b, 0x67, 0x1f, 0x31,
}, {
// data
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
0xf4, 0x0a, 0x0e, 0xa2, 0x0a, 0x71, 0xd5, 0x92,
0xfa, 0xa3, 0x25, 0xc6, 0x4b, 0x76, 0xf1, 0x64,
0xf4, 0x60, 0xa0, 0x30, 0x72, 0x23, 0xbe, 0x03,
0xcd, 0xde, 0x7a, 0x06, 0xd4, 0x01, 0xeb, 0xdc,
0xe0, 0x50, 0xc0, 0x53, 0x0a, 0x50, 0xb0, 0x37,
0xe5, 0x05, 0x25, 0x0e, 0xa4, 0xc8, 0x5a, 0xff,
0x46, 0x6e, 0xa5, 0x31, 0xf3, 0xdd, 0x94, 0xb7,
0xe0, 0xd3, 0xf9, 0x04, 0xb2, 0x54, 0xb1, 0x64,
}, {
// magic
0x6b, 0x62, 0x6f, 0x78,
}, {
// Crc
0xa1, 0x99, 0x5f, 0x46,
}
};
// 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
};
} // namespace wvoec
#endif // CDM_OEC_TEST_DATA_H_

View File

@@ -0,0 +1,159 @@
#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 NULL;
}
return &(*pos);
}
// If force is true, we assert that the key loads successfully.
void SessionUtil::CreateWrappedRSAKeyFromKeybox(uint32_t allowed_schemes,
bool force) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(s.GenerateDerivedKeysFromKeybox(keybox_));
// Provisioning request would be signed by the client and verified by the
// server.
ASSERT_NO_FATAL_FAILURE(s.VerifyClientSignature());
struct RSAPrivateKeyMessage encrypted;
std::vector<uint8_t> signature;
ASSERT_NO_FATAL_FAILURE(
s.MakeRSACertificate(&encrypted, sizeof(encrypted),
&signature, allowed_schemes,
encoded_rsa_key_));
ASSERT_NO_FATAL_FAILURE(s.RewrapRSAKey(
encrypted, sizeof(encrypted), signature, &wrapped_rsa_key_, force));
// Verify that the clear key is not contained in the wrapped key.
// It should be encrypted.
ASSERT_EQ(NULL, find(wrapped_rsa_key_, encoded_rsa_key_));
}
// If force is true, we assert that the key loads successfully.
void SessionUtil::CreateWrappedRSAKeyFromOEMCert(
uint32_t allowed_schemes, bool force) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(s.LoadOEMCert());
s.GenerateNonce();
struct RSAPrivateKeyMessage encrypted;
std::vector<uint8_t> signature;
std::vector<uint8_t> message_key;
std::vector<uint8_t> encrypted_message_key;
s.GenerateRSASessionKey(&message_key, &encrypted_message_key);
ASSERT_NO_FATAL_FAILURE(
s.MakeRSACertificate(&encrypted, sizeof(encrypted), &signature,
allowed_schemes, encoded_rsa_key_, &message_key));
ASSERT_NO_FATAL_FAILURE(
s.RewrapRSAKey30(encrypted, encrypted_message_key,
&wrapped_rsa_key_, force));
// Verify that the clear key is not contained in the wrapped key.
// It should be encrypted.
ASSERT_EQ(NULL, find(wrapped_rsa_key_, encoded_rsa_key_));
}
// If force is true, we assert that the key loads successfully.
void SessionUtil::CreateWrappedRSAKey(uint32_t allowed_schemes,
bool force) {
switch (global_features.provisioning_method) {
case OEMCrypto_OEMCertificate:
CreateWrappedRSAKeyFromOEMCert(allowed_schemes, force);
break;
case OEMCrypto_Keybox:
CreateWrappedRSAKeyFromKeybox(allowed_schemes, force);
break;
default:
FAIL() << "Cannot generate wrapped RSA key if provision method = "
<< wvoec::ProvisioningMethodName(
global_features.provisioning_method);
}
}
void SessionUtil::InstallKeybox(const wvoec_mock::WidevineKeybox& keybox,
bool good) {
uint8_t wrapped[sizeof(wvoec_mock::WidevineKeybox)];
size_t length = sizeof(wvoec_mock::WidevineKeybox);
keybox_ = keybox;
ASSERT_EQ(
OEMCrypto_SUCCESS,
OEMCrypto_WrapKeybox(reinterpret_cast<const uint8_t*>(&keybox),
sizeof(keybox), wrapped, &length, NULL, 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;
/* Note: If you are upgrading from an older version, it may be easier to
* uncomment the following line. This uses the same test keybox as we
* used in older versions of this test.
*/
// keybox_ = kValidKeybox01;
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::EXISTING_TEST_KEYBOX:
// already has test keybox.
keybox_ = kTestKeybox;
break;
case DeviceFeatures::FORCE_TEST_KEYBOX:
keybox_ = kTestKeybox;
InstallKeybox(keybox_, true);
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::InstallTestSessionKeys(Session* s) {
if (global_features.uses_certificate) {
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(kSign_RSASSA_PSS, true));
}
// 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->GenerateDerivedKeysFromSessionKey());
} else { // Just uses keybox. Test keybox should already be installed.
ASSERT_NO_FATAL_FAILURE(
s->GenerateDerivedKeysFromKeybox(keybox_));
}
}
}

View File

@@ -0,0 +1,40 @@
#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 "OEMCryptoCENC.h"
namespace wvoec {
class SessionUtil {
public:
SessionUtil()
: encoded_rsa_key_(kTestRSAPKCS8PrivateKeyInfo2_2048,
kTestRSAPKCS8PrivateKeyInfo2_2048 +
sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048)) {}
// If force is true, we assert that the key loads successfully.
void CreateWrappedRSAKeyFromKeybox(uint32_t allowed_schemes, bool force);
// If force is true, we assert that the key loads successfully.
void CreateWrappedRSAKeyFromOEMCert(uint32_t allowed_schemes, bool force);
// If force is true, we assert that the key loads successfully.
void CreateWrappedRSAKey(uint32_t allowed_schemes, bool force);
void InstallKeybox(const wvoec_mock::WidevineKeybox& keybox, bool good);
void EnsureTestKeys();
void InstallTestSessionKeys(Session* s);
std::vector<uint8_t> encoded_rsa_key_;
std::vector<uint8_t> wrapped_rsa_key_;
wvoec_mock::WidevineKeybox keybox_;
};
} // namespace wvoec

5714
test/oemcrypto_test.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,151 @@
// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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 "OEMCryptoCENC.h"
namespace wvoec {
// These tests are required for LollyPop Android devices.
class OEMCryptoAndroidLMPTest : public ::testing::Test {
protected:
virtual void SetUp() { ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize()); }
virtual void TearDown() { 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());
}
}
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) {
if (OEMCrypto_Keybox == OEMCrypto_GetProvisioningMethod()) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_RewrapDeviceRSAKey(0, NULL, 0, NULL, 0, NULL, NULL, 0,
NULL, NULL, NULL));
} else {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_RewrapDeviceRSAKey30(0, NULL, NULL, 0, NULL, 0, NULL,
NULL, NULL));
}
}
TEST_F(OEMCryptoAndroidLMPTest, RSASignatureImplemented) {
ASSERT_NE(
OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_GenerateRSASignature(0, NULL, 0, NULL, NULL, kSign_RSASSA_PSS));
}
TEST_F(OEMCryptoAndroidLMPTest, GenericCryptoImplemented) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_Generic_Encrypt(0, NULL, 0, NULL,
OEMCrypto_AES_CBC_128_NO_PADDING, NULL));
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_Generic_Decrypt(0, NULL, 0, NULL,
OEMCrypto_AES_CBC_128_NO_PADDING, NULL));
ASSERT_NE(
OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_Generic_Sign(0, NULL, 0, OEMCrypto_HMAC_SHA256, NULL, NULL));
ASSERT_NE(
OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_Generic_Verify(0, NULL, 0, OEMCrypto_HMAC_SHA256, NULL, 0));
}
TEST_F(OEMCryptoAndroidLMPTest, SupportsUsageTable) {
ASSERT_TRUE(OEMCrypto_SupportsUsageTable());
}
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);
}
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());
}
}
TEST_F(OEMCryptoAndroidMNCTest, NumberOfSessionsImplemented) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_GetNumberOfOpenSessions(NULL));
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_GetMaxNumberOfSessions(NULL));
}
TEST_F(OEMCryptoAndroidMNCTest, QueryKeyControlImplemented) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_QueryKeyControl(0, NULL, 0, NULL, NULL));
}
// 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 Pi Android devices.
class OEMCryptoAndroidPiTest : public OEMCryptoAndroidOCTest {};
TEST_F(OEMCryptoAndroidPiTest, MinVersionNumber14) {
uint32_t version = OEMCrypto_APIVersion();
ASSERT_GE(version, 14u);
}
} // namespace wvoec

View File

@@ -0,0 +1,43 @@
#include <gtest/gtest.h>
#include <iostream>
#include "OEMCryptoCENC.h"
#include "log.h"
#include "oec_device_features.h"
#include "properties.h"
static void acknowledge_cast() {
std::cout
<< "==================================================================\n"
<< "= This device is expected to load x509 certs as a cast receiver. =\n"
<< "==================================================================\n";
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
wvcdm::Properties::Init();
wvcdm::g_cutoff = wvcdm::LOG_INFO;
bool is_cast_receiver = false;
bool force_load_test_keybox = false;
bool filter_tests = true;
for (int i = 0; i < argc; i++) {
if (!strcmp(argv[i], "--cast")) {
acknowledge_cast();
is_cast_receiver = true;
}
if (!strcmp(argv[i], "--force_load_test_keybox")) {
force_load_test_keybox = true;
}
if (!strcmp(argv[i], "--no_filter")) {
filter_tests = false;
}
}
wvoec::global_features.Initialize(is_cast_receiver, force_load_test_keybox);
// 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();
}