Files
android/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp
Jeff Tinker 1a8aa0dd05 Initial import of Widevine Common Encryption DRM engine
Builds libwvmdrmengine.so, which is loaded by the new
MediaDrm APIs to support playback of Widevine/CENC
protected content.

Change-Id: I6f57dd37083dfd96c402cb9dd137c7d74edc8f1c
2013-03-22 11:14:17 -07:00

1402 lines
50 KiB
C++

// Copyright 2013 Google Inc. All Rights Reserved.
//
// OEMCrypto unit tests
//
#include <arpa/inet.h> // TODO(fredgc): Add ntoh to wv_cdm_utilities.h
#include <gtest/gtest.h>
#include <stdint.h>
#include <sys/types.h>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include "OEMCryptoCENC.h"
#include "oemcrypto_key_mock.h"
#include "openssl/aes.h"
#include "openssl/cmac.h"
#include "openssl/hmac.h"
#include "openssl/rand.h"
#include "openssl/sha.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
#include "wv_keybox.h"
using namespace std;
namespace wvoec {
typedef struct {
uint8_t verification[4];
uint32_t duration;
uint32_t nonce;
uint32_t control_bits;
} KeyControlBlock;
const size_t kTestKeyIdLength = 12; // pick a length. any length.
typedef struct {
uint8_t key_id[kTestKeyIdLength];
uint8_t key_data[wvcdm::KEY_SIZE];
uint8_t key_iv[wvcdm::KEY_IV_SIZE];
uint8_t control_iv[wvcdm::KEY_IV_SIZE];
KeyControlBlock control;
} MessageKeyData;
template<unsigned int kNumberKeys>
struct MessageData {
MessageKeyData keys[kNumberKeys];
uint8_t mac_key_iv[wvcdm::KEY_IV_SIZE];
uint8_t mac_key[wvcdm::MAC_KEY_SIZE];
};
const wvoec_mock::WidevineKeybox kDefaultKeybox = {
// 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,
}
};
class OEMCryptoClientTest : public ::testing::Test {
protected:
class Session;
OEMCryptoClientTest() : alive_(false) {}
bool init() {
OEMCryptoResult result;
if (!alive_) {
result = OEMCrypto_Initialize();
alive_ = (OEMCrypto_SUCCESS == result);
}
return alive_;
}
bool terminate() {
OEMCryptoResult result;
result = OEMCrypto_Terminate();
if (OEMCrypto_SUCCESS == result) {
alive_ = false;
}
return !alive_;
}
void testSetUp() {
init();
}
void InstallKeybox(const wvoec_mock::WidevineKeybox& keybox) {
OEMCryptoResult sts;
uint8_t wrapped[sizeof(wvoec_mock::WidevineKeybox)];
size_t length = sizeof(wvoec_mock::WidevineKeybox);
sts = OEMCrypto_WrapKeybox(reinterpret_cast<const uint8_t*>(&keybox),
sizeof(keybox),
wrapped,
&length,
NULL, 0);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
sts = OEMCrypto_InstallKeybox(wrapped, sizeof(keybox));
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
}
void testTearDown() {
destroySessions();
terminate();
}
bool validateKeybox() {
OEMCryptoResult result;
result = OEMCrypto_IsKeyboxValid();
return (OEMCrypto_SUCCESS == result);
}
class Session {
public:
Session() : valid_(false), open_(false) {}
Session(string sname) : valid_(true), open_(false), sname_(sname),
mac_key_(wvcdm::MAC_KEY_SIZE),
enc_key_(wvcdm::KEY_SIZE) {}
bool isValid() { return valid_; }
bool isOpen() { return open_; }
bool successStatus() { return (OEMCrypto_SUCCESS == session_status_); }
OEMCryptoResult getStatus() { return session_status_; }
uint32_t getNonce() { return nonce_; }
uint32_t session_id() { return (uint32_t)session_id_; }
void set_session_id(uint32_t newsession) {
session_id_ = (OEMCrypto_SESSION)newsession;
}
void open() {
EXPECT_TRUE(valid_ && !open_);
session_status_ = OEMCrypto_OpenSession(&session_id_);
if (OEMCrypto_SUCCESS == session_status_) {
open_ = true;
}
}
void close() {
EXPECT_TRUE(valid_);
session_status_ = OEMCrypto_CloseSession(session_id_);
if (OEMCrypto_SUCCESS == session_status_) {
open_ = false;
}
}
bool GenerateNonce(uint32_t* nonce) {
OEMCryptoResult sts;
sts = OEMCrypto_GenerateNonce(session_id(), nonce);
return (OEMCrypto_SUCCESS == sts);
}
bool GenerateDerivedKeys() {
if( !GenerateNonce(&nonce_) ) {
cout << "Generate Nonce failed." << endl;
return false;
}
vector<uint8_t> mac_context = wvcdm::a2b_hex(
"41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff"
"de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873"
"4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a"
"230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635"
"34333231180120002a0c31383836373837343035000000000100");
vector<uint8_t> enc_context = wvcdm::a2b_hex(
"454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95"
"c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb"
"e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408"
"0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231"
"180120002a0c31383836373837343035000000000080");
OEMCryptoResult sts;
sts = OEMCrypto_GenerateDerivedKeys(
session_id(),
&mac_context[0], mac_context.size(),
&enc_context[0], enc_context.size());
if (sts != OEMCrypto_SUCCESS) {
cout << "GenerateDerivedKeys: Failed OEMCrypto_GenerateDerivedKeys with "
<< static_cast<long unsigned int>(sts) << endl;
}
mac_key_ = wvcdm::a2b_hex(
"9D41F0A77A76E071841C33B06104D106641421E651FBE55F0AED453CDA7713AC");
enc_key_ = wvcdm::a2b_hex("D0BFC35DA9E33436E81C4229E78CB9F4");
return (OEMCrypto_SUCCESS == sts);
}
bool LoadTestKeys() {
if (!GenerateDerivedKeys()) {
cout << "LoadTestKeys: Failed GenerateDerivedKeys" << endl;
return false;
}
return CreateAndLoadKeyMessage();
}
bool CertificateProvision(vector<uint8_t>* wrappedKey) {
vector<uint8_t> context = wvcdm::a2b_hex(
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"38373430350000");
OEMCryptoResult sts;
// Generate signature
size_t gen_signature_length = 0;
sts = OEMCrypto_GenerateSignature(session_id(), &context[0],
context.size(), NULL,
&gen_signature_length);
uint8_t* gen_signature = new uint8_t[gen_signature_length];
sts = OEMCrypto_GenerateSignature(session_id(), &context[0],
context.size(), gen_signature,
&gen_signature_length);
if (sts != OEMCrypto_SUCCESS) {
return false;
}
// Rewrap Canned Response
// In the real world, the signature above would just have been used to
// contact the certificate provisioning server to get this response.
// TODO: This is not a valid test vector
vector<uint8_t> message = wvcdm::a2b_hex(
"000000001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637");
memcpy(&message[0], &nonce_, sizeof(uint32_t));
uint32_t* messageNonce = reinterpret_cast<uint32_t*>(&message[0]);
uint8_t* key = &message[32];
size_t key_length = 7;
uint8_t* key_iv = &message[64];
// TODO: In practice, we need to generate a signature here after inserting
// the right nonce into the message.
vector<uint8_t> signature = wvcdm::a2b_hex(
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840");
size_t wrapped_key_length;
sts = OEMCrypto_RewrapDeviceRSAKey(session_id(), &message[0],
message.size(), &signature[0],
signature.size(), messageNonce, key,
key_length, key_iv, NULL,
&wrapped_key_length);
wrappedKey->clear();
wrappedKey->resize(wrapped_key_length);
sts = OEMCrypto_RewrapDeviceRSAKey(session_id(), &message[0],
message.size(), &signature[0],
signature.size(), messageNonce, key,
key_length, key_iv,
&(wrappedKey->front()),
&wrapped_key_length);
delete[] gen_signature;
return (sts == OEMCrypto_SUCCESS);
}
bool CertificateLicense() {
OEMCryptoResult sts;
vector<uint8_t> wrappedKey;
if (!CertificateProvision(&wrappedKey)) {
return false;
}
// Load the Wrapped Key
sts = OEMCrypto_LoadDeviceRSAKey(session_id(), &wrappedKey[0],
wrappedKey.size());
if (sts != OEMCrypto_SUCCESS) {
return false;
}
// Sign a Message
vector<uint8_t> licenseRequest = wvcdm::a2b_hex(
"ba711a51e0c4c995440c28057f7f5e2f2e9c3a1edeb7549aca21e6050b059ac8"
"6ad64ec1a528eef17b4f5ce781af488d50fb0e60d04b48c78d55847a4e14243c"
"0023c553b46a2f53995870f351295e3aa2237f153f1415e817ad23e662e547b1"
"4708b303473813f93ee192353ff22bee54dd0f558bbe4b61b75b387bc310e9d6"
"8ff2cb3482689c0688570809b756dba4c2697be3132a2da782aa877ed64d8c7d"
"506525a382bad14d7e797c256c3617c22fa4165482b9742e9b54ffb6c52eda1d");
size_t signature_length = 0;
sts = OEMCrypto_GenerateRSASignature(session_id(), &licenseRequest[0],
licenseRequest.size(), NULL,
&signature_length);
uint8_t* signature = new uint8_t[signature_length];
sts = OEMCrypto_GenerateRSASignature(session_id(), &licenseRequest[0],
licenseRequest.size(), signature,
&signature_length);
if (sts != OEMCrypto_SUCCESS) {
return false;
}
// Rewrap Canned Response
// In the real world, the signature above would just have been used to contact
// the license server to get this response.
// TODO: This is not a valid test vector
vector<uint8_t> sessionKey = wvcdm::a2b_hex(
"6fa479c731d2770b6a61a5d1420bb9d1");
vector<uint8_t> mac_context = wvcdm::a2b_hex(
"41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff"
"de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873"
"4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a"
"230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635"
"34333231180120002a0c31383836373837343035000000000100");
vector<uint8_t> enc_context = wvcdm::a2b_hex(
"454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95"
"c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb"
"e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408"
"0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231"
"180120002a0c31383836373837343035000000000080");
sts = OEMCrypto_DeriveKeysFromSessionKey(session_id(),
&sessionKey[0],
sessionKey.size(),
&mac_context[0],
mac_context.size(),
&enc_context[0],
enc_context.size());
if (sts != OEMCrypto_SUCCESS) {
return false;
}
delete[] signature;
return CreateAndLoadKeyMessage();
}
template<unsigned int kNumberKeys>
void fill_simple_message(MessageData<kNumberKeys>* data) {
OEMCrypto_GetRandom(data->mac_key_iv, wvcdm::KEY_IV_SIZE);
OEMCrypto_GetRandom(data->mac_key, wvcdm::KEY_IV_SIZE);
for (unsigned int i = 0; i < kNumberKeys; i++) {
memset(data->keys[i].key_id, i, kTestKeyIdLength);
OEMCrypto_GetRandom(data->keys[i].key_data, wvcdm::KEY_SIZE);
OEMCrypto_GetRandom(data->keys[i].key_iv, wvcdm::KEY_IV_SIZE);
OEMCrypto_GetRandom(data->keys[i].control_iv, wvcdm::KEY_IV_SIZE);
memcpy(data->keys[i].control.verification, "kctl", 4);
data->keys[i].control.duration = htonl(0);
data->keys[i].control.nonce = htonl(nonce_);
data->keys[i].control.control_bits = htonl(0);
}
// For the canned decryption content, The first key is:
vector<uint8_t> key = wvcdm::a2b_hex("39AD33E5719656069F9EDE9EBBA7A77D");
memcpy(data->keys[0].key_data, &key[0], key.size());
}
template<unsigned int kNumberKeys>
void encrypt_message(const MessageData<kNumberKeys>& data,
MessageData<kNumberKeys>* encrypted) {
*encrypted = data;
uint8_t iv_buffer[16];
memcpy(iv_buffer, &data.mac_key_iv[0], wvcdm::KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
AES_cbc_encrypt(&data.mac_key[0], &encrypted->mac_key[0],
wvcdm::MAC_KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
for (unsigned int i = 0; i < kNumberKeys; i++) {
memcpy(iv_buffer, &data.keys[i].control_iv[0], wvcdm::KEY_IV_SIZE);
AES_set_encrypt_key(&data.keys[i].key_data[0], 128, &aes_key);
AES_cbc_encrypt(reinterpret_cast<const uint8_t*>(&data.keys[i].control),
reinterpret_cast<uint8_t*>(&encrypted->keys[i].control),
wvcdm::KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
memcpy(iv_buffer, &data.keys[i].key_iv[0], wvcdm::KEY_IV_SIZE);
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
AES_cbc_encrypt(&data.keys[i].key_data[0], &encrypted->keys[i].key_data[0],
wvcdm::KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
}
}
template<unsigned int kNumberKeys>
void sign_message(MessageData<kNumberKeys> data,
std::vector<uint8_t>* signature) {
signature->resize(SHA256_DIGEST_LENGTH);
unsigned int md_len = SHA256_DIGEST_LENGTH;
HMAC(EVP_sha256(), &mac_key_[0], SHA256_DIGEST_LENGTH,
reinterpret_cast<uint8_t*>(&data), sizeof(data),
&(signature->front()), &md_len);
}
template<unsigned int kNumberKeys>
void fill_key_array(const MessageData<kNumberKeys>& data,
OEMCrypto_KeyObject* key_array) {
for (unsigned int i = 0; i < kNumberKeys; i++) {
key_array[i].key_id = data.keys[i].key_id;
key_array[i].key_id_length = kTestKeyIdLength;
key_array[i].key_data_iv = data.keys[i].key_iv;
key_array[i].key_data = data.keys[i].key_data;
key_array[i].key_control_iv = data.keys[i].control_iv;
key_array[i].key_control
= reinterpret_cast<const uint8_t*>(&data.keys[i].control);
}
}
private:
bool CreateAndLoadKeyMessage() {
const unsigned int num_keys = 3;
MessageData<num_keys> data;
fill_simple_message(&data);
MessageData<num_keys> encrypted;
encrypt_message(data, &encrypted);
std::vector<uint8_t> signature;
sign_message(encrypted, &signature);
OEMCrypto_KeyObject key_array[num_keys];
const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(&encrypted);
fill_key_array(encrypted, key_array);
OEMCryptoResult sts = OEMCrypto_LoadKeys(
session_id(),
message_ptr, sizeof(encrypted),
&signature[0], signature.size(),
encrypted.mac_key_iv,
encrypted.mac_key,
num_keys, key_array);
if (sts != OEMCrypto_SUCCESS) {
cout << "LoadTestKeys: Failed OEMCrypto_LoadKeys with "
<< static_cast<long unsigned int>(sts) << endl;
}
return sts == OEMCrypto_SUCCESS;
}
bool valid_;
bool open_;
string sname_;
OEMCrypto_SESSION session_id_;
OEMCryptoResult session_status_;
vector<uint8_t> mac_key_;
vector<uint8_t> enc_key_;
uint32_t nonce_;
};
static Session badSession;
Session& findSession(string sname) {
map<string, Session>::iterator it = _sessions.find(sname);
if (it != _sessions.end()) {
return it->second;
}
return badSession;
}
Session& createSession(string sname) {
Session temp(sname);
_sessions.insert(pair<string, Session>(sname, temp));
return findSession(sname);
}
bool destroySession(string sname) {
Session& temp = findSession(sname);
if (!temp.isValid()) {
return false;
}
_sessions.erase(sname);
return true;
}
bool destroySessions() {
_sessions.clear();
return true;
}
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);
}
private:
bool alive_;
map<string, Session> _sessions;
};
OEMCryptoClientTest::Session OEMCryptoClientTest::badSession;
///////////////////////////////////////////////////
// initialization tests
///////////////////////////////////////////////////
TEST_F(OEMCryptoClientTest, NormalInitTermination) {
bool success;
success = init();
EXPECT_TRUE(success);
success = terminate();
ASSERT_TRUE(success);
}
///////////////////////////////////////////////////
// Keybox Tests
///////////////////////////////////////////////////
TEST_F(OEMCryptoClientTest, KeyboxValid) {
bool success;
success = init();
EXPECT_TRUE(success);
success = validateKeybox();
ASSERT_TRUE(success);
success = terminate();
ASSERT_TRUE(success);
}
TEST_F(OEMCryptoClientTest, NormalGetDeviceId) {
testSetUp();
OEMCryptoResult sts;
uint8_t dev_id[128];
size_t dev_id_len = 128;
sts = OEMCrypto_GetDeviceID(dev_id, &dev_id_len);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// cout << "NormalGetDeviceId: dev_id = " << dev_id
// << " len = " << dev_id_len << endl;
testTearDown();
}
TEST_F(OEMCryptoClientTest, GetDeviceIdShortBuffer) {
testSetUp();
OEMCryptoResult sts;
uint8_t dev_id[128];
uint32_t req_len = 11;
for (int i = 0; i < 128; ++i) {
dev_id[i] = 0x55;
}
dev_id[127] = '\0';
size_t dev_id_len = req_len;
sts = OEMCrypto_GetDeviceID(dev_id, &dev_id_len);
// cout << "GetDeviceIdShortBuffer: sts = " << (int)sts << " request = "
// << req_len << " required = " << dev_id_len << endl;
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
// On short buffer error, function should return minimum buffer length
ASSERT_TRUE(dev_id_len > req_len);
// cout << "NormalGetDeviceId: dev_id = " << dev_id
// << " len = " << dev_id_len << endl;
testTearDown();
}
TEST_F(OEMCryptoClientTest, NormalGetKeyData) {
testSetUp();
OEMCryptoResult sts;
uint8_t key_data[256];
uint32_t req_len = 256;
size_t key_data_len = req_len;
sts = OEMCrypto_GetKeyData(key_data, &key_data_len);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
testTearDown();
}
///////////////////////////////////////////////////
// Session Tests
///////////////////////////////////////////////////
TEST_F(OEMCryptoClientTest, NormalSessionOpenClose) {
Session& s = createSession("ONE");
testSetUp();
s.open();
ASSERT_TRUE(s.successStatus());
ASSERT_TRUE(s.isOpen());
s.close();
ASSERT_TRUE(s.successStatus());
ASSERT_FALSE(s.isOpen());
testTearDown();
}
TEST_F(OEMCryptoClientTest, TwoSessionsOpenClose) {
Session& s1 = createSession("ONE");
Session& s2 = createSession("TWO");
testSetUp();
s1.open();
ASSERT_TRUE(s1.successStatus());
ASSERT_TRUE(s1.isOpen());
s2.open();
ASSERT_TRUE(s2.successStatus());
ASSERT_TRUE(s2.isOpen());
s1.close();
ASSERT_TRUE(s1.successStatus());
ASSERT_FALSE(s1.isOpen());
s2.close();
ASSERT_TRUE(s2.successStatus());
ASSERT_FALSE(s2.isOpen());
testTearDown();
}
TEST_F(OEMCryptoClientTest, EightSessionsOpenClose) {
Session& s1 = createSession("ONE");
Session& s2 = createSession("TWO");
Session& s3 = createSession("THREE");
Session& s4 = createSession("FOUR");
Session& s5 = createSession("FIVE");
Session& s6 = createSession("SIX");
Session& s7 = createSession("SEVEN");
Session& s8 = createSession("EIGHT");
testSetUp();
s1.open();
ASSERT_TRUE(s1.successStatus());
ASSERT_TRUE(s1.isOpen());
s2.open();
ASSERT_TRUE(s2.successStatus());
ASSERT_TRUE(s2.isOpen());
s3.open();
ASSERT_TRUE(s3.successStatus());
ASSERT_TRUE(s3.isOpen());
s4.open();
ASSERT_TRUE(s4.successStatus());
ASSERT_TRUE(s4.isOpen());
s5.open();
ASSERT_TRUE(s5.successStatus());
ASSERT_TRUE(s5.isOpen());
s6.open();
ASSERT_TRUE(s6.successStatus());
ASSERT_TRUE(s6.isOpen());
s7.open();
ASSERT_TRUE(s7.successStatus());
ASSERT_TRUE(s7.isOpen());
s8.open();
ASSERT_TRUE(s8.successStatus());
ASSERT_TRUE(s8.isOpen());
s1.close();
ASSERT_TRUE(s1.successStatus());
ASSERT_FALSE(s1.isOpen());
s8.close();
ASSERT_TRUE(s8.successStatus());
ASSERT_FALSE(s8.isOpen());
s3.close();
ASSERT_TRUE(s3.successStatus());
ASSERT_FALSE(s3.isOpen());
s6.close();
ASSERT_TRUE(s6.successStatus());
ASSERT_FALSE(s6.isOpen());
s5.close();
ASSERT_TRUE(s5.successStatus());
ASSERT_FALSE(s5.isOpen());
s4.close();
ASSERT_TRUE(s4.successStatus());
ASSERT_FALSE(s4.isOpen());
s7.close();
ASSERT_TRUE(s7.successStatus());
ASSERT_FALSE(s7.isOpen());
s2.close();
ASSERT_TRUE(s2.successStatus());
ASSERT_FALSE(s2.isOpen());
testTearDown();
}
///////////////////////////////////////////////////
// AddKey Tests
///////////////////////////////////////////////////
TEST_F(OEMCryptoClientTest, GenerateNonce) {
Session& s = createSession("ONE");
testSetUp();
s.open();
uint32_t nonce;
ASSERT_TRUE(s.GenerateNonce(&nonce));
std::cout << "GenerateNonce:: nonce=" << nonce << std::endl;
s.close();
ASSERT_TRUE(s.successStatus());
ASSERT_FALSE(s.isOpen());
testTearDown();
}
TEST_F(OEMCryptoClientTest, GenerateTwoNonces) {
Session& s = createSession("ONE");
testSetUp();
s.open();
uint32_t nonce1;
uint32_t nonce2;
ASSERT_TRUE(s.GenerateNonce(&nonce1));
ASSERT_TRUE(s.GenerateNonce(&nonce2));
std::cout << "GenerateNonce:: nonce1=" << nonce1 << std::endl;
std::cout << "GenerateNonce:: nonce2=" << nonce2 << std::endl;
ASSERT_TRUE(nonce1 != nonce2);
s.close();
ASSERT_TRUE(s.successStatus());
ASSERT_FALSE(s.isOpen());
testTearDown();
}
TEST_F(OEMCryptoClientTest, GenerateDerivedKeys) {
Session& s = createSession("ONE");
testSetUp();
s.open();
ASSERT_TRUE(s.GenerateDerivedKeys());
s.close();
ASSERT_TRUE(s.successStatus());
ASSERT_FALSE(s.isOpen());
testTearDown();
}
TEST_F(OEMCryptoClientTest, GenerateSignature) {
Session& s = createSession("ONE");
testSetUp();
s.open();
ASSERT_TRUE(s.GenerateDerivedKeys());
vector<uint8_t> context = wvcdm::a2b_hex(
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"38373430350000");
static const uint32_t SignatureBufferMaxLength = 256;
uint8_t signature[SignatureBufferMaxLength];
size_t signature_length = SignatureBufferMaxLength;
OEMCryptoResult sts;
sts = OEMCrypto_GenerateSignature(
s.session_id(),
&context[0], context.size(), signature, &signature_length);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
static const uint32_t SignatureExpectedLength = 32;
ASSERT_EQ(signature_length, SignatureExpectedLength);
std::string expected_signature =
"281C3ECC8BD1CAFA5786329471043A388E04AF97B3133D9A8F9B102FBD3CAF1E";
ASSERT_EQ(expected_signature, wvcdm::HexEncode(signature, signature_length));
s.close();
ASSERT_TRUE(s.successStatus());
ASSERT_FALSE(s.isOpen());
testTearDown();
}
// Define CAN_INSTALL_KEYBOX if you are compiling with the reference
// implementation of OEMCrypto, or if your version of OEMCrypto supports
// OEMCrypto_InstallKeybox and OEwith a clear keybox.
// The Below tests are based on a specific keybox which is installed for testing.
#if defined(CAN_INSTALL_KEYBOX)
TEST_F(OEMCryptoClientTest, LoadKeyNoNonce) {
testSetUp();
InstallKeybox(kDefaultKeybox);
Session& s = createSession("ONE");
s.open();
ASSERT_TRUE(s.GenerateDerivedKeys());
ASSERT_TRUE(s.LoadTestKeys());
s.close();
testTearDown();
}
TEST_F(OEMCryptoClientTest, LoadKeyWithNonce) {
testSetUp();
InstallKeybox(kDefaultKeybox);
Session& s = createSession("ONE");
s.open();
ASSERT_TRUE(s.GenerateDerivedKeys());
const unsigned int num_keys = 3;
MessageData<num_keys> data;
s.fill_simple_message(&data);
data.keys[0].control.control_bits = wvoec_mock::kControlNonceEnabled;
data.keys[1].control.control_bits = wvoec_mock::kControlNonceEnabled;
data.keys[2].control.control_bits = wvoec_mock::kControlNonceEnabled;
MessageData<num_keys> encrypted;
s.encrypt_message(data, &encrypted);
std::vector<uint8_t> signature;
s.sign_message(encrypted, &signature);
OEMCrypto_KeyObject key_array[num_keys];
const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(&encrypted);
s.fill_key_array(encrypted, key_array);
OEMCryptoResult sts = OEMCrypto_LoadKeys(
s.session_id(),
message_ptr, sizeof(encrypted),
&signature[0], signature.size(),
encrypted.mac_key_iv,
encrypted.mac_key,
num_keys, key_array);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
s.close();
testTearDown();
}
TEST_F(OEMCryptoClientTest, LoadKeyWithBadNonce) {
testSetUp();
InstallKeybox(kDefaultKeybox);
Session& s = createSession("ONE");
s.open();
ASSERT_TRUE(s.GenerateDerivedKeys());
const unsigned int num_keys = 3;
MessageData<num_keys> data;
s.fill_simple_message(&data);
data.keys[0].control.control_bits = wvoec_mock::kControlNonceEnabled;
data.keys[1].control.control_bits = wvoec_mock::kControlNonceEnabled;
data.keys[2].control.control_bits = wvoec_mock::kControlNonceEnabled;
data.keys[1].control.nonce = 42; // This one is bad.
MessageData<num_keys> encrypted;
s.encrypt_message(data, &encrypted);
std::vector<uint8_t> signature;
s.sign_message(encrypted, &signature);
OEMCrypto_KeyObject key_array[num_keys];
const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(&encrypted);
s.fill_key_array(encrypted, key_array);
OEMCryptoResult sts = OEMCrypto_LoadKeys(
s.session_id(),
message_ptr, sizeof(encrypted),
&signature[0], signature.size(),
encrypted.mac_key_iv,
encrypted.mac_key,
num_keys, key_array);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
s.close();
testTearDown();
}
TEST_F(OEMCryptoClientTest, LoadKeysBadSignature) {
testSetUp();
InstallKeybox(kDefaultKeybox);
Session& s = createSession("ONE");
s.open();
ASSERT_TRUE(s.GenerateDerivedKeys());
const unsigned int num_keys = 3;
MessageData<num_keys> data;
s.fill_simple_message(&data);
MessageData<num_keys> encrypted;
s.encrypt_message(data, &encrypted);
std::vector<uint8_t> signature;
s.sign_message(encrypted, &signature);
OEMCrypto_KeyObject key_array[num_keys];
const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(&encrypted);
s.fill_key_array(encrypted, key_array);
signature[0] = 42; // Bad signature.
OEMCryptoResult sts = OEMCrypto_LoadKeys(
s.session_id(),
message_ptr, sizeof(encrypted),
&signature[0], signature.size(),
encrypted.mac_key_iv,
encrypted.mac_key,
num_keys, key_array);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
s.close();
testTearDown();
}
TEST_F(OEMCryptoClientTest, LoadKeysWithNoDerivedKeys) {
testSetUp();
InstallKeybox(kDefaultKeybox);
Session& s = createSession("ONE");
s.open();
// ASSERT_TRUE(s.GenerateDerivedKeys());
const unsigned int num_keys = 3;
MessageData<num_keys> data;
s.fill_simple_message(&data);
MessageData<num_keys> encrypted;
s.encrypt_message(data, &encrypted);
std::vector<uint8_t> signature;
s.sign_message(encrypted, &signature);
OEMCrypto_KeyObject key_array[num_keys];
const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(&encrypted);
s.fill_key_array(encrypted, key_array);
OEMCryptoResult sts = OEMCrypto_LoadKeys(
s.session_id(),
message_ptr, sizeof(encrypted),
&signature[0], signature.size(),
encrypted.mac_key_iv,
encrypted.mac_key,
num_keys, key_array);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
s.close();
testTearDown();
}
///////////////////////////////////////////////////
// Decrypt Tests
///////////////////////////////////////////////////
TEST_F(OEMCryptoClientTest, Decrypt) {
OEMCryptoResult sts;
testSetUp();
InstallKeybox(kDefaultKeybox);
Session& s = createSession("ONE");
s.open();
ASSERT_TRUE(s.LoadTestKeys());
// Select the key (from fill_simple_message)
vector<uint8_t> keyId = wvcdm::a2b_hex("000000000000000000000000");
sts = OEMCrypto_SelectKey(s.session_id(), &keyId[0], keyId.size());
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// Set up our expected input and output
vector<uint8_t> encryptedData = wvcdm::a2b_hex(
"ec261c115f9d5cda1d5cc7d33c4e37362d1397c89efdd1da5f0065c4848b0462"
"337ba14693735203c9b4184e362439c0cea5e5d1a628425eddf8a6bf9ba901ca"
"46f5a9fd973cffbbe3c276af9919e2e8f6f3f420538b7a0d6dc41487874d96b8"
"efaedb45a689b91beb8c20d36140ad467d9d620b19a5fc6f223b57e0e6a7f913"
"00fd899e5e1b89963e83067ca0912aa5b79df683e2530b55a9645be341bc5f07"
"cffc724790af635c959e2644e51ba7f23bae710eb55a1f2f4e060c3c1dd1387c"
"74415dc880492dd1d5b9ecf3f01de48a44baeb4d3ea5cc4f8d561d0865afcabb"
"fc14a9ab9647e6e31adabb72d792f0c9ba99dc3e9205657d28fc7771d64e6d4b");
vector<uint8_t> encryptionIv = wvcdm::a2b_hex(
"719dbcb253b2ec702bb8c1b1bc2f3bc6");
vector<uint8_t> unencryptedData = wvcdm::a2b_hex(
"19ef4361e16e6825b336e2012ad8ffc9ce176ab2256e1b98aa15b7877bd8c626"
"fa40b2e88373457cbcf4f1b4b9793434a8ac03a708f85974cff01bddcbdd7a8e"
"e33fd160c1d5573bfd8104efd23237edcf28205c3673920553f8dd5e916604b0"
"1082345181dceeae5ea39d829c7f49e1850c460645de33c288723b7ae3d91a17"
"a3f04195cd1945ba7b0f37fef7e82368be30f04365d877766f6d56f67d22a244"
"ef2596d3053f657c1b5d90b64e11797edf1c198a23a7bfc20e4d44c74ae41280"
"a8317f443255f4020eda850ff0954e308f53a634cbce799ae58911bc59ccd6a5"
"de2ac53ee0fa7ea15fc692cc892acc0090865dc57becacddf362a092dfd3040b");
// Describe the output
uint8_t outputBuffer[256];
OEMCrypto_DestBufferDesc destBuffer;
destBuffer.type = OEMCrypto_BufferType_Clear;
destBuffer.buffer.clear.address = outputBuffer;
destBuffer.buffer.clear.max_length = sizeof(outputBuffer);
// Decrypt the data
sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0],
encryptedData.size(), true, &encryptionIv[0], 0,
&destBuffer);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer,
unencryptedData.size()));
s.close();
testTearDown();
}
TEST_F(OEMCryptoClientTest, DecryptWithOffset) {
OEMCryptoResult sts;
testSetUp();
InstallKeybox(kDefaultKeybox);
Session& s = createSession("ONE");
s.open();
ASSERT_TRUE(s.LoadTestKeys());
// Select the key (from fill_simple_message)
vector<uint8_t> keyId = wvcdm::a2b_hex("000000000000000000000000");
sts = OEMCrypto_SelectKey(s.session_id(),
&keyId[0],
keyId.size());
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// Set up our expected input and output
vector<uint8_t> encryptedData = wvcdm::a2b_hex(
"c17055d4e3ab8e892b40ca2deed7cd46b406cd41d50f23d5877b36"
"ad351887df2b3774dc413904afd958ba766cc6ab51a3ffd8f845296c5d8326ee"
"39c9d0fec79885515e6b8a12911831d9fb158ca2fd3dfcfcf228741a63734685"
"8dffc30f5871260c5cef8be61cfa08b191c837901f077046664c0c56db81d412"
"98b59e5655cd94871c3c226dc3565144297f1459cddba069d5d2d6206cfd5798"
"eda4b82e01a9966d48984d6ef3fbd326ba0f6fcbe52c95786d478c2f33398c62"
"ae5210c7472d7d8dc7d12f981679f4ea9793736f354747ef14165367b94e07fc"
"4bcc7bd14746304fea100dc6465ab51241355bb19e6c2cfb2bb6bbf709765d13");
vector<uint8_t> encryptionIv = wvcdm::a2b_hex(
"c09454479a280829c946df3c22f25539");
vector<uint8_t> unencryptedData = wvcdm::a2b_hex(
"f344d9cfe336c94cf4e3ea9e3446d1427bc02d2debe6dec5b272b8"
"a4004b696c4b37e01d7418510abf32bb071f9a4bc0d2ad7e874b648e50bd0e4f"
"7085b70bf9ad2c7f37025dd45f93e90304739b1ce098a52e7b99a90f92544a9b"
"dca6f49e0006c80a0cfa018600523ad30e483141fe720d045394815d5c875ad4"
"b4387b8d09b6119bd0943e51b0b9103034496b3a83ba593f79baa188aeb6e08f"
"f6475933e9ce1bb95fbb526424e7966e25830c20da73c65c6fbff110b08e4def"
"eae94f98296770275b0d738207a8217cd6118f6ebc6e393428f2268cfedf800e"
"a7ebc606471b9a9dfccd1589e86d88fde508261eaf190efd20554ce9e14ff3c9");
// Describe the output
uint8_t outputBuffer[256];
OEMCrypto_DestBufferDesc destBuffer;
destBuffer.type = OEMCrypto_BufferType_Clear;
destBuffer.buffer.clear.address = outputBuffer;
destBuffer.buffer.clear.max_length = sizeof(outputBuffer);
// Decrypt the data
sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0],
encryptedData.size(), true, &encryptionIv[0], 5,
&destBuffer);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer,
unencryptedData.size()));
s.close();
testTearDown();
}
TEST_F(OEMCryptoClientTest, DecryptUnencrypted) {
OEMCryptoResult sts;
testSetUp();
InstallKeybox(kDefaultKeybox);
Session& s = createSession("ONE");
s.open();
ASSERT_TRUE(s.LoadTestKeys());
// Select the key (from fill_simple_message)
vector<uint8_t> keyId = wvcdm::a2b_hex("000000000000000000000000");
sts = OEMCrypto_SelectKey(s.session_id(), &keyId[0], keyId.size());
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// Set up our expected input and output
vector<uint8_t> unencryptedData = wvcdm::a2b_hex(
"1558497b6d994be343ed1c6d6313e0537b843e9a9c0836d1e83fe33154191ce9"
"a14d8d95bebaddc03bd471827170f527c0a166b9068b273d1bc57fbb13975ee4"
"f6b9a31743da6c447acbb712e81b13eddfd4e96c76010ac9b8aa1b6b3152b0fc"
"39ad33e5719656069f9ede9ebba7a77dd2e2074eec5c1b7ffc427a6f1be168f0"
"b5857713a44623862c903284bc53417e23c65602b52c1cb699e8352453eb9698"
"0b31459b90c26c907b549c1ab293725e414d4e45f5b30af7a55f95499a7dc89f"
"7d13ba90b34aef6b49484b0701bf96ea8b660c24bb4e92a2d1c43beb434fa386"
"1071380388799ac31d79285f5817687ed3e2eeb73a30744e77b757686c9ba5ad");
vector<uint8_t> encryptionIv = wvcdm::a2b_hex(
"49fc3efaaf614ed81d595847b928edd0");
// Describe the output
uint8_t outputBuffer[256];
OEMCrypto_DestBufferDesc destBuffer;
destBuffer.type = OEMCrypto_BufferType_Clear;
destBuffer.buffer.clear.address = outputBuffer;
destBuffer.buffer.clear.max_length = sizeof(outputBuffer);
// Decrypt the data
sts = OEMCrypto_DecryptCTR(s.session_id(), &unencryptedData[0],
unencryptedData.size(), false, &encryptionIv[0], 0,
&destBuffer);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer,
unencryptedData.size()));
s.close();
testTearDown();
}
///////////////////////////////////////////////////
// Certificate Root of Trust Tests
///////////////////////////////////////////////////
TEST_F(OEMCryptoClientTest, CertificateProvision) {
OEMCryptoResult sts;
testSetUp();
InstallKeybox(kDefaultKeybox);
Session& s = createSession("ONE");
s.open();
ASSERT_TRUE(s.GenerateDerivedKeys());
uint32_t nonce = s.getNonce();
vector<uint8_t> context = wvcdm::a2b_hex(
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"38373430350000");
// Generate signature
size_t gen_signature_length = 0;
sts = OEMCrypto_GenerateSignature(s.session_id(), &context[0], context.size(),
NULL, &gen_signature_length);
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
ASSERT_EQ(static_cast<size_t>(256), gen_signature_length);
uint8_t* gen_signature = new uint8_t[gen_signature_length];
sts = OEMCrypto_GenerateSignature(s.session_id(), &context[0], context.size(),
gen_signature, &gen_signature_length);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// Rewrap Canned Response
// In the real world, the signature above would just have been used to
// contact the certificate provisioning server to get this response.
// TODO: This is not a valid test vector
vector<uint8_t> message = wvcdm::a2b_hex(
"000000001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637");
memcpy(&message[0], &nonce, sizeof(uint32_t));
uint32_t* messageNonce = reinterpret_cast<uint32_t*>(&message[0]);
uint8_t* key = &message[32];
size_t key_length = 7;
uint8_t* key_iv = &message[64];
// TODO: In practice, we need to generate a signature here after inserting
// the right nonce into the message.
vector<uint8_t> signature = wvcdm::a2b_hex(
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840");
size_t wrapped_key_length;
sts = OEMCrypto_RewrapDeviceRSAKey(s.session_id(), &message[0],
message.size(), &signature[0],
signature.size(), messageNonce, key,
key_length, key_iv, NULL,
&wrapped_key_length);
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
ASSERT_NE(static_cast<size_t>(0), wrapped_key_length);
vector<uint8_t> wrapped_key;
wrapped_key.resize(wrapped_key_length);
sts = OEMCrypto_RewrapDeviceRSAKey(s.session_id(), &message[0],
message.size(), &signature[0],
signature.size(), messageNonce, key,
key_length, key_iv, &wrapped_key[0],
&wrapped_key_length);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// TODO: This is not a valid test vector
vector<uint8_t> clear_key = wvcdm::a2b_hex(
"1558497b6d994be343ed1c6d6313e0537b843e9a9c0836d1e83fe33154191ce9"
"a14d8d95bebaddc03bd471827170f527c0a166b9068b273d1bc57fbb13975ee4"
"f6b9a31743da6c447acbb712e81b13eddfd4e96c76010ac9b8aa1b6b3152b0fc"
"39ad33e5719656069f9ede9ebba7a77dd2e2074eec5c1b7ffc427a6f1be168f0"
"b5857713a44623862c903284bc53417e23c65602b52c1cb699e8352453eb9698"
"0b31459b90c26c907b549c1ab293725e414d4e45f5b30af7a55f95499a7dc89f"
"7d13ba90b34aef6b49484b0701bf96ea8b660c24bb4e92a2d1c43beb434fa386"
"1071380388799ac31d79285f5817687ed3e2eeb73a30744e77b757686c9ba5ad");;
ASSERT_EQ(NULL, find(wrapped_key, clear_key));
s.close();
testTearDown();
delete[] gen_signature;
}
TEST_F(OEMCryptoClientTest, CertificateLicense) {
OEMCryptoResult sts;
InstallKeybox(kDefaultKeybox);
testSetUp();
Session& s = createSession("ONE");
s.open();
vector<uint8_t> wrappedKey;
ASSERT_TRUE(s.GenerateDerivedKeys());
ASSERT_TRUE(s.CertificateProvision(&wrappedKey));
// Load the Wrapped Key
sts = OEMCrypto_LoadDeviceRSAKey(s.session_id(), &wrappedKey[0],
wrappedKey.size());
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// Sign a Message
vector<uint8_t> licenseRequest = wvcdm::a2b_hex(
"ba711a51e0c4c995440c28057f7f5e2f2e9c3a1edeb7549aca21e6050b059ac8"
"6ad64ec1a528eef17b4f5ce781af488d50fb0e60d04b48c78d55847a4e14243c"
"0023c553b46a2f53995870f351295e3aa2237f153f1415e817ad23e662e547b1"
"4708b303473813f93ee192353ff22bee54dd0f558bbe4b61b75b387bc310e9d6"
"8ff2cb3482689c0688570809b756dba4c2697be3132a2da782aa877ed64d8c7d"
"506525a382bad14d7e797c256c3617c22fa4165482b9742e9b54ffb6c52eda1d");
size_t signature_length = 0;
sts = OEMCrypto_GenerateRSASignature(s.session_id(), &licenseRequest[0],
licenseRequest.size(), NULL,
&signature_length);
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
ASSERT_NE(static_cast<size_t>(0), signature_length);
uint8_t* signature = new uint8_t[signature_length];
sts = OEMCrypto_GenerateRSASignature(s.session_id(), &licenseRequest[0],
licenseRequest.size(), signature,
&signature_length);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// TODO: Validate the signature
// Rewrap Canned Response
// In the real world, the signature above would just have been used to contact
// the license server to get this response.
// TODO: This is not a valid test vector
vector<uint8_t> sessionKey = wvcdm::a2b_hex(
"6fa479c731d2770b6a61a5d1420bb9d1");
vector<uint8_t> mac_context = wvcdm::a2b_hex(
"41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff"
"de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873"
"4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a"
"230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635"
"34333231180120002a0c31383836373837343035000000000100");
vector<uint8_t> enc_context = wvcdm::a2b_hex(
"454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95"
"c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb"
"e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408"
"0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231"
"180120002a0c31383836373837343035000000000080");
sts = OEMCrypto_DeriveKeysFromSessionKey(s.session_id(), &sessionKey[0],
sessionKey.size(), &mac_context[0],
mac_context.size(), &enc_context[0],
enc_context.size());
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
s.close();
testTearDown();
delete[] signature;
}
TEST_F(OEMCryptoClientTest, CertificateDecrypt) {
OEMCryptoResult sts;
testSetUp();
InstallKeybox(kDefaultKeybox);
Session& s = createSession("ONE");
s.open();
ASSERT_TRUE(s.GenerateDerivedKeys());
ASSERT_TRUE(s.CertificateLicense());
// Select the key (from fill_simple_message)
vector<uint8_t> keyId = wvcdm::a2b_hex("000000000000000000000000");
sts = OEMCrypto_SelectKey(s.session_id(), &keyId[0], keyId.size());
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
// Set up our expected input and output
vector<uint8_t> encryptedData = wvcdm::a2b_hex(
"ec261c115f9d5cda1d5cc7d33c4e37362d1397c89efdd1da5f0065c4848b0462"
"337ba14693735203c9b4184e362439c0cea5e5d1a628425eddf8a6bf9ba901ca"
"46f5a9fd973cffbbe3c276af9919e2e8f6f3f420538b7a0d6dc41487874d96b8"
"efaedb45a689b91beb8c20d36140ad467d9d620b19a5fc6f223b57e0e6a7f913"
"00fd899e5e1b89963e83067ca0912aa5b79df683e2530b55a9645be341bc5f07"
"cffc724790af635c959e2644e51ba7f23bae710eb55a1f2f4e060c3c1dd1387c"
"74415dc880492dd1d5b9ecf3f01de48a44baeb4d3ea5cc4f8d561d0865afcabb"
"fc14a9ab9647e6e31adabb72d792f0c9ba99dc3e9205657d28fc7771d64e6d4b");
vector<uint8_t> encryptionIv = wvcdm::a2b_hex(
"719dbcb253b2ec702bb8c1b1bc2f3bc6");
vector<uint8_t> unencryptedData = wvcdm::a2b_hex(
"19ef4361e16e6825b336e2012ad8ffc9ce176ab2256e1b98aa15b7877bd8c626"
"fa40b2e88373457cbcf4f1b4b9793434a8ac03a708f85974cff01bddcbdd7a8e"
"e33fd160c1d5573bfd8104efd23237edcf28205c3673920553f8dd5e916604b0"
"1082345181dceeae5ea39d829c7f49e1850c460645de33c288723b7ae3d91a17"
"a3f04195cd1945ba7b0f37fef7e82368be30f04365d877766f6d56f67d22a244"
"ef2596d3053f657c1b5d90b64e11797edf1c198a23a7bfc20e4d44c74ae41280"
"a8317f443255f4020eda850ff0954e308f53a634cbce799ae58911bc59ccd6a5"
"de2ac53ee0fa7ea15fc692cc892acc0090865dc57becacddf362a092dfd3040b");
// Describe the output
uint8_t outputBuffer[256];
OEMCrypto_DestBufferDesc destBuffer;
destBuffer.type = OEMCrypto_BufferType_Clear;
destBuffer.buffer.clear.address = outputBuffer;
destBuffer.buffer.clear.max_length = sizeof(outputBuffer);
// Decrypt the data
sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0],
encryptedData.size(), true, &encryptionIv[0], 0,
&destBuffer);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer,
unencryptedData.size()));
s.close();
testTearDown();
}
#endif // CAN_INSTALL_KEYBOX
// TODO(kqyang): Add more unit tests
} // namespace wvoec