// Copyright 2013 Google Inc. All Rights Reserved. // // OEMCrypto unit tests // #include // TODO(fredgc): Add ntoh to wv_cdm_utilities.h #include #include #include #include #include #include #include #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 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(&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 mac_context = wvcdm::a2b_hex( "41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff" "de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873" "4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a" "230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635" "34333231180120002a0c31383836373837343035000000000100"); vector 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(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* wrappedKey) { vector 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 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(&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 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 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 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 sessionKey = wvcdm::a2b_hex( "6fa479c731d2770b6a61a5d1420bb9d1"); vector mac_context = wvcdm::a2b_hex( "41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff" "de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873" "4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a" "230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635" "34333231180120002a0c31383836373837343035000000000100"); vector 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 void fill_simple_message(MessageData* 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 key = wvcdm::a2b_hex("39AD33E5719656069F9EDE9EBBA7A77D"); memcpy(data->keys[0].key_data, &key[0], key.size()); } template void encrypt_message(const MessageData& data, MessageData* 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(&data.keys[i].control), reinterpret_cast(&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 void sign_message(MessageData data, std::vector* signature) { signature->resize(SHA256_DIGEST_LENGTH); unsigned int md_len = SHA256_DIGEST_LENGTH; HMAC(EVP_sha256(), &mac_key_[0], SHA256_DIGEST_LENGTH, reinterpret_cast(&data), sizeof(data), &(signature->front()), &md_len); } template void fill_key_array(const MessageData& 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(&data.keys[i].control); } } private: bool CreateAndLoadKeyMessage() { const unsigned int num_keys = 3; MessageData data; fill_simple_message(&data); MessageData encrypted; encrypt_message(data, &encrypted); std::vector signature; sign_message(encrypted, &signature); OEMCrypto_KeyObject key_array[num_keys]; const uint8_t* message_ptr = reinterpret_cast(&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(sts) << endl; } return sts == OEMCrypto_SUCCESS; } bool valid_; bool open_; string sname_; OEMCrypto_SESSION session_id_; OEMCryptoResult session_status_; vector mac_key_; vector enc_key_; uint32_t nonce_; }; static Session badSession; Session& findSession(string sname) { map::iterator it = _sessions.find(sname); if (it != _sessions.end()) { return it->second; } return badSession; } Session& createSession(string sname) { Session temp(sname); _sessions.insert(pair(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& message, const vector& substring) { vector::const_iterator pos = search(message.begin(), message.end(), substring.begin(), substring.end()); if (pos == message.end()) { return NULL; } return &(*pos); } private: bool alive_; map _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 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 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 encrypted; s.encrypt_message(data, &encrypted); std::vector signature; s.sign_message(encrypted, &signature); OEMCrypto_KeyObject key_array[num_keys]; const uint8_t* message_ptr = reinterpret_cast(&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 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 encrypted; s.encrypt_message(data, &encrypted); std::vector signature; s.sign_message(encrypted, &signature); OEMCrypto_KeyObject key_array[num_keys]; const uint8_t* message_ptr = reinterpret_cast(&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 data; s.fill_simple_message(&data); MessageData encrypted; s.encrypt_message(data, &encrypted); std::vector signature; s.sign_message(encrypted, &signature); OEMCrypto_KeyObject key_array[num_keys]; const uint8_t* message_ptr = reinterpret_cast(&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 data; s.fill_simple_message(&data); MessageData encrypted; s.encrypt_message(data, &encrypted); std::vector signature; s.sign_message(encrypted, &signature); OEMCrypto_KeyObject key_array[num_keys]; const uint8_t* message_ptr = reinterpret_cast(&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 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 encryptedData = wvcdm::a2b_hex( "ec261c115f9d5cda1d5cc7d33c4e37362d1397c89efdd1da5f0065c4848b0462" "337ba14693735203c9b4184e362439c0cea5e5d1a628425eddf8a6bf9ba901ca" "46f5a9fd973cffbbe3c276af9919e2e8f6f3f420538b7a0d6dc41487874d96b8" "efaedb45a689b91beb8c20d36140ad467d9d620b19a5fc6f223b57e0e6a7f913" "00fd899e5e1b89963e83067ca0912aa5b79df683e2530b55a9645be341bc5f07" "cffc724790af635c959e2644e51ba7f23bae710eb55a1f2f4e060c3c1dd1387c" "74415dc880492dd1d5b9ecf3f01de48a44baeb4d3ea5cc4f8d561d0865afcabb" "fc14a9ab9647e6e31adabb72d792f0c9ba99dc3e9205657d28fc7771d64e6d4b"); vector encryptionIv = wvcdm::a2b_hex( "719dbcb253b2ec702bb8c1b1bc2f3bc6"); vector 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 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 encryptedData = wvcdm::a2b_hex( "c17055d4e3ab8e892b40ca2deed7cd46b406cd41d50f23d5877b36" "ad351887df2b3774dc413904afd958ba766cc6ab51a3ffd8f845296c5d8326ee" "39c9d0fec79885515e6b8a12911831d9fb158ca2fd3dfcfcf228741a63734685" "8dffc30f5871260c5cef8be61cfa08b191c837901f077046664c0c56db81d412" "98b59e5655cd94871c3c226dc3565144297f1459cddba069d5d2d6206cfd5798" "eda4b82e01a9966d48984d6ef3fbd326ba0f6fcbe52c95786d478c2f33398c62" "ae5210c7472d7d8dc7d12f981679f4ea9793736f354747ef14165367b94e07fc" "4bcc7bd14746304fea100dc6465ab51241355bb19e6c2cfb2bb6bbf709765d13"); vector encryptionIv = wvcdm::a2b_hex( "c09454479a280829c946df3c22f25539"); vector 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 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 unencryptedData = wvcdm::a2b_hex( "1558497b6d994be343ed1c6d6313e0537b843e9a9c0836d1e83fe33154191ce9" "a14d8d95bebaddc03bd471827170f527c0a166b9068b273d1bc57fbb13975ee4" "f6b9a31743da6c447acbb712e81b13eddfd4e96c76010ac9b8aa1b6b3152b0fc" "39ad33e5719656069f9ede9ebba7a77dd2e2074eec5c1b7ffc427a6f1be168f0" "b5857713a44623862c903284bc53417e23c65602b52c1cb699e8352453eb9698" "0b31459b90c26c907b549c1ab293725e414d4e45f5b30af7a55f95499a7dc89f" "7d13ba90b34aef6b49484b0701bf96ea8b660c24bb4e92a2d1c43beb434fa386" "1071380388799ac31d79285f5817687ed3e2eeb73a30744e77b757686c9ba5ad"); vector 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 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(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 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(&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 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(0), wrapped_key_length); vector 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 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 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 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(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 sessionKey = wvcdm::a2b_hex( "6fa479c731d2770b6a61a5d1420bb9d1"); vector mac_context = wvcdm::a2b_hex( "41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff" "de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873" "4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a" "230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635" "34333231180120002a0c31383836373837343035000000000100"); vector 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 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 encryptedData = wvcdm::a2b_hex( "ec261c115f9d5cda1d5cc7d33c4e37362d1397c89efdd1da5f0065c4848b0462" "337ba14693735203c9b4184e362439c0cea5e5d1a628425eddf8a6bf9ba901ca" "46f5a9fd973cffbbe3c276af9919e2e8f6f3f420538b7a0d6dc41487874d96b8" "efaedb45a689b91beb8c20d36140ad467d9d620b19a5fc6f223b57e0e6a7f913" "00fd899e5e1b89963e83067ca0912aa5b79df683e2530b55a9645be341bc5f07" "cffc724790af635c959e2644e51ba7f23bae710eb55a1f2f4e060c3c1dd1387c" "74415dc880492dd1d5b9ecf3f01de48a44baeb4d3ea5cc4f8d561d0865afcabb" "fc14a9ab9647e6e31adabb72d792f0c9ba99dc3e9205657d28fc7771d64e6d4b"); vector encryptionIv = wvcdm::a2b_hex( "719dbcb253b2ec702bb8c1b1bc2f3bc6"); vector 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