diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index ceca0493..724e9031 100755 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -161,7 +161,7 @@ void CryptoSession::GenerateMacContext(const std::string& input_context, deriv_context->assign(kSigningKeyLabel); deriv_context->append(1, '\0'); deriv_context->append(input_context); - deriv_context->append(EncodeUint32(kSigningKeySizeBits)); + deriv_context->append(EncodeUint32(kSigningKeySizeBits*2)); } void CryptoSession::GenerateEncryptContext(const std::string& input_context, @@ -419,10 +419,15 @@ CdmResponseType CryptoSession::Decrypt(bool is_encrypted, break; } - OEMCryptoResult sts = OEMCrypto_DecryptCTR(oec_session_id_, encrypt_buffer, - encrypt_length, is_encrypted, - &iv[0], block_offset, - &buffer_descriptor); + OEMCryptoResult sts = OEMCrypto_DecryptCTR( + oec_session_id_, + encrypt_buffer, + encrypt_length, + is_encrypted, + &iv[0], + block_offset, + &buffer_descriptor, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); if (OEMCrypto_SUCCESS != sts) { return UNKNOWN_ERROR; diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index 528720ba..80cd892a 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -31,30 +31,31 @@ using video_widevine_server::sdk::ClientIdentification_NameValue; using video_widevine_server::sdk::LicenseRequest; using video_widevine_server::sdk::LicenseRequest_ContentIdentification; using video_widevine_server::sdk::LicenseRequest_ContentIdentification_CENC; +using video_widevine_server::sdk::LicenseRequest_ContentIdentification_ExistingLicense; using video_widevine_server::sdk::License; using video_widevine_server::sdk::License_KeyContainer; using video_widevine_server::sdk::LicenseError; using video_widevine_server::sdk::SignedMessage; using video_widevine_server::sdk::STREAMING; -using video_widevine_server::sdk::LicenseRequest_ContentIdentification_ExistingLicense; +using video_widevine_server::sdk::VERSION_2_1; + static std::vector ExtractContentKeys(const License& license) { std::vector key_array; // Extract content key(s) for (int i = 0; i < license.key_size(); ++i) { - // TODO(kqyang): Key ID size is not fixed in spec, but conventionally we - // always use 16 bytes key id. We'll need to update oemcrypto to support - // variable size key id. - if (license.key(i).id().size() == KEY_ID_SIZE && - license.key(i).key().size() == KEY_SIZE + KEY_PAD_SIZE && - license.key(i).type() == License_KeyContainer::CONTENT) { - + // TODO(fredgc): Figure out what key.type is for Generic Keys. + // If the generic signing key is CONTENT, then the extra size log below is good. + // If it is SIGNING, then we are ignoring it. -- we should fix that by adding + // an else clause to this if statement. + if (license.key(i).type() == License_KeyContainer::CONTENT) { CryptoKey key; key.set_key_id(license.key(i).id()); - // Strip off PKCS#5 padding - key.set_key_data( - license.key(i).key().substr(0, KEY_SIZE)); + // Strip off PKCS#5 padding - since we know the key is 16 or 32 bytes, the + // padding will always be 16 bytes. + size_t length = license.key(i).key().size() - 16; + key.set_key_data( license.key(i).key().substr(0, length)); key.set_key_data_iv(license.key(i).iv()); if (license.key(i).has_key_control()) { key.set_key_control( @@ -184,6 +185,7 @@ bool CdmLicense::PrepareKeyRequest(const CdmInitData& init_data, } license_request.set_key_control_nonce(UintToString(nonce)); LOGD("PrepareKeyRequest: nonce=%u", nonce); + license_request.set_protocol_version(VERSION_2_1); // License request is complete. Serialize it. std::string serialized_license_req; @@ -240,6 +242,7 @@ bool CdmLicense::PrepareKeyRenewalRequest(CdmKeyMessage* signed_request) { } license_request.set_key_control_nonce(UintToString(nonce)); LOGD("PrepareKeyRenewalRequest: nonce=%u", nonce); + license_request.set_protocol_version(VERSION_2_1); // License request is complete. Serialize it. std::string serialized_license_req; diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index e5b015f2..4ae1c606 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -545,7 +545,7 @@ TEST_F(WvCdmRequestLicenseTest, PartialBlockWithOffsetDecryptionTest) { 0)); EXPECT_TRUE(std::equal(data.decrypt_data.begin(), data.decrypt_data.end(), - decrypt_buffer.begin())); + decrypt_buffer.begin())); decryptor_.CloseSession(session_id_); } diff --git a/libwvdrmengine/level3/arm/entry_points.cpp b/libwvdrmengine/level3/arm/entry_points.cpp index bf3c100f..6f04a87c 100644 --- a/libwvdrmengine/level3/arm/entry_points.cpp +++ b/libwvdrmengine/level3/arm/entry_points.cpp @@ -2,7 +2,7 @@ * * Copyright 2013 Google Inc. All Rights Reserved. * - * mock implementation of OEMCrypto APIs + * Wrapper for Level 1 OEMCrypto or Level 3 Fallback APIs * ******************************************************************************/ @@ -16,6 +16,9 @@ #include "log.h" #include "oemcrypto_engine_mock.h" +#include "openssl/cmac.h" +#include "openssl/evp.h" +#include "openssl/hmac.h" #include "openssl/rand.h" #include "openssl/sha.h" #include "wv_cdm_constants.h" @@ -65,7 +68,8 @@ typedef OEMCryptoResult (*L1_DecryptCTR_t)(OEMCrypto_SESSION session, bool is_encrypted, const uint8_t *iv, size_t offset, - const OEMCrypto_DestBufferDesc* out_buffer); + const OEMCrypto_DestBufferDesc* out_buffer, + uint8_t subsample_flags); typedef OEMCryptoResult (*L1_InstallKeybox_t)(const uint8_t *keybox, size_t keyBoxLength); typedef OEMCryptoResult (*L1_IsKeyboxValid_t)(void); @@ -363,7 +367,8 @@ OEMCryptoResult OEMCrypto_GenerateDerivedKeys(OEMCrypto_SESSION session, enc_key_context + enc_key_context_length); // Generate mac and encryption keys for current session context - if (!session_ctx->DeriveKeys(mac_ctx_str, enc_ctx_str)) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + mac_ctx_str, enc_ctx_str)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } return OEMCrypto_SUCCESS; @@ -428,12 +433,12 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, const uint8_t* signature, size_t signature_length, const uint8_t* enc_mac_key_iv, - const uint8_t* enc_mac_key, + const uint8_t* enc_mac_keys, size_t num_keys, const OEMCrypto_KeyObject* key_array) { if (level1.library) { return level1.OEMCrypto_LoadKeys(session, message, message_length, signature, - signature_length, enc_mac_key_iv, enc_mac_key, + signature_length, enc_mac_key_iv, enc_mac_keys, num_keys, key_array); } if (NO_ERROR != crypto_engine->ValidateKeybox()) { @@ -455,8 +460,8 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, } // Range check - if (!RangeCheck(message, message_length, enc_mac_key, - wvcdm::MAC_KEY_SIZE, true) || + if (!RangeCheck(message, message_length, enc_mac_keys, + 2*wvcdm::MAC_KEY_SIZE, true) || !RangeCheck(message, message_length, enc_mac_key_iv, wvcdm::KEY_IV_SIZE, true)) { LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE - range check.]"); @@ -471,9 +476,9 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, !RangeCheck(message, message_length, key_array[i].key_data_iv, wvcdm::KEY_IV_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control, - wvcdm::KEY_CONTROL_SIZE, true) || + wvcdm::KEY_CONTROL_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control_iv, - wvcdm::KEY_IV_SIZE, true)) { + wvcdm::KEY_IV_SIZE, false)) { LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE -range check %d]", i); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } @@ -521,18 +526,17 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; // enc_mac_key can be NULL if license renewal is not supported - if (enc_mac_key == NULL) return OEMCrypto_SUCCESS; + if (enc_mac_keys == NULL) return OEMCrypto_SUCCESS; - // V2 license protocol: update mac key after processing license response - const std::vector enc_mac_key_str = std::vector( - enc_mac_key, enc_mac_key + wvcdm::MAC_KEY_SIZE); + // V2.1 license protocol: update mac keys after processing license response + const std::vector enc_mac_keys_str = std::vector( + enc_mac_keys, enc_mac_keys + 2*wvcdm::MAC_KEY_SIZE); const std::vector enc_mac_key_iv_str = std::vector( enc_mac_key_iv, enc_mac_key_iv + wvcdm::KEY_IV_SIZE); - if (!session_ctx->UpdateMacKey(enc_mac_key_str, enc_mac_key_iv_str)) { + if (!session_ctx->UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - return OEMCrypto_SUCCESS; } @@ -560,7 +564,8 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, } if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0) { + signature == NULL || signature_length == 0 || + num_keys == 0) { LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return OEMCrypto_ERROR_INVALID_CONTEXT; } @@ -570,10 +575,10 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, if (!RangeCheck(message, message_length, key_array[i].key_id, key_array[i].key_id_length, true) || !RangeCheck(message, message_length, key_array[i].key_control, - wvcdm::KEY_CONTROL_SIZE, true) || + wvcdm::KEY_CONTROL_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control_iv, wvcdm::KEY_IV_SIZE, true)) { - LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE]"); + LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } } @@ -581,6 +586,7 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, // Validate message signature if (!session_ctx->ValidateMessage(message, message_length, signature, signature_length)) { + LOGE("[OEMCrypto_RefreshKeys(): signature was invalid]"); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } @@ -590,24 +596,28 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, std::vector key_control; std::vector key_control_iv; for (unsigned int i = 0; i < num_keys; i++) { - // TODO(gmorgan): key_id may be null if special control key type (TBS) if (key_array[i].key_id != NULL) { key_id.assign(key_array[i].key_id, key_array[i].key_id + key_array[i].key_id_length); - } else { - key_id.clear(); - } - if (key_array[i].key_control != NULL) { key_control.assign(key_array[i].key_control, key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE); - key_control_iv.assign(key_array[i].key_control_iv, - key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE); + if (key_array[i].key_control_iv == NULL ) { + key_control_iv.clear(); + } else { + key_control_iv.assign(key_array[i].key_control_iv, + key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE); + } } else { - key_control.clear(); + // key_id could be null if special control key type + // key_control is not encrypted in this case + key_id.clear(); key_control_iv.clear(); + key_control.assign(key_array[i].key_control, + key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE); } if (!session_ctx->RefreshKey(key_id, key_control, key_control_iv)) { + LOGE("[OEMCrypto_RefreshKeys(): error in key %i]", i); status = false; break; } @@ -638,8 +648,8 @@ OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, return OEMCrypto_ERROR_INVALID_SESSION; } - const std::vector key_id_str = std::vector(key_id, key_id + key_id_length); - if (!session_ctx->SelectContentKey(key_id_str)) { + const std::vector key_id_vec = std::vector(key_id, key_id + key_id_length); + if (!session_ctx->SelectContentKey(key_id_vec)) { LOGE("[OEMCrypto_SelectKey(): FAIL]"); return OEMCrypto_ERROR_NO_CONTENT_KEY; } @@ -653,14 +663,16 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, size_t data_length, bool is_encrypted, const uint8_t* iv, - size_t offset, - const OEMCrypto_DestBufferDesc* out_buffer) { + size_t block_offset, + const OEMCrypto_DestBufferDesc* out_buffer, + uint8_t subsample_flags) { if (level1.library) { return level1.OEMCrypto_DecryptCTR( session, data_addr, data_length, - is_encrypted, iv, offset, out_buffer); + is_encrypted, iv, block_offset, + out_buffer, subsample_flags); } wvoec_mock::BufferType buffer_type = kBufferTypeDirect; - void* destination = NULL; + uint8_t* destination = NULL; size_t max_length = 0; switch (out_buffer->type) { case OEMCrypto_BufferType_Clear: @@ -670,7 +682,8 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, break; case OEMCrypto_BufferType_Secure: buffer_type = kBufferTypeSecure; - destination = out_buffer->buffer.secure.handle; + destination = ((uint8_t*)out_buffer->buffer.secure.handle + + out_buffer->buffer.secure.offset); max_length = out_buffer->buffer.secure.max_length; break; default: @@ -685,10 +698,12 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, return OEMCrypto_ERROR_SHORT_BUFFER; } +#ifndef NDEBUG if (NO_ERROR != crypto_engine->ValidateKeybox()) { LOGE("[OEMCrypto_DecryptCTR(): ERROR_KEYBOX_INVALID]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } +#endif SessionContext* session_ctx = crypto_engine->FindSession(session); if (!session_ctx || !session_ctx->isValid()) { @@ -702,11 +717,11 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, return OEMCrypto_ERROR_INVALID_CONTEXT; } - if (!crypto_engine->DecryptCTR(session_ctx, iv, (int)offset, + if (!crypto_engine->DecryptCTR(session_ctx, iv, (int)block_offset, data_addr, data_length, is_encrypted, destination, buffer_type)) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; + LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_DECRYPT_FAILED]"); + return OEMCrypto_ERROR_DECRYPT_FAILED; } return OEMCrypto_SUCCESS; @@ -744,20 +759,20 @@ OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, if (level1.library) { return level1.OEMCrypto_GetDeviceID(deviceID, idLength); } - std::vector dev_id_string = crypto_engine->keybox().device_id(); - if (dev_id_string.empty()) { + std::vector dev_id_vec = crypto_engine->keybox().device_id(); + if (dev_id_vec.empty()) { LOGE("[OEMCrypto_GetDeviceId(): Keybox Invalid]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } - size_t dev_id_len = dev_id_string.size(); + size_t dev_id_len = dev_id_vec.size(); if (*idLength < dev_id_len) { *idLength = dev_id_len; LOGE("[OEMCrypto_GetDeviceId(): ERROR_SHORT_BUFFER]"); return OEMCrypto_ERROR_SHORT_BUFFER; } memset(deviceID, 0, *idLength); - memcpy(deviceID, &dev_id_string[0], dev_id_len); + memcpy(deviceID, &dev_id_vec[0], dev_id_len); *idLength = dev_id_len; LOGD("[OEMCrypto_GetDeviceId(): success]"); return OEMCrypto_SUCCESS; @@ -889,46 +904,73 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, } session_ctx->FlushNonces(); - // Decrypt key and verify signature. - if (!session_ctx->LoadRSAKey(enc_rsa_key, enc_rsa_key_length, - enc_rsa_key_iv, message, message_length, - signature, signature_length)) { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; + // Decrypt RSA key. + uint8_t* pkcs8_rsa_key = new uint8_t[enc_rsa_key_length]; + OEMCryptoResult result = OEMCrypto_SUCCESS; + if (!session_ctx->DecryptRSAKey(enc_rsa_key, enc_rsa_key_length, + enc_rsa_key_iv, pkcs8_rsa_key)) { + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; + if( result == OEMCrypto_SUCCESS) { + if (padding > 16) { + LOGE("[RewrapRSAKey(): Encrypted RSA has bad padding: %d]", padding); + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + size_t rsa_key_length = enc_rsa_key_length - padding; + // verify signature, verify RSA key, and load it. + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->LoadRSAKey(pkcs8_rsa_key, rsa_key_length, + message, message_length, + signature, signature_length)) { + result = OEMCrypto_ERROR_SIGNATURE_FAILURE; // return OEMCrypto_ERROR_INVALID_RSA_KEY; + } } // Now we generate a wrapped keybox. WrappedRSAKey* wrapped = reinterpret_cast(wrapped_rsa_key); // Pick a random context and IV for generating keys. - if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } - if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const std::vector mac_ctx_str(wrapped->context, - wrapped->context + sizeof(wrapped->context)); + const std::vector context(wrapped->context, + wrapped->context + sizeof(wrapped->context)); // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(mac_ctx_str, mac_ctx_str)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + context, context)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } // Encrypt rsa key with keybox. - if (!session_ctx->EncryptRSAKey(wrapped->enc_rsa_key, - enc_rsa_key_length, - wrapped->iv)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->EncryptRSAKey(pkcs8_rsa_key, enc_rsa_key_length, + wrapped->iv, wrapped->enc_rsa_key)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } + delete[] pkcs8_rsa_key; - size_t sig_length = sizeof(wrapped->signature); - if (!session_ctx->GenerateSignature(wrapped->context, // start signing here. - buffer_size - sizeof(wrapped->signature), - wrapped->signature, - &sig_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + // The wrapped keybox must be signed with the same key we verify with. I'll + // pick the server key, so I don't have to modify LoadRSAKey. + if( result == OEMCrypto_SUCCESS) { + size_t sig_length = sizeof(wrapped->signature); + if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0], + SHA256_DIGEST_LENGTH, wrapped->context, + buffer_size - sizeof(wrapped->signature), wrapped->signature, + &sig_length)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } - - return OEMCrypto_SUCCESS; + return result; } extern "C" @@ -942,40 +984,60 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, return level1.OEMCrypto_LoadDeviceRSAKey( session, wrapped_rsa_key, wrapped_rsa_key_length); } - const WrappedRSAKey* wrapped - = reinterpret_cast(wrapped_rsa_key); if (wrapped_rsa_key == NULL) { LOGE("[OEMCrypto_LoadDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return OEMCrypto_ERROR_INVALID_CONTEXT; } + const WrappedRSAKey* wrapped + = reinterpret_cast(wrapped_rsa_key); if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); + LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } SessionContext* session_ctx = crypto_engine->FindSession(session); if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); + LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); return OEMCrypto_ERROR_INVALID_SESSION; } - const std::vector mac_ctx_str(wrapped->context, - wrapped->context + sizeof(wrapped->context)); + const std::vector context(wrapped->context, + wrapped->context + sizeof(wrapped->context)); // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(mac_ctx_str, mac_ctx_str)) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + context, context)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - // Decrypt key and verify signature. - if (!session_ctx->LoadRSAKey(wrapped->enc_rsa_key, - wrapped_rsa_key_length - sizeof(WrappedRSAKey), - wrapped->iv, - wrapped->context, - wrapped_rsa_key_length - sizeof(wrapped->signature), - wrapped->signature, - sizeof(wrapped->signature))) { - return OEMCrypto_ERROR_INVALID_RSA_KEY; + // Decrypt RSA key. + uint8_t* pkcs8_rsa_key = new uint8_t[wrapped_rsa_key_length + - sizeof(wrapped->signature)]; + size_t enc_rsa_key_length = wrapped_rsa_key_length - sizeof(WrappedRSAKey); + OEMCryptoResult result = OEMCrypto_SUCCESS; + if (!session_ctx->DecryptRSAKey(wrapped->enc_rsa_key, enc_rsa_key_length, + wrapped->iv, pkcs8_rsa_key)) { + result = OEMCrypto_ERROR_INVALID_RSA_KEY; } - return OEMCrypto_SUCCESS; + size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; + if( result == OEMCrypto_SUCCESS) { + if (padding > 16) { + LOGE("[LoadDeviceRSAKey(): Encrypted RSA has bad padding: %d]", padding); + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + size_t rsa_key_length = enc_rsa_key_length - padding; + // verify signature. + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->LoadRSAKey(pkcs8_rsa_key, rsa_key_length, + wrapped->context, + wrapped_rsa_key_length - sizeof(wrapped->signature), + wrapped->signature, + sizeof(wrapped->signature))) { + result = OEMCrypto_ERROR_SIGNATURE_FAILURE; + // return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + delete[] pkcs8_rsa_key; + return result; } extern "C" @@ -1058,15 +1120,15 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(OEMCrypto_SESSION session, return OEMCrypto_ERROR_INVALID_SESSION; } - const std::vector ssn_key_str(enc_session_key, + const std::vector ssn_key_vec(enc_session_key, enc_session_key + enc_session_key_length); - const std::vector mac_ctx_str(mac_key_context, + const std::vector mac_ctx_vec(mac_key_context, mac_key_context + mac_key_context_length); - const std::vector enc_ctx_str(enc_key_context, + const std::vector enc_ctx_vec(enc_key_context, enc_key_context + enc_key_context_length); // Generate mac and encryption keys for current session context - if (!session_ctx->RSADeriveKeys(ssn_key_str, mac_ctx_str, enc_ctx_str)) { + if (!session_ctx->RSADeriveKeys(ssn_key_vec, mac_ctx_vec, enc_ctx_vec)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } return OEMCrypto_SUCCESS; diff --git a/libwvdrmengine/level3/mips/entry_points.cpp b/libwvdrmengine/level3/mips/entry_points.cpp index bf3c100f..6f04a87c 100644 --- a/libwvdrmengine/level3/mips/entry_points.cpp +++ b/libwvdrmengine/level3/mips/entry_points.cpp @@ -2,7 +2,7 @@ * * Copyright 2013 Google Inc. All Rights Reserved. * - * mock implementation of OEMCrypto APIs + * Wrapper for Level 1 OEMCrypto or Level 3 Fallback APIs * ******************************************************************************/ @@ -16,6 +16,9 @@ #include "log.h" #include "oemcrypto_engine_mock.h" +#include "openssl/cmac.h" +#include "openssl/evp.h" +#include "openssl/hmac.h" #include "openssl/rand.h" #include "openssl/sha.h" #include "wv_cdm_constants.h" @@ -65,7 +68,8 @@ typedef OEMCryptoResult (*L1_DecryptCTR_t)(OEMCrypto_SESSION session, bool is_encrypted, const uint8_t *iv, size_t offset, - const OEMCrypto_DestBufferDesc* out_buffer); + const OEMCrypto_DestBufferDesc* out_buffer, + uint8_t subsample_flags); typedef OEMCryptoResult (*L1_InstallKeybox_t)(const uint8_t *keybox, size_t keyBoxLength); typedef OEMCryptoResult (*L1_IsKeyboxValid_t)(void); @@ -363,7 +367,8 @@ OEMCryptoResult OEMCrypto_GenerateDerivedKeys(OEMCrypto_SESSION session, enc_key_context + enc_key_context_length); // Generate mac and encryption keys for current session context - if (!session_ctx->DeriveKeys(mac_ctx_str, enc_ctx_str)) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + mac_ctx_str, enc_ctx_str)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } return OEMCrypto_SUCCESS; @@ -428,12 +433,12 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, const uint8_t* signature, size_t signature_length, const uint8_t* enc_mac_key_iv, - const uint8_t* enc_mac_key, + const uint8_t* enc_mac_keys, size_t num_keys, const OEMCrypto_KeyObject* key_array) { if (level1.library) { return level1.OEMCrypto_LoadKeys(session, message, message_length, signature, - signature_length, enc_mac_key_iv, enc_mac_key, + signature_length, enc_mac_key_iv, enc_mac_keys, num_keys, key_array); } if (NO_ERROR != crypto_engine->ValidateKeybox()) { @@ -455,8 +460,8 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, } // Range check - if (!RangeCheck(message, message_length, enc_mac_key, - wvcdm::MAC_KEY_SIZE, true) || + if (!RangeCheck(message, message_length, enc_mac_keys, + 2*wvcdm::MAC_KEY_SIZE, true) || !RangeCheck(message, message_length, enc_mac_key_iv, wvcdm::KEY_IV_SIZE, true)) { LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE - range check.]"); @@ -471,9 +476,9 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, !RangeCheck(message, message_length, key_array[i].key_data_iv, wvcdm::KEY_IV_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control, - wvcdm::KEY_CONTROL_SIZE, true) || + wvcdm::KEY_CONTROL_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control_iv, - wvcdm::KEY_IV_SIZE, true)) { + wvcdm::KEY_IV_SIZE, false)) { LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE -range check %d]", i); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } @@ -521,18 +526,17 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; // enc_mac_key can be NULL if license renewal is not supported - if (enc_mac_key == NULL) return OEMCrypto_SUCCESS; + if (enc_mac_keys == NULL) return OEMCrypto_SUCCESS; - // V2 license protocol: update mac key after processing license response - const std::vector enc_mac_key_str = std::vector( - enc_mac_key, enc_mac_key + wvcdm::MAC_KEY_SIZE); + // V2.1 license protocol: update mac keys after processing license response + const std::vector enc_mac_keys_str = std::vector( + enc_mac_keys, enc_mac_keys + 2*wvcdm::MAC_KEY_SIZE); const std::vector enc_mac_key_iv_str = std::vector( enc_mac_key_iv, enc_mac_key_iv + wvcdm::KEY_IV_SIZE); - if (!session_ctx->UpdateMacKey(enc_mac_key_str, enc_mac_key_iv_str)) { + if (!session_ctx->UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - return OEMCrypto_SUCCESS; } @@ -560,7 +564,8 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, } if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0) { + signature == NULL || signature_length == 0 || + num_keys == 0) { LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return OEMCrypto_ERROR_INVALID_CONTEXT; } @@ -570,10 +575,10 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, if (!RangeCheck(message, message_length, key_array[i].key_id, key_array[i].key_id_length, true) || !RangeCheck(message, message_length, key_array[i].key_control, - wvcdm::KEY_CONTROL_SIZE, true) || + wvcdm::KEY_CONTROL_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control_iv, wvcdm::KEY_IV_SIZE, true)) { - LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE]"); + LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } } @@ -581,6 +586,7 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, // Validate message signature if (!session_ctx->ValidateMessage(message, message_length, signature, signature_length)) { + LOGE("[OEMCrypto_RefreshKeys(): signature was invalid]"); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } @@ -590,24 +596,28 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, std::vector key_control; std::vector key_control_iv; for (unsigned int i = 0; i < num_keys; i++) { - // TODO(gmorgan): key_id may be null if special control key type (TBS) if (key_array[i].key_id != NULL) { key_id.assign(key_array[i].key_id, key_array[i].key_id + key_array[i].key_id_length); - } else { - key_id.clear(); - } - if (key_array[i].key_control != NULL) { key_control.assign(key_array[i].key_control, key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE); - key_control_iv.assign(key_array[i].key_control_iv, - key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE); + if (key_array[i].key_control_iv == NULL ) { + key_control_iv.clear(); + } else { + key_control_iv.assign(key_array[i].key_control_iv, + key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE); + } } else { - key_control.clear(); + // key_id could be null if special control key type + // key_control is not encrypted in this case + key_id.clear(); key_control_iv.clear(); + key_control.assign(key_array[i].key_control, + key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE); } if (!session_ctx->RefreshKey(key_id, key_control, key_control_iv)) { + LOGE("[OEMCrypto_RefreshKeys(): error in key %i]", i); status = false; break; } @@ -638,8 +648,8 @@ OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, return OEMCrypto_ERROR_INVALID_SESSION; } - const std::vector key_id_str = std::vector(key_id, key_id + key_id_length); - if (!session_ctx->SelectContentKey(key_id_str)) { + const std::vector key_id_vec = std::vector(key_id, key_id + key_id_length); + if (!session_ctx->SelectContentKey(key_id_vec)) { LOGE("[OEMCrypto_SelectKey(): FAIL]"); return OEMCrypto_ERROR_NO_CONTENT_KEY; } @@ -653,14 +663,16 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, size_t data_length, bool is_encrypted, const uint8_t* iv, - size_t offset, - const OEMCrypto_DestBufferDesc* out_buffer) { + size_t block_offset, + const OEMCrypto_DestBufferDesc* out_buffer, + uint8_t subsample_flags) { if (level1.library) { return level1.OEMCrypto_DecryptCTR( session, data_addr, data_length, - is_encrypted, iv, offset, out_buffer); + is_encrypted, iv, block_offset, + out_buffer, subsample_flags); } wvoec_mock::BufferType buffer_type = kBufferTypeDirect; - void* destination = NULL; + uint8_t* destination = NULL; size_t max_length = 0; switch (out_buffer->type) { case OEMCrypto_BufferType_Clear: @@ -670,7 +682,8 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, break; case OEMCrypto_BufferType_Secure: buffer_type = kBufferTypeSecure; - destination = out_buffer->buffer.secure.handle; + destination = ((uint8_t*)out_buffer->buffer.secure.handle + + out_buffer->buffer.secure.offset); max_length = out_buffer->buffer.secure.max_length; break; default: @@ -685,10 +698,12 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, return OEMCrypto_ERROR_SHORT_BUFFER; } +#ifndef NDEBUG if (NO_ERROR != crypto_engine->ValidateKeybox()) { LOGE("[OEMCrypto_DecryptCTR(): ERROR_KEYBOX_INVALID]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } +#endif SessionContext* session_ctx = crypto_engine->FindSession(session); if (!session_ctx || !session_ctx->isValid()) { @@ -702,11 +717,11 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, return OEMCrypto_ERROR_INVALID_CONTEXT; } - if (!crypto_engine->DecryptCTR(session_ctx, iv, (int)offset, + if (!crypto_engine->DecryptCTR(session_ctx, iv, (int)block_offset, data_addr, data_length, is_encrypted, destination, buffer_type)) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; + LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_DECRYPT_FAILED]"); + return OEMCrypto_ERROR_DECRYPT_FAILED; } return OEMCrypto_SUCCESS; @@ -744,20 +759,20 @@ OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, if (level1.library) { return level1.OEMCrypto_GetDeviceID(deviceID, idLength); } - std::vector dev_id_string = crypto_engine->keybox().device_id(); - if (dev_id_string.empty()) { + std::vector dev_id_vec = crypto_engine->keybox().device_id(); + if (dev_id_vec.empty()) { LOGE("[OEMCrypto_GetDeviceId(): Keybox Invalid]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } - size_t dev_id_len = dev_id_string.size(); + size_t dev_id_len = dev_id_vec.size(); if (*idLength < dev_id_len) { *idLength = dev_id_len; LOGE("[OEMCrypto_GetDeviceId(): ERROR_SHORT_BUFFER]"); return OEMCrypto_ERROR_SHORT_BUFFER; } memset(deviceID, 0, *idLength); - memcpy(deviceID, &dev_id_string[0], dev_id_len); + memcpy(deviceID, &dev_id_vec[0], dev_id_len); *idLength = dev_id_len; LOGD("[OEMCrypto_GetDeviceId(): success]"); return OEMCrypto_SUCCESS; @@ -889,46 +904,73 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, } session_ctx->FlushNonces(); - // Decrypt key and verify signature. - if (!session_ctx->LoadRSAKey(enc_rsa_key, enc_rsa_key_length, - enc_rsa_key_iv, message, message_length, - signature, signature_length)) { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; + // Decrypt RSA key. + uint8_t* pkcs8_rsa_key = new uint8_t[enc_rsa_key_length]; + OEMCryptoResult result = OEMCrypto_SUCCESS; + if (!session_ctx->DecryptRSAKey(enc_rsa_key, enc_rsa_key_length, + enc_rsa_key_iv, pkcs8_rsa_key)) { + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; + if( result == OEMCrypto_SUCCESS) { + if (padding > 16) { + LOGE("[RewrapRSAKey(): Encrypted RSA has bad padding: %d]", padding); + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + size_t rsa_key_length = enc_rsa_key_length - padding; + // verify signature, verify RSA key, and load it. + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->LoadRSAKey(pkcs8_rsa_key, rsa_key_length, + message, message_length, + signature, signature_length)) { + result = OEMCrypto_ERROR_SIGNATURE_FAILURE; // return OEMCrypto_ERROR_INVALID_RSA_KEY; + } } // Now we generate a wrapped keybox. WrappedRSAKey* wrapped = reinterpret_cast(wrapped_rsa_key); // Pick a random context and IV for generating keys. - if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } - if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const std::vector mac_ctx_str(wrapped->context, - wrapped->context + sizeof(wrapped->context)); + const std::vector context(wrapped->context, + wrapped->context + sizeof(wrapped->context)); // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(mac_ctx_str, mac_ctx_str)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + context, context)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } // Encrypt rsa key with keybox. - if (!session_ctx->EncryptRSAKey(wrapped->enc_rsa_key, - enc_rsa_key_length, - wrapped->iv)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->EncryptRSAKey(pkcs8_rsa_key, enc_rsa_key_length, + wrapped->iv, wrapped->enc_rsa_key)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } + delete[] pkcs8_rsa_key; - size_t sig_length = sizeof(wrapped->signature); - if (!session_ctx->GenerateSignature(wrapped->context, // start signing here. - buffer_size - sizeof(wrapped->signature), - wrapped->signature, - &sig_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + // The wrapped keybox must be signed with the same key we verify with. I'll + // pick the server key, so I don't have to modify LoadRSAKey. + if( result == OEMCrypto_SUCCESS) { + size_t sig_length = sizeof(wrapped->signature); + if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0], + SHA256_DIGEST_LENGTH, wrapped->context, + buffer_size - sizeof(wrapped->signature), wrapped->signature, + &sig_length)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } - - return OEMCrypto_SUCCESS; + return result; } extern "C" @@ -942,40 +984,60 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, return level1.OEMCrypto_LoadDeviceRSAKey( session, wrapped_rsa_key, wrapped_rsa_key_length); } - const WrappedRSAKey* wrapped - = reinterpret_cast(wrapped_rsa_key); if (wrapped_rsa_key == NULL) { LOGE("[OEMCrypto_LoadDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return OEMCrypto_ERROR_INVALID_CONTEXT; } + const WrappedRSAKey* wrapped + = reinterpret_cast(wrapped_rsa_key); if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); + LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } SessionContext* session_ctx = crypto_engine->FindSession(session); if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); + LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); return OEMCrypto_ERROR_INVALID_SESSION; } - const std::vector mac_ctx_str(wrapped->context, - wrapped->context + sizeof(wrapped->context)); + const std::vector context(wrapped->context, + wrapped->context + sizeof(wrapped->context)); // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(mac_ctx_str, mac_ctx_str)) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + context, context)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - // Decrypt key and verify signature. - if (!session_ctx->LoadRSAKey(wrapped->enc_rsa_key, - wrapped_rsa_key_length - sizeof(WrappedRSAKey), - wrapped->iv, - wrapped->context, - wrapped_rsa_key_length - sizeof(wrapped->signature), - wrapped->signature, - sizeof(wrapped->signature))) { - return OEMCrypto_ERROR_INVALID_RSA_KEY; + // Decrypt RSA key. + uint8_t* pkcs8_rsa_key = new uint8_t[wrapped_rsa_key_length + - sizeof(wrapped->signature)]; + size_t enc_rsa_key_length = wrapped_rsa_key_length - sizeof(WrappedRSAKey); + OEMCryptoResult result = OEMCrypto_SUCCESS; + if (!session_ctx->DecryptRSAKey(wrapped->enc_rsa_key, enc_rsa_key_length, + wrapped->iv, pkcs8_rsa_key)) { + result = OEMCrypto_ERROR_INVALID_RSA_KEY; } - return OEMCrypto_SUCCESS; + size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; + if( result == OEMCrypto_SUCCESS) { + if (padding > 16) { + LOGE("[LoadDeviceRSAKey(): Encrypted RSA has bad padding: %d]", padding); + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + size_t rsa_key_length = enc_rsa_key_length - padding; + // verify signature. + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->LoadRSAKey(pkcs8_rsa_key, rsa_key_length, + wrapped->context, + wrapped_rsa_key_length - sizeof(wrapped->signature), + wrapped->signature, + sizeof(wrapped->signature))) { + result = OEMCrypto_ERROR_SIGNATURE_FAILURE; + // return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + delete[] pkcs8_rsa_key; + return result; } extern "C" @@ -1058,15 +1120,15 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(OEMCrypto_SESSION session, return OEMCrypto_ERROR_INVALID_SESSION; } - const std::vector ssn_key_str(enc_session_key, + const std::vector ssn_key_vec(enc_session_key, enc_session_key + enc_session_key_length); - const std::vector mac_ctx_str(mac_key_context, + const std::vector mac_ctx_vec(mac_key_context, mac_key_context + mac_key_context_length); - const std::vector enc_ctx_str(enc_key_context, + const std::vector enc_ctx_vec(enc_key_context, enc_key_context + enc_key_context_length); // Generate mac and encryption keys for current session context - if (!session_ctx->RSADeriveKeys(ssn_key_str, mac_ctx_str, enc_ctx_str)) { + if (!session_ctx->RSADeriveKeys(ssn_key_vec, mac_ctx_vec, enc_ctx_vec)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } return OEMCrypto_SUCCESS; diff --git a/libwvdrmengine/level3/x86/entry_points.cpp b/libwvdrmengine/level3/x86/entry_points.cpp index bf3c100f..6f04a87c 100644 --- a/libwvdrmengine/level3/x86/entry_points.cpp +++ b/libwvdrmengine/level3/x86/entry_points.cpp @@ -2,7 +2,7 @@ * * Copyright 2013 Google Inc. All Rights Reserved. * - * mock implementation of OEMCrypto APIs + * Wrapper for Level 1 OEMCrypto or Level 3 Fallback APIs * ******************************************************************************/ @@ -16,6 +16,9 @@ #include "log.h" #include "oemcrypto_engine_mock.h" +#include "openssl/cmac.h" +#include "openssl/evp.h" +#include "openssl/hmac.h" #include "openssl/rand.h" #include "openssl/sha.h" #include "wv_cdm_constants.h" @@ -65,7 +68,8 @@ typedef OEMCryptoResult (*L1_DecryptCTR_t)(OEMCrypto_SESSION session, bool is_encrypted, const uint8_t *iv, size_t offset, - const OEMCrypto_DestBufferDesc* out_buffer); + const OEMCrypto_DestBufferDesc* out_buffer, + uint8_t subsample_flags); typedef OEMCryptoResult (*L1_InstallKeybox_t)(const uint8_t *keybox, size_t keyBoxLength); typedef OEMCryptoResult (*L1_IsKeyboxValid_t)(void); @@ -363,7 +367,8 @@ OEMCryptoResult OEMCrypto_GenerateDerivedKeys(OEMCrypto_SESSION session, enc_key_context + enc_key_context_length); // Generate mac and encryption keys for current session context - if (!session_ctx->DeriveKeys(mac_ctx_str, enc_ctx_str)) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + mac_ctx_str, enc_ctx_str)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } return OEMCrypto_SUCCESS; @@ -428,12 +433,12 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, const uint8_t* signature, size_t signature_length, const uint8_t* enc_mac_key_iv, - const uint8_t* enc_mac_key, + const uint8_t* enc_mac_keys, size_t num_keys, const OEMCrypto_KeyObject* key_array) { if (level1.library) { return level1.OEMCrypto_LoadKeys(session, message, message_length, signature, - signature_length, enc_mac_key_iv, enc_mac_key, + signature_length, enc_mac_key_iv, enc_mac_keys, num_keys, key_array); } if (NO_ERROR != crypto_engine->ValidateKeybox()) { @@ -455,8 +460,8 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, } // Range check - if (!RangeCheck(message, message_length, enc_mac_key, - wvcdm::MAC_KEY_SIZE, true) || + if (!RangeCheck(message, message_length, enc_mac_keys, + 2*wvcdm::MAC_KEY_SIZE, true) || !RangeCheck(message, message_length, enc_mac_key_iv, wvcdm::KEY_IV_SIZE, true)) { LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE - range check.]"); @@ -471,9 +476,9 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, !RangeCheck(message, message_length, key_array[i].key_data_iv, wvcdm::KEY_IV_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control, - wvcdm::KEY_CONTROL_SIZE, true) || + wvcdm::KEY_CONTROL_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control_iv, - wvcdm::KEY_IV_SIZE, true)) { + wvcdm::KEY_IV_SIZE, false)) { LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE -range check %d]", i); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } @@ -521,18 +526,17 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; // enc_mac_key can be NULL if license renewal is not supported - if (enc_mac_key == NULL) return OEMCrypto_SUCCESS; + if (enc_mac_keys == NULL) return OEMCrypto_SUCCESS; - // V2 license protocol: update mac key after processing license response - const std::vector enc_mac_key_str = std::vector( - enc_mac_key, enc_mac_key + wvcdm::MAC_KEY_SIZE); + // V2.1 license protocol: update mac keys after processing license response + const std::vector enc_mac_keys_str = std::vector( + enc_mac_keys, enc_mac_keys + 2*wvcdm::MAC_KEY_SIZE); const std::vector enc_mac_key_iv_str = std::vector( enc_mac_key_iv, enc_mac_key_iv + wvcdm::KEY_IV_SIZE); - if (!session_ctx->UpdateMacKey(enc_mac_key_str, enc_mac_key_iv_str)) { + if (!session_ctx->UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - return OEMCrypto_SUCCESS; } @@ -560,7 +564,8 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, } if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0) { + signature == NULL || signature_length == 0 || + num_keys == 0) { LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return OEMCrypto_ERROR_INVALID_CONTEXT; } @@ -570,10 +575,10 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, if (!RangeCheck(message, message_length, key_array[i].key_id, key_array[i].key_id_length, true) || !RangeCheck(message, message_length, key_array[i].key_control, - wvcdm::KEY_CONTROL_SIZE, true) || + wvcdm::KEY_CONTROL_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control_iv, wvcdm::KEY_IV_SIZE, true)) { - LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE]"); + LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } } @@ -581,6 +586,7 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, // Validate message signature if (!session_ctx->ValidateMessage(message, message_length, signature, signature_length)) { + LOGE("[OEMCrypto_RefreshKeys(): signature was invalid]"); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } @@ -590,24 +596,28 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, std::vector key_control; std::vector key_control_iv; for (unsigned int i = 0; i < num_keys; i++) { - // TODO(gmorgan): key_id may be null if special control key type (TBS) if (key_array[i].key_id != NULL) { key_id.assign(key_array[i].key_id, key_array[i].key_id + key_array[i].key_id_length); - } else { - key_id.clear(); - } - if (key_array[i].key_control != NULL) { key_control.assign(key_array[i].key_control, key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE); - key_control_iv.assign(key_array[i].key_control_iv, - key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE); + if (key_array[i].key_control_iv == NULL ) { + key_control_iv.clear(); + } else { + key_control_iv.assign(key_array[i].key_control_iv, + key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE); + } } else { - key_control.clear(); + // key_id could be null if special control key type + // key_control is not encrypted in this case + key_id.clear(); key_control_iv.clear(); + key_control.assign(key_array[i].key_control, + key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE); } if (!session_ctx->RefreshKey(key_id, key_control, key_control_iv)) { + LOGE("[OEMCrypto_RefreshKeys(): error in key %i]", i); status = false; break; } @@ -638,8 +648,8 @@ OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, return OEMCrypto_ERROR_INVALID_SESSION; } - const std::vector key_id_str = std::vector(key_id, key_id + key_id_length); - if (!session_ctx->SelectContentKey(key_id_str)) { + const std::vector key_id_vec = std::vector(key_id, key_id + key_id_length); + if (!session_ctx->SelectContentKey(key_id_vec)) { LOGE("[OEMCrypto_SelectKey(): FAIL]"); return OEMCrypto_ERROR_NO_CONTENT_KEY; } @@ -653,14 +663,16 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, size_t data_length, bool is_encrypted, const uint8_t* iv, - size_t offset, - const OEMCrypto_DestBufferDesc* out_buffer) { + size_t block_offset, + const OEMCrypto_DestBufferDesc* out_buffer, + uint8_t subsample_flags) { if (level1.library) { return level1.OEMCrypto_DecryptCTR( session, data_addr, data_length, - is_encrypted, iv, offset, out_buffer); + is_encrypted, iv, block_offset, + out_buffer, subsample_flags); } wvoec_mock::BufferType buffer_type = kBufferTypeDirect; - void* destination = NULL; + uint8_t* destination = NULL; size_t max_length = 0; switch (out_buffer->type) { case OEMCrypto_BufferType_Clear: @@ -670,7 +682,8 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, break; case OEMCrypto_BufferType_Secure: buffer_type = kBufferTypeSecure; - destination = out_buffer->buffer.secure.handle; + destination = ((uint8_t*)out_buffer->buffer.secure.handle + + out_buffer->buffer.secure.offset); max_length = out_buffer->buffer.secure.max_length; break; default: @@ -685,10 +698,12 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, return OEMCrypto_ERROR_SHORT_BUFFER; } +#ifndef NDEBUG if (NO_ERROR != crypto_engine->ValidateKeybox()) { LOGE("[OEMCrypto_DecryptCTR(): ERROR_KEYBOX_INVALID]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } +#endif SessionContext* session_ctx = crypto_engine->FindSession(session); if (!session_ctx || !session_ctx->isValid()) { @@ -702,11 +717,11 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, return OEMCrypto_ERROR_INVALID_CONTEXT; } - if (!crypto_engine->DecryptCTR(session_ctx, iv, (int)offset, + if (!crypto_engine->DecryptCTR(session_ctx, iv, (int)block_offset, data_addr, data_length, is_encrypted, destination, buffer_type)) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; + LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_DECRYPT_FAILED]"); + return OEMCrypto_ERROR_DECRYPT_FAILED; } return OEMCrypto_SUCCESS; @@ -744,20 +759,20 @@ OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, if (level1.library) { return level1.OEMCrypto_GetDeviceID(deviceID, idLength); } - std::vector dev_id_string = crypto_engine->keybox().device_id(); - if (dev_id_string.empty()) { + std::vector dev_id_vec = crypto_engine->keybox().device_id(); + if (dev_id_vec.empty()) { LOGE("[OEMCrypto_GetDeviceId(): Keybox Invalid]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } - size_t dev_id_len = dev_id_string.size(); + size_t dev_id_len = dev_id_vec.size(); if (*idLength < dev_id_len) { *idLength = dev_id_len; LOGE("[OEMCrypto_GetDeviceId(): ERROR_SHORT_BUFFER]"); return OEMCrypto_ERROR_SHORT_BUFFER; } memset(deviceID, 0, *idLength); - memcpy(deviceID, &dev_id_string[0], dev_id_len); + memcpy(deviceID, &dev_id_vec[0], dev_id_len); *idLength = dev_id_len; LOGD("[OEMCrypto_GetDeviceId(): success]"); return OEMCrypto_SUCCESS; @@ -889,46 +904,73 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, } session_ctx->FlushNonces(); - // Decrypt key and verify signature. - if (!session_ctx->LoadRSAKey(enc_rsa_key, enc_rsa_key_length, - enc_rsa_key_iv, message, message_length, - signature, signature_length)) { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; + // Decrypt RSA key. + uint8_t* pkcs8_rsa_key = new uint8_t[enc_rsa_key_length]; + OEMCryptoResult result = OEMCrypto_SUCCESS; + if (!session_ctx->DecryptRSAKey(enc_rsa_key, enc_rsa_key_length, + enc_rsa_key_iv, pkcs8_rsa_key)) { + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; + if( result == OEMCrypto_SUCCESS) { + if (padding > 16) { + LOGE("[RewrapRSAKey(): Encrypted RSA has bad padding: %d]", padding); + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + size_t rsa_key_length = enc_rsa_key_length - padding; + // verify signature, verify RSA key, and load it. + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->LoadRSAKey(pkcs8_rsa_key, rsa_key_length, + message, message_length, + signature, signature_length)) { + result = OEMCrypto_ERROR_SIGNATURE_FAILURE; // return OEMCrypto_ERROR_INVALID_RSA_KEY; + } } // Now we generate a wrapped keybox. WrappedRSAKey* wrapped = reinterpret_cast(wrapped_rsa_key); // Pick a random context and IV for generating keys. - if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } - if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const std::vector mac_ctx_str(wrapped->context, - wrapped->context + sizeof(wrapped->context)); + const std::vector context(wrapped->context, + wrapped->context + sizeof(wrapped->context)); // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(mac_ctx_str, mac_ctx_str)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + context, context)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } // Encrypt rsa key with keybox. - if (!session_ctx->EncryptRSAKey(wrapped->enc_rsa_key, - enc_rsa_key_length, - wrapped->iv)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->EncryptRSAKey(pkcs8_rsa_key, enc_rsa_key_length, + wrapped->iv, wrapped->enc_rsa_key)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } + delete[] pkcs8_rsa_key; - size_t sig_length = sizeof(wrapped->signature); - if (!session_ctx->GenerateSignature(wrapped->context, // start signing here. - buffer_size - sizeof(wrapped->signature), - wrapped->signature, - &sig_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + // The wrapped keybox must be signed with the same key we verify with. I'll + // pick the server key, so I don't have to modify LoadRSAKey. + if( result == OEMCrypto_SUCCESS) { + size_t sig_length = sizeof(wrapped->signature); + if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0], + SHA256_DIGEST_LENGTH, wrapped->context, + buffer_size - sizeof(wrapped->signature), wrapped->signature, + &sig_length)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } - - return OEMCrypto_SUCCESS; + return result; } extern "C" @@ -942,40 +984,60 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, return level1.OEMCrypto_LoadDeviceRSAKey( session, wrapped_rsa_key, wrapped_rsa_key_length); } - const WrappedRSAKey* wrapped - = reinterpret_cast(wrapped_rsa_key); if (wrapped_rsa_key == NULL) { LOGE("[OEMCrypto_LoadDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return OEMCrypto_ERROR_INVALID_CONTEXT; } + const WrappedRSAKey* wrapped + = reinterpret_cast(wrapped_rsa_key); if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); + LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } SessionContext* session_ctx = crypto_engine->FindSession(session); if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); + LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); return OEMCrypto_ERROR_INVALID_SESSION; } - const std::vector mac_ctx_str(wrapped->context, - wrapped->context + sizeof(wrapped->context)); + const std::vector context(wrapped->context, + wrapped->context + sizeof(wrapped->context)); // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(mac_ctx_str, mac_ctx_str)) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + context, context)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - // Decrypt key and verify signature. - if (!session_ctx->LoadRSAKey(wrapped->enc_rsa_key, - wrapped_rsa_key_length - sizeof(WrappedRSAKey), - wrapped->iv, - wrapped->context, - wrapped_rsa_key_length - sizeof(wrapped->signature), - wrapped->signature, - sizeof(wrapped->signature))) { - return OEMCrypto_ERROR_INVALID_RSA_KEY; + // Decrypt RSA key. + uint8_t* pkcs8_rsa_key = new uint8_t[wrapped_rsa_key_length + - sizeof(wrapped->signature)]; + size_t enc_rsa_key_length = wrapped_rsa_key_length - sizeof(WrappedRSAKey); + OEMCryptoResult result = OEMCrypto_SUCCESS; + if (!session_ctx->DecryptRSAKey(wrapped->enc_rsa_key, enc_rsa_key_length, + wrapped->iv, pkcs8_rsa_key)) { + result = OEMCrypto_ERROR_INVALID_RSA_KEY; } - return OEMCrypto_SUCCESS; + size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; + if( result == OEMCrypto_SUCCESS) { + if (padding > 16) { + LOGE("[LoadDeviceRSAKey(): Encrypted RSA has bad padding: %d]", padding); + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + size_t rsa_key_length = enc_rsa_key_length - padding; + // verify signature. + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->LoadRSAKey(pkcs8_rsa_key, rsa_key_length, + wrapped->context, + wrapped_rsa_key_length - sizeof(wrapped->signature), + wrapped->signature, + sizeof(wrapped->signature))) { + result = OEMCrypto_ERROR_SIGNATURE_FAILURE; + // return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + delete[] pkcs8_rsa_key; + return result; } extern "C" @@ -1058,15 +1120,15 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(OEMCrypto_SESSION session, return OEMCrypto_ERROR_INVALID_SESSION; } - const std::vector ssn_key_str(enc_session_key, + const std::vector ssn_key_vec(enc_session_key, enc_session_key + enc_session_key_length); - const std::vector mac_ctx_str(mac_key_context, + const std::vector mac_ctx_vec(mac_key_context, mac_key_context + mac_key_context_length); - const std::vector enc_ctx_str(enc_key_context, + const std::vector enc_ctx_vec(enc_key_context, enc_key_context + enc_key_context_length); // Generate mac and encryption keys for current session context - if (!session_ctx->RSADeriveKeys(ssn_key_str, mac_ctx_str, enc_ctx_str)) { + if (!session_ctx->RSADeriveKeys(ssn_key_vec, mac_ctx_vec, enc_ctx_vec)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } return OEMCrypto_SUCCESS; diff --git a/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp b/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp index 184eab2a..47cacee3 100644 --- a/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp +++ b/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp @@ -130,4 +130,4 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) { "WVCryptoPlugin decrypted the wrong number of bytes"; EXPECT_EQ(0u, errorDetailMessage.size()) << "WVCryptoPlugin reported a detailed error message."; -} +} \ No newline at end of file diff --git a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h index 97253c32..db08880d 100644 --- a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h +++ b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h @@ -16,9 +16,9 @@ extern "C" { #endif -#define OEMCRYPTO_VERSION "7.0" +#define OEMCRYPTO_VERSION "8.0" static const char oec_version[] = OEMCRYPTO_VERSION; -static const uint32_t oec_latest_version = 7; +static const uint32_t oec_latest_version = 8; typedef uint32_t OEMCrypto_SESSION; @@ -187,6 +187,12 @@ typedef enum OEMCrypto_Algorithm { OEMCrypto_HMAC_SHA256 = 1, } OEMCrypto_Algorithm; +/* + * Flags indicating data endpoints in OEMCrypto_DecryptCTR. + */ +#define OEMCrypto_FirstSubsample 1 +#define OEMCrypto_LastSubsample 2 + /* Obfuscation Renames. */ #define OEMCrypto_Initialize _oecc01 #define OEMCrypto_Terminate _oecc02 @@ -214,7 +220,7 @@ typedef enum OEMCrypto_Algorithm { #define OEMCrypto_Generic_Encrypt _oecc24 #define OEMCrypto_Generic_Decrypt _oecc25 #define OEMCrypto_Generic_Sign _oecc26 -#define OEMCrypto_Generic_Virify _oecc27 +#define OEMCrypto_Generic_Verify _oecc27 /* * OEMCrypto_Initialize @@ -313,16 +319,17 @@ OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session); * OEMCrypto_GenerateDerivedKeys * * Description: - * Generates a pair of secondary keys, mac_key and encrypt_key, for handling - * signing and content key decryption under the license server protocol - * for AES CTR mode. + * Generates three secondary keys -- mac_key_server, mac_key_client, and + * encrypt_key -- for handling signing and content key decryption under the + * license server protocol for AES CTR mode. * - * Refer to document "OEMCrypto Changes for V2 License Protocol" for details. - * This function computes the AES-128-CMAC of the enc_key_context and stores - * it in secure memory as the encrypt_key. - * It then computes two cycles of AES-128-CMAC of the mac_key_context and - * stores it in the mac_key. These two keys will be stored until the next - * call to LoadKeys. + * Refer to document "Widevine Modular DRM Security Integration Guide for + * CENC" for details. This function computes the AES-128-CMAC of the + * enc_key_context and stores it in secure memory as the encrypt_key. It + * then computes four cycles of AES-128-CMAC of the mac_key_context and + * stores it in the mac_keys. The first two cycles are used for + * mac_key_server and the second two cycles are used for mac_key_client. + * These three keys will be stored until the next call to LoadKeys. * * Parameters: * session (in) - crypto session identifier. @@ -334,7 +341,8 @@ OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session); * enc_key_context_length (in) - length of the encryption key context data. * * Results: - * mac_key: the 256 bit mac key is generated and stored in secure memory. + * mac_key_server: the 256 bit mac key is generated and stored in secure memory. + * mac_key_client: the 256 bit mac key is generated and stored in secure memory. * enc_key: the 128 bit encryption key is generated and stored in secure memory. * * Threading: @@ -349,7 +357,7 @@ OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session); * OEMCrypto_ERROR_INVALID_CONTEXT * * Version: - * This method changed in API version 5. + * This method changed in API version 8. */ OEMCryptoResult OEMCrypto_GenerateDerivedKeys( OEMCrypto_SESSION session, @@ -366,8 +374,8 @@ OEMCryptoResult OEMCrypto_GenerateDerivedKeys( * control block. The nonce is stored in secure memory and will be used * for the next call to LoadKeys. * - * Refer to documents "OEMCrypto Changes for V2 License Protocol" and "Key - * Control Block Definition" for details. + * Refer to documents "Widevine Modular DRM Security Integration Guide for + * CENC". * * Parameters: * session (in) - crypto session identifier. @@ -399,12 +407,13 @@ OEMCryptoResult OEMCrypto_GenerateNonce( * * Description: * Generates a HMAC-SHA256 signature for license request signing under the - * license server protocol for AES CTR mode. + * license server protocol for AES CTR mode. This uses the key mac_key_client. * - * NOTE: OEMCrypto_GenerateDerivedKeys() must be called first to establish the - * mac_key + * NOTE: OEMCrypto_GenerateDerivedKeys() must be called first to establish the + * mac_key_client. * - * Refer to document "OEMCrypto Changes for V2 License Protocol" for details. + * Refer to document "Widevine Modular DRM Security Integration Guide for + * CENC" for details. * * Parameters: * session (in) - crypto session identifier. @@ -444,10 +453,10 @@ OEMCryptoResult OEMCrypto_GenerateSignature( * * The relevant fields have been extracted from the License Response protocol * message, but the entire message and associated signature are provided so - * the message can be verified (using HMAC-SHA256 with the derived mac_key). - * If the signature verification fails, ignore all other arguments and return - * OEMCrypto_ERROR_SIGNATURE_FAILURE. Otherwise, add the keys to the session - * context. + * the message can be verified (using HMAC-SHA256 with the derived + * mac_key_server). If the signature verification fails, ignore all other + * arguments and return OEMCrypto_ERROR_SIGNATURE_FAILURE. Otherwise, add the + * keys to the session context. * * The keys will be decrypted using the current encrypt_key (AES-128-CBC) and * the IV given in the KeyObject. Each key control block will be decrypted @@ -461,20 +470,21 @@ OEMCryptoResult OEMCrypto_GenerateSignature( * block is different from the current nonce, return * OEMCrypto_ERROR_INVALID_NONCE. In that case, do not install any keys. * - * The new mac_key is decrypted with the current encrypt_key and the offered - * IV. It replaces the current mac_key. + * The new mac_keys are decrypted with the current encrypt_key and the offered + * IV. They replace the current mac_keys. * - * The mac_key and encrypt_key were generated and stored by the previous call + * The mac_keys and encrypt_key were generated and stored by the previous call * to OEMCrypto_GenerateDerivedKeys(). The nonce was generated and stored by * the previous call to OEMCrypto_GenerateNonce(). * * This session’s elapsed time clock is started at 0. The clock will be used * in OEMCrypto_DecryptCTR. * - * NOTE: OEMCrypto_GenerateDerivedKeys() must be called first to establish the - * mac_key and encrypt_key. + * NOTE: OEMCrypto_GenerateDerivedKeys() must be called first to establish + * the mac_keys and encrypt_key. * - * Refer to document "OEMCrypto Changes for V2 License Protocol" for details. + * Refer to document "Widevine Modular DRM Security Integration Guide for + * CENC" for details. * * Parameters: * session (in) - crypto session identifier. @@ -482,9 +492,9 @@ OEMCryptoResult OEMCrypto_GenerateSignature( * message_length (in) - length of the message. * signature (in) - pointer to memory containing the signature. * signature_length (in) - length of the signature. - * enc_mac_key_iv (in) - IV for decrypting new mac_key. Size is 128 bits. - * enc_mac_key (in) - encrypted mac_key for generating new mac_key. Size is - * 256 bits. + * enc_mac_keys_iv (in) - IV for decrypting new mac_key. Size is 128 bits. + * enc_mac_keys (in) - encrypted mac_keys for generating new mac_keys. Size is + * 512 bits. * num_keys (in) - number of keys present. * key_array (in) - set of keys to be installed. * @@ -503,15 +513,15 @@ OEMCryptoResult OEMCrypto_GenerateSignature( * OEMCrypto_ERROR_TOO_MANY_KEYS * * Version: - * This method changed in API version 5. + * This method changed in API version 8. */ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, const uint8_t* signature, size_t signature_length, - const uint8_t* enc_mac_key_iv, - const uint8_t* enc_mac_key, + const uint8_t* enc_mac_keys_iv, + const uint8_t* enc_mac_keys, size_t num_keys, const OEMCrypto_KeyObject* key_array); @@ -524,15 +534,16 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, * * The relevant fields have been extracted from the Renewal Response protocol * message, but the entire message and associated signature are provided so - * the message can be verified (using HMAC-SHA256 with the current mac_key). - * If the signature verification fails, ignore all other arguments and return - * OEMCrypto_ERROR_SIGNATURE_FAILURE. Otherwise, add the keys to the session - * context. + * the message can be verified (using HMAC-SHA256 with the current + * mac_key_server). If the signature verification fails, ignore all other + * arguments and return OEMCrypto_ERROR_SIGNATURE_FAILURE. Otherwise, add + * the keys to the session context. * - * NOTE: OEMCrypto_GenerateDerivedKeys() or OEMCrypto_LoadKeys() must be called - * first to establish the mac_key + * NOTE: OEMCrypto_GenerateDerivedKeys() or OEMCrypto_LoadKeys() must be + * called first to establish the mac_keys. * - * Refer to document OEMCrypto Changes for V2 License Protocol for details. + * Refer to document "Widevine Modular DRM Security Integration Guide for + * CENC" for details. * * Parameters: * session (in) - crypto session identifier. @@ -557,7 +568,7 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, * OEMCrypto_ERROR_SIGNATURE_FAILURE * * Version: - * This method changed in API version 5. + * This method changed in API version 8. */ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, @@ -614,7 +625,7 @@ OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, * OEMCrypto_ERROR_KEYBOX_INVALID cannot decrypt and read from Keybox * * Version: - * This method changed in API version 5. + * This method changed in API version 8. */ OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, const uint8_t* key_id, @@ -649,6 +660,10 @@ OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, * out_buffer (in) - A caller-owned descriptor that specifies the * handling of the decrypted byte stream. See OEMCrypto_DestbufferDesc * for details. + * subsample_flags (in) - bitwise flags indicating if this is the first, + * middle, or last subsample in a chunk of data. 1 = first subsample, + * 2 = last subsample, 3 = both first and last subsample, 0 = neither + * first nor last subsample. * * AES CTR is a stream cipher. The stream may be composed of arbitrary- * length clear and encrypted segments. The encrypted portions of a sample @@ -678,6 +693,15 @@ OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, * zero when it reaches its maximum value (0xFFFFFFFFFFFFFFFF). * The upper 64 bits (byte 0-7) of the IV do not change. * + * This method may be called several times before the decrypted data is used. + * For this reason, the parameter subsample_flags may be used to optimize + * decryption. The first buffer in a chunk of data will have the + * OEMCrypto_FirstSubsample bit set in subsample_flags. The last buffer in a + * chunk of data will have the OEMCrypto_LastSubsample bit set in + * subsample_flags. The decrypted data will not be used until after + * OEMCrypto_LastSubsample has been set. If an implementation decrypts data + * immediately, it may ignore subsample_flags. + * * Threading: * This function may be called simultaneously with functions on other sessions, * but not with other functions on this session. @@ -699,7 +723,8 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, bool is_encrypted, const uint8_t *iv, size_t block_offset, - const OEMCrypto_DestBufferDesc* out_buffer); + const OEMCrypto_DestBufferDesc* out_buffer, + uint8_t subsample_flags); /* * OEMCrypto_InstallKeybox @@ -886,7 +911,8 @@ OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox, * private key is decrypted and stored in secure memory. The RSA key is then * re-encrypted for storage on the filesystem. The OEM may either encrypt it * with the private key from the Widevine Keybox, or with an OEM specific - * device key. + * device key. The signature of the message is verified with the + * mac_key_server. * * Parameters: * session (in) - crypto session identifier. @@ -894,13 +920,13 @@ OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox, * - verified. * message_length (in) - length of the message, in bytes. * signature (in) - pointer to memory containing the HMAC-SHA256 - * - signature for - * - message, received from the provisioning server. + * - signature for message, received from the + * - provisioning server. * signature_length (in) - length of the signature, in bytes. * nonce (in) - The nonce provided in the provisioning response. * enc_rsa_key (in) - Encrypted device private RSA key received from - * - the provisioning server. Format is PKCS#1, binary - * - DER encoded, and encrypted with the derived + * - the provisioning server. Format is PKCS#8 + * - PrivateKeyInfo, encrypted with the derived * - encryption key, using AES-128-CBC with PKCS#5 * - padding. * enc_rsa_key_length (in) - length of the encrypted RSA key, in bytes. @@ -909,8 +935,6 @@ OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox, * - should be stored. May be null on the first call * - in order to find required buffer size. * wrapped_rsa_key_length (in/out) - length of the encrypted RSA key, in bytes. - * wrapped_rsa_key_iv (out) - IV for encrypting/decrypting the RSA private key. - * - Size is 128 bits. * * Returns: * OEMCrypto_SUCCESS success @@ -923,7 +947,7 @@ OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox, * OEMCrypto_ERROR_SHORT_BUFFER * * Version: - * This method changed in API versions 6. + * This method changed in API versions 8. */ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, @@ -950,7 +974,7 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, * Parameters: * session (in) - crypto session identifier. * wrapped_rsa_key (in) - wrapped device RSA key stored on the device. - * - Format is PKCS#1, binary DER encoded, and + * - Format is PKCS#8 PrivateKeyInfo, and * - encrypted with a key internal to the OEMCrypto * - instance, using AES-128-CBC with PKCS#5 * - padding. This is the wrapped key generated @@ -1016,16 +1040,16 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session, * OEMCrypto_DeriveKeysFromSessionKey * * Description: - * Generates a pair of secondary keys, mac_key and encrypt_key, for handling - * signing and content key decryption under the license server protocol for - * AES CTR mode. + * Generates three secondary keys -- mac_key_server, mac_key_client, and + * encrypt_key -- for handling signing and content key decryption under the + * license server protocol for AES CTR mode. * * This function is similar to OEMCrypto_GenerateDerivedKeys, except that it * uses a session key to generate the secondary keys instead of the Widevine * Keybox device key. These two keys will be stored in secure memory until * the next call to LoadKeys. The session key is passed in encrypted by the * device RSA public key, and must be decrypted with the RSA private key - * before use. Once the enc_key and mac_key have been generated, all calls + * before use. Once the enc_key and mac_keys have been generated, all calls * to LoadKeys and RefreshKeys proceed in the same manner for license * requests using RSA or using a Widevine keybox token. * @@ -1050,7 +1074,7 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session, * OEMCrypto_ERROR_INVALID_CONTEXT * * Version: - * This method changed in API version 6. + * This method changed in API version 8. */ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(OEMCrypto_SESSION session, const uint8_t* enc_session_key, diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp index a7711df7..6b7885f0 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp @@ -15,6 +15,7 @@ #include "log.h" #include "oemcrypto_key_mock.h" #include "openssl/aes.h" +#include "openssl/bio.h" #include "openssl/cmac.h" #include "openssl/err.h" #include "openssl/evp.h" @@ -22,6 +23,7 @@ #include "openssl/rand.h" #include #include "openssl/sha.h" +#include "openssl/x509.h" #include "string_conversions.h" #include "wv_cdm_constants.h" @@ -75,6 +77,15 @@ void SessionKeyTable::Remove(const KeyId key_id) { } } +bool SessionKeyTable::UpdateDuration(const KeyControlBlock& control) { + for(KeyMap::iterator it = keys_.begin(); it != keys_.end(); ++it) { + if (!it->second->UpdateDuration(control)) { + return false; + } + } + return true; +} + void SessionContext::Open() { } @@ -86,7 +97,7 @@ bool SessionContext::DeriveKey(const std::vector& key, const std::vector& context, int counter, std::vector* out) { - if (key.empty() || counter > 2 || context.empty() || out == NULL) { + if (key.empty() || counter > 4 || context.empty() || out == NULL) { LOGE("[DeriveKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return false; } @@ -122,34 +133,45 @@ bool SessionContext::DeriveKey(const std::vector& key, return true; } -bool SessionContext::DeriveKeys(const std::vector& mac_key_context, +bool SessionContext::DeriveKeys(const std::vector& master_key, + const std::vector& mac_key_context, const std::vector& enc_key_context) { // Generate derived key for mac key - std::vector device_key = ce_->keybox().device_key().value(); - std::vector mac_key; + std::vector mac_key_server; + std::vector mac_key_client; std::vector mac_key_part2; - if (!DeriveKey(device_key, mac_key_context, 1, &mac_key)) { + if (!DeriveKey(master_key, mac_key_context, 1, &mac_key_server)) { return false; } - if (!DeriveKey(device_key, mac_key_context, 2, &mac_key_part2)) { + if (!DeriveKey(master_key, mac_key_context, 2, &mac_key_part2)) { return false; } - mac_key.insert(mac_key.end(), mac_key_part2.begin(), mac_key_part2.end()); + mac_key_server.insert(mac_key_server.end(), mac_key_part2.begin(), mac_key_part2.end()); + + if (!DeriveKey(master_key, mac_key_context, 3, &mac_key_client)) { + return false; + } + if (!DeriveKey(master_key, mac_key_context, 4, &mac_key_part2)) { + return false; + } + mac_key_client.insert(mac_key_client.end(), mac_key_part2.begin(), mac_key_part2.end()); // Generate derived key for encryption key std::vector enc_key; - if (!DeriveKey(device_key, enc_key_context, 1, &enc_key)) { + if (!DeriveKey(master_key, enc_key_context, 1, &enc_key)) { return false; } #if 0 // Print Derived Keys to stdout. std::cout << " mac_key_context = " << wvcdm::b2a_hex(mac_key_context) << std::endl; std::cout << " enc_key_context = " << wvcdm::b2a_hex(enc_key_context) << std::endl; - std::cout << " mac_key = " << wvcdm::b2a_hex(mac_key) << std::endl; + std::cout << " mac_key_server = " << wvcdm::b2a_hex(mac_key_server) << std::endl; + std::cout << " mac_key_client = " << wvcdm::b2a_hex(mac_key_client) << std::endl; std::cout << " enc_key = " << wvcdm::b2a_hex(enc_key) << std::endl; #endif - set_mac_key(mac_key); + set_mac_key_server(mac_key_server); + set_mac_key_client(mac_key_client); set_encryption_key(enc_key); return true; } @@ -185,38 +207,7 @@ bool SessionContext::RSADeriveKeys(const std::vector& enc_session_key, session_key_.clear(); return false; } - - // Generate derived key for mac key - std::vector mac_key; - std::vector mac_key_part2; - if (!DeriveKey(session_key_, mac_key_context, 1, &mac_key)) { - session_key_.clear(); - return false; - } - if (!DeriveKey(session_key_, mac_key_context, 2, &mac_key_part2)) { - session_key_.clear(); - return false; - } - mac_key.insert(mac_key.end(), mac_key_part2.begin(), mac_key_part2.end()); - - // Generate derived key for encryption key - std::vector enc_key; - if (!DeriveKey(session_key_, enc_key_context, 1, &enc_key)) { - session_key_.clear(); - return false; - } - -#if 0 // Print Derived Keys to stdout. - std::cout << " mac_key_context = " << wvcdm::b2a_hex(mac_key_context) << std::endl; - std::cout << " enc_key_context = " << wvcdm::b2a_hex(enc_key_context) << std::endl; - std::cout << " session_key = " << wvcdm::b2a_hex(session_key_) << std::endl; - std::cout << " mac_key = " << wvcdm::b2a_hex(mac_key) << std::endl; - std::cout << " enc_key = " << wvcdm::b2a_hex(enc_key) << std::endl; -#endif - - set_mac_key(mac_key); - set_encryption_key(enc_key); - return true; + return DeriveKeys(session_key_, mac_key_context, enc_key_context); } // Utility function to generate a message signature @@ -231,7 +222,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message, return false; } - if (mac_key_.empty() || mac_key_.size() != wvcdm::MAC_KEY_SIZE) { + if (mac_key_client_.empty() || mac_key_client_.size() != wvcdm::MAC_KEY_SIZE) { LOGE("[GenerateSignature(): No MAC Key]"); return false; } @@ -242,7 +233,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message, } unsigned int md_len = *signature_length; - if (HMAC(EVP_sha256(), &mac_key_[0], SHA256_DIGEST_LENGTH, + if (HMAC(EVP_sha256(), &mac_key_client_[0], SHA256_DIGEST_LENGTH, message, message_length, signature, &md_len)) { *signature_length = md_len; return true; @@ -315,8 +306,10 @@ bool SessionContext::ValidateMessage(const uint8_t* given_message, return false; } uint8_t computed_signature[SHA256_DIGEST_LENGTH]; - if (! GenerateSignature(given_message, message_length, - computed_signature, &signature_length)) { + unsigned int md_len = SHA256_DIGEST_LENGTH; + if (!HMAC(EVP_sha256(), &mac_key_server_[0], SHA256_DIGEST_LENGTH, + given_message, message_length, computed_signature, &md_len)) { + LOGE("ValidateMessage: Could not compute signature."); return false; } if (memcmp(given_signature, computed_signature, signature_length)) { @@ -336,6 +329,7 @@ bool SessionContext::ParseKeyControl( key_control_block.Invalidate(); if (key_control_string.size() < wvcdm::KEY_CONTROL_SIZE) { + LOGD("ParseKeyControl: wrong size."); return false; } if (!key_control_block.SetFromString(key_control_string)) { @@ -357,6 +351,14 @@ bool SessionContext::ParseKeyControl( LOGD(" duration: %d", key_control_block.duration()); LOGD(" nonce: %08X", key_control_block.nonce()); LOGD(" bits: %08X", key_control_block.control_bits()); + LOGD(" bit kControlAllowEncrypt %s.", + (key_control_block.control_bits() & kControlAllowEncrypt) ? "set" : "unset"); + LOGD(" bit kControlAllowDecrypt %s.", + (key_control_block.control_bits() & kControlAllowDecrypt) ? "set" : "unset"); + LOGD(" bit kControlAllowSign %s.", + (key_control_block.control_bits() & kControlAllowSign) ? "set" : "unset"); + LOGD(" bit kControlAllowVerify %s.", + (key_control_block.control_bits() & kControlAllowVerify) ? "set" : "unset"); LOGD(" bit kControlObserveDataPath %s.", (key_control_block.control_bits() & kControlObserveDataPath) ? "set" : "unset"); LOGD(" bit kControlObserveHDCP %s.", @@ -428,6 +430,7 @@ bool SessionContext::InstallKey(const KeyId& key_id, } if (!ParseKeyControl(key_control_str, key_control_block)) { + LOGE("Error parsing key control."); return false; } } @@ -437,38 +440,36 @@ bool SessionContext::InstallKey(const KeyId& key_id, return true; } -bool SessionContext::EncryptRSAKey(uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length, - uint8_t* wrapped_rsa_key_iv) { - std::vector buffer(wrapped_rsa_key_length); - uint8_t* p = &buffer[0]; - int len = i2d_RSAPrivateKey(rsa_key_, &p); - if (len < 0) { - LOGE("[EncryptRSAKey(): Could not decode rsa key]"); - dump_openssl_error(); - return false; - } - if (static_cast(len) >= wrapped_rsa_key_length) { - LOGE("[EncryptRSAKey(): padding is wrong size: len=%d, size=%zu", - len, wrapped_rsa_key_length); - return false; - } - size_t padding = wrapped_rsa_key_length - len; - memset(&buffer[len], static_cast(padding), padding); +bool SessionContext::DecryptRSAKey(const uint8_t* enc_rsa_key, + size_t enc_rsa_key_length, + const uint8_t* enc_rsa_key_iv, + uint8_t* pkcs8_rsa_key) { + // Decrypt rsa key with keybox. + uint8_t iv_buffer[ wvcdm::KEY_IV_SIZE]; + memcpy(iv_buffer, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE); + AES_KEY aes_key; + AES_set_decrypt_key(&encryption_key_[0], 128, &aes_key); + AES_cbc_encrypt(enc_rsa_key, pkcs8_rsa_key, enc_rsa_key_length, + &aes_key, iv_buffer, AES_DECRYPT); + return true; +} +bool SessionContext::EncryptRSAKey(const uint8_t* pkcs8_rsa_key, + size_t enc_rsa_key_length, + const uint8_t* enc_rsa_key_iv, + uint8_t* enc_rsa_key) { // Encrypt rsa key with keybox. uint8_t iv_buffer[ wvcdm::KEY_IV_SIZE]; - memcpy(iv_buffer, wrapped_rsa_key_iv, wvcdm::KEY_IV_SIZE); + memcpy(iv_buffer, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE); AES_KEY aes_key; AES_set_encrypt_key(&encryption_key_[0], 128, &aes_key); - AES_cbc_encrypt(&buffer[0], wrapped_rsa_key, wrapped_rsa_key_length, + AES_cbc_encrypt(pkcs8_rsa_key, enc_rsa_key, enc_rsa_key_length, &aes_key, iv_buffer, AES_ENCRYPT); return true; } -bool SessionContext::LoadRSAKey(const uint8_t* enc_rsa_key, - size_t enc_rsa_key_length, - const uint8_t* enc_rsa_key_iv, +bool SessionContext::LoadRSAKey(uint8_t* pkcs8_rsa_key, + size_t rsa_key_length, const uint8_t* message, size_t message_length, const uint8_t* signature, @@ -479,32 +480,44 @@ bool SessionContext::LoadRSAKey(const uint8_t* enc_rsa_key, LOGE("[LoadRSAKey(): Could not verify signature]"); return false; } - - uint8_t iv[wvcdm::KEY_IV_SIZE]; - uint8_t* clear = new uint8_t[enc_rsa_key_length]; - memcpy(iv, enc_rsa_key_iv, 16); - AES_KEY aes_key; - AES_set_decrypt_key(&encryption_key_[0], 128, &aes_key); - AES_cbc_encrypt(enc_rsa_key, clear, enc_rsa_key_length, &aes_key, - iv, AES_DECRYPT); - size_t padding = clear[enc_rsa_key_length - 1]; - if (padding > 16) { - LOGE("[LoadRSAKey(): Encrypted RSA has bad padding]"); - return false; - } - size_t rsa_key_length = enc_rsa_key_length - padding; - if (rsa_key_) { RSA_free(rsa_key_); rsa_key_ = NULL; } - uint8_t const* p = clear; - rsa_key_ = d2i_RSAPrivateKey(0, &p, rsa_key_length); - delete[] clear; - - if (! rsa_key_) { - LOGE("[LoadRSAKey(): Could decode unencrypted rsa key]"); - dump_openssl_error(); + BIO *bio = BIO_new_mem_buf(pkcs8_rsa_key, rsa_key_length); + if( bio == NULL ) { + LOGE("[LoadRSAKey(): Could not allocate bio buffer]"); + return false; + } + bool success = true; + PKCS8_PRIV_KEY_INFO *pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL); + if (pkcs8_pki == NULL) { + LOGE("d2i_PKCS8_PRIV_KEY_INFO_bio returned NULL."); + success = false; + } + EVP_PKEY *evp = NULL; + if (success) { + evp = EVP_PKCS82PKEY(pkcs8_pki); + if (evp == NULL) { + LOGE("EVP_PKCS82PKEY returned NULL."); + success = false; + } + } + if (success) { + rsa_key_ = EVP_PKEY_get1_RSA(evp); + if (rsa_key_ == NULL) { + LOGE("PrivateKeyInfo did not contain an RSA key."); + success = false; + } + } + if (evp != NULL) { + EVP_PKEY_free(evp); + } + if (pkcs8_pki != NULL) { + PKCS8_PRIV_KEY_INFO_free(pkcs8_pki); + } + BIO_free(bio); + if (!success) { return false; } switch (RSA_check_key(rsa_key_)) { @@ -535,7 +548,7 @@ bool SessionContext::Generic_Encrypt(const uint8_t* in_buffer, const KeyControlBlock& control = current_content_key()->control(); // Set the AES key. if (static_cast(key.size()) != AES_BLOCK_SIZE) { - LOGE("[Generic_Encrypt(): CONTENT_KEY has wrong size."); + LOGE("[Generic_Encrypt(): CONTENT_KEY has wrong size: %d",key.size()); return false; } if (!(control.control_bits() & kControlAllowEncrypt)) { @@ -590,6 +603,10 @@ bool SessionContext::Generic_Decrypt(const uint8_t* in_buffer, LOGE("[Generic_Decrypt(): control bit says not allowed."); return false; } + if (control.control_bits() & kControlDataPathSecure) { + LOGE("[Generic_Decrypt(): control bit says secure path only."); + return false; + } if (control.duration() > 0) { if (control.duration() < CurrentTimer()) { LOGE("[Generic_Decrypt(): key expired."); @@ -635,7 +652,7 @@ bool SessionContext::Generic_Sign(const uint8_t* in_buffer, const std::vector& key = current_content_key()->value(); const KeyControlBlock& control = current_content_key()->control(); if (static_cast(key.size()) != SHA256_DIGEST_LENGTH) { - LOGE("[Generic_Sign(): CONTENT_KEY has wrong size."); + LOGE("[Generic_Sign(): CONTENT_KEY has wrong size; %d", key.size()); return false; } if (!(control.control_bits() & kControlAllowSign)) { @@ -679,7 +696,7 @@ bool SessionContext::Generic_Verify(const uint8_t* in_buffer, const std::vector& key = current_content_key()->value(); const KeyControlBlock& control = current_content_key()->control(); if (static_cast(key.size()) != SHA256_DIGEST_LENGTH) { - LOGE("[Generic_Verify(): CONTENT_KEY has wrong size."); + LOGE("[Generic_Verify(): CONTENT_KEY has wrong size: %d", key.size()); return false; } if (!(control.control_bits() & kControlAllowVerify)) { @@ -711,52 +728,73 @@ bool SessionContext::RefreshKey(const KeyId& key_id, const std::vector& key_control, const std::vector& key_control_iv) { if (key_id.empty()) { - return false; + // Key control is not encrypted if key id is NULL + KeyControlBlock key_control_block(true); + if (!ParseKeyControl(key_control, key_control_block)) { + LOGD("Parse key control error."); + return false; + } + // Apply duration to all keys in this session + return session_keys_.UpdateDuration(key_control_block); } Key* content_key = session_keys_.Find(key_id); if (NULL == content_key) { + LOGD("Error: no matching content key."); return false; } - if (!key_control.empty()) { - const std::vector content_key_value = content_key->value(); + if (key_control.empty()) { + LOGD("Error: no key_control."); + return false; + } - // Decrypt encrypted key control block - // We don't actually make use of it in Oemcrypto mock, just to verify its - // validity - std::vector control; - if (key_control_iv.empty()) { - control = key_control; - } else if (!ce_->DecryptMessage(this, content_key_value, key_control_iv, - key_control, &control)) { + const std::vector content_key_value = content_key->value(); + + // Decrypt encrypted key control block + std::vector control; + if (key_control_iv.empty()) { + // TODO(fredg): get confirmation from server team this is valid. + LOGD("Key control block is NOT encrypted."); + control = key_control; + } else { + // TODO(fredg): get confirmation from server team this is valid, too. + LOGD("Key control block is encrypted."); + if (!ce_->DecryptMessage(this, content_key_value, key_control_iv, + key_control, &control)) { + LOGD("Error decrypting key control block."); return false; } + } - KeyControlBlock key_control_block; - if (!ParseKeyControl(control, key_control_block)) { - return false; - } + KeyControlBlock key_control_block(true); + if (!ParseKeyControl(control, key_control_block)) { + LOGD("Error parsing key control."); + return false; + } - if (!content_key->UpdateControl(key_control_block)) { - return false; - } + if (!content_key->UpdateDuration(key_control_block)) { + LOGD("Error updating duration."); + return false; } return true; } -bool SessionContext::UpdateMacKey(const std::vector& enc_mac_key, - const std::vector& iv) { +bool SessionContext::UpdateMacKeys(const std::vector& enc_mac_keys, + const std::vector& iv) { - // Decrypt mac key from enc_mac_key using device_key - std::vector mac_key; + // Decrypt mac key from enc_mac_key using device_keya + std::vector mac_keys; if (!ce_->DecryptMessage(this, encryption_key_, iv, - enc_mac_key, &mac_key)) { + enc_mac_keys, &mac_keys)) { return false; } - mac_key_ = mac_key; + mac_key_server_ = std::vector(mac_keys.begin(), + mac_keys.begin()+wvcdm::MAC_KEY_SIZE); + mac_key_client_ = std::vector(mac_keys.begin()+wvcdm::MAC_KEY_SIZE, + mac_keys.end()); return true; } @@ -896,7 +934,7 @@ bool CryptoEngine::DecryptCTR(SessionContext* session, // Set the AES key. if (static_cast(content_key.size()) != AES_BLOCK_SIZE) { - LOGE("[DecryptCTR(): CONTENT_KEY has wrong size."); + LOGE("[DecryptCTR(): CONTENT_KEY has wrong size: %d", content_key.size()); return false; } const uint8_t* key_u8 = &content_key[0]; diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h index 7db606b9..15783020 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h @@ -50,6 +50,7 @@ class SessionKeyTable { bool Insert(const KeyId key_id, const Key& key_data); Key* Find(const KeyId key_id); void Remove(const KeyId key_id); + bool UpdateDuration(const KeyControlBlock& control); private: KeyMap keys_; @@ -95,7 +96,8 @@ class SessionContext { bool isValid() { return valid_; } - bool DeriveKeys(const std::vector& mac_context, + bool DeriveKeys(const std::vector& master_key, + const std::vector& mac_context, const std::vector& enc_context); bool RSADeriveKeys(const std::vector& enc_session_key, const std::vector& mac_context, @@ -140,12 +142,16 @@ class SessionContext { const std::vector& key_data_iv, const std::vector& key_control, const std::vector& key_control_iv); - bool EncryptRSAKey(uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length, - uint8_t* wrapped_rsa_key_iv); - bool LoadRSAKey(const uint8_t* enc_rsa_key, - size_t enc_rsa_key_length, - const uint8_t* enc_rsa_key_iv, + bool DecryptRSAKey(const uint8_t* enc_rsa_key, + size_t enc_rsa_key_length, + const uint8_t* wrapped_rsa_key_iv, + uint8_t* pkcs8_rsa_key); + bool EncryptRSAKey(const uint8_t* pkcs8_rsa_key, + size_t enc_rsa_key_length, + const uint8_t* enc_rsa_key_iv, + uint8_t* enc_rsa_key); + bool LoadRSAKey(uint8_t* pkcs8_rsa_key, + size_t rsa_key_length, const uint8_t* message, size_t message_length, const uint8_t* signature, @@ -155,11 +161,17 @@ class SessionContext { bool RefreshKey(const KeyId& key_id, const std::vector& key_control, const std::vector& key_control_iv); - bool UpdateMacKey(const std::vector& mac_key, const std::vector& iv); + bool UpdateMacKeys(const std::vector& mac_keys, + const std::vector& iv); bool SelectContentKey(const KeyId& key_id); const Key* current_content_key(void) {return current_content_key_;} - void set_mac_key(const std::vector& mac_key) { mac_key_ = mac_key; } - const std::vector& mac_key() { return mac_key_; } + void set_mac_key_server(const std::vector& mac_key_server) { + mac_key_server_ = mac_key_server; + } + const std::vector& mac_key_server() { return mac_key_server_; } + void set_mac_key_client(const std::vector& mac_key_client) { + mac_key_client_ = mac_key_client; } + const std::vector& mac_key_client() { return mac_key_client_; } void set_encryption_key(const std::vector& enc_key) { encryption_key_ = enc_key; @@ -178,7 +190,8 @@ class SessionContext { bool valid_; CryptoEngine* ce_; SessionId id_; - std::vector mac_key_; + std::vector mac_key_server_; + std::vector mac_key_client_; std::vector encryption_key_; std::vector session_key_; const Key* current_content_key_; diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.cpp index 27f42c3e..4dd78dcd 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.cpp @@ -23,7 +23,19 @@ bool KeyControlBlock::Validate() { 0x6b63746c); return false; } - // TODO(gmorgan): validate control bits + + if (refresh_) { + if (control_bits_ & kControlObserveDataPath) { + LOGW("KCB: data_path_type set for refresh."); + } + if (control_bits_ & kControlObserveHDCP) { + LOGW("KCB: HDCP setting set for refresh."); + } + if (control_bits_ & kControlObserveCGMS) { + LOGW("KCB: CGMS setting set for refresh."); + } + } + valid_ = true; return valid_; } @@ -103,4 +115,21 @@ bool Key::setControl(const KeyControlBlock& control) { return valid_; } +bool Key::UpdateDuration(const KeyControlBlock& control) { + valid_ = false; + if (!control.valid() || !has_control_) { + LOGE("UpdateDuration: control block not valid."); + return false; + } + + control_.set_duration(control.duration()); + + if (isValidType() && !value_.empty()) { + valid_ = true; + } else { + LOGE("UpdateDuration: value or type bad."); + } + return valid_; +} + }; // namespace wvoec_eng diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.h b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.h index 845706cb..38ca7ff6 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.h +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_key_mock.h @@ -43,10 +43,8 @@ const uint32_t kControlCGMSCopyNever = (0x03); class KeyControlBlock { public: - KeyControlBlock() {} - KeyControlBlock(const std::vector& key_control_string) { - valid_ = SetFromString(key_control_string); - } + KeyControlBlock() : valid_(false) {} + KeyControlBlock(bool refresh) : valid_(false), refresh_(refresh) {} ~KeyControlBlock() {} bool SetFromString(const std::vector& key_control_string); @@ -55,6 +53,7 @@ class KeyControlBlock { bool valid() const { return valid_; } uint32_t duration() const { return duration_; } + void set_duration(uint32_t duration) { duration_ = duration; } uint32_t nonce() const { return nonce_; } uint32_t control_bits() const { return control_bits_; } @@ -63,6 +62,7 @@ class KeyControlBlock { uint32_t ExtractField(const std::vector& str, int idx); bool valid_; + bool refresh_; uint32_t verification_; uint32_t duration_; uint32_t nonce_; @@ -86,7 +86,7 @@ class Key { bool setValue(const char* key_string, size_t key_string_length); bool setType(KeyType ktype); bool setControl(const KeyControlBlock& control); - bool UpdateControl(const KeyControlBlock& control) { return true; } + bool UpdateDuration(const KeyControlBlock& control); KeyType keyType() { return type_; } const std::vector& value() const { return value_; } diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp index a6292a25..d6f52841 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp @@ -2,7 +2,7 @@ * * Copyright 2013 Google Inc. All Rights Reserved. * - * mock implementation of OEMCrypto APIs + * Reference implementation of OEMCrypto APIs * ******************************************************************************/ @@ -14,6 +14,9 @@ #include #include "log.h" #include "oemcrypto_engine_mock.h" +#include "openssl/cmac.h" +#include "openssl/evp.h" +#include "openssl/hmac.h" #include "openssl/rand.h" #include "openssl/sha.h" #include "wv_cdm_constants.h" @@ -75,8 +78,6 @@ OEMCryptoResult OEMCrypto_Initialize(void) { return OEMCrypto_ERROR_INIT_FAILED; } LOGD("[OEMCrypto_Initialize(): success]"); - LOGW("WARNING -- this is the reference implementation of OEMCrypto."); - printf("WARNING -- you are using the reference implementation of OEMCrypto.\n"); return OEMCrypto_SUCCESS; } @@ -181,12 +182,15 @@ OEMCryptoResult OEMCrypto_GenerateDerivedKeys(OEMCrypto_SESSION session, enc_key_context + enc_key_context_length); // Generate mac and encryption keys for current session context - if (!session_ctx->DeriveKeys(mac_ctx_str, enc_ctx_str)) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + mac_ctx_str, enc_ctx_str)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } if (trace_all_calls) { - dump_hex("mac_key", &session_ctx->mac_key()[0], - session_ctx->mac_key().size()); + dump_hex("mac_key_server", &session_ctx->mac_key_server()[0], + session_ctx->mac_key_server().size()); + dump_hex("mac_key_client", &session_ctx->mac_key_client()[0], + session_ctx->mac_key_client().size()); dump_hex("enc_key", &session_ctx->encryption_key()[0], session_ctx->encryption_key().size()); } @@ -257,7 +261,7 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, const uint8_t* signature, size_t signature_length, const uint8_t* enc_mac_key_iv, - const uint8_t* enc_mac_key, + const uint8_t* enc_mac_keys, size_t num_keys, const OEMCrypto_KeyObject* key_array) { if (trace_all_calls) { @@ -265,7 +269,7 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, dump_hex("message", message, message_length); dump_hex("signature", signature, signature_length); dump_hex("enc_mac_key_iv", enc_mac_key_iv, wvcdm::KEY_IV_SIZE); - dump_hex("enc_mac_key", enc_mac_key, wvcdm::MAC_KEY_SIZE); + dump_hex("enc_mac_keys", enc_mac_keys, 2*wvcdm::MAC_KEY_SIZE); for (size_t i = 0; i < num_keys; i++) { printf("key_array[%zu].key_id_length=%zu;\n", i, key_array[i].key_id_length); dump_array_part("key_array", i, "key_id", @@ -273,7 +277,7 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, dump_array_part("key_array", i, "key_data_iv", key_array[i].key_data_iv, wvcdm::KEY_IV_SIZE); dump_array_part("key_array", i, "key_data", - key_array[i].key_data, wvcdm::KEY_IV_SIZE); + key_array[i].key_data, key_array[i].key_data_length); dump_array_part("key_array", i, "key_control_iv", key_array[i].key_control_iv, wvcdm::KEY_IV_SIZE); dump_array_part("key_array", i, "key_control", @@ -300,8 +304,8 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, } // Range check - if (!RangeCheck(message, message_length, enc_mac_key, - wvcdm::MAC_KEY_SIZE, true) || + if (!RangeCheck(message, message_length, enc_mac_keys, + 2*wvcdm::MAC_KEY_SIZE, true) || !RangeCheck(message, message_length, enc_mac_key_iv, wvcdm::KEY_IV_SIZE, true)) { LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE - range check.]"); @@ -316,9 +320,9 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, !RangeCheck(message, message_length, key_array[i].key_data_iv, wvcdm::KEY_IV_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control, - wvcdm::KEY_CONTROL_SIZE, true) || + wvcdm::KEY_CONTROL_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control_iv, - wvcdm::KEY_IV_SIZE, true)) { + wvcdm::KEY_IV_SIZE, false)) { LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE -range check %d]", i); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } @@ -366,18 +370,17 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session, if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; // enc_mac_key can be NULL if license renewal is not supported - if (enc_mac_key == NULL) return OEMCrypto_SUCCESS; + if (enc_mac_keys == NULL) return OEMCrypto_SUCCESS; - // V2 license protocol: update mac key after processing license response - const std::vector enc_mac_key_str = std::vector( - enc_mac_key, enc_mac_key + wvcdm::MAC_KEY_SIZE); + // V2.1 license protocol: update mac keys after processing license response + const std::vector enc_mac_keys_str = std::vector( + enc_mac_keys, enc_mac_keys + 2*wvcdm::MAC_KEY_SIZE); const std::vector enc_mac_key_iv_str = std::vector( enc_mac_key_iv, enc_mac_key_iv + wvcdm::KEY_IV_SIZE); - if (!session_ctx->UpdateMacKey(enc_mac_key_str, enc_mac_key_iv_str)) { + if (!session_ctx->UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - return OEMCrypto_SUCCESS; } @@ -390,7 +393,7 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, size_t num_keys, const OEMCrypto_KeyRefreshObject* key_array) { if (trace_all_calls) { - printf("-- OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session,\n"); + printf("-- OEMCryptoResult OEMCrypto_RefreshKeys(num_keys=%d)\n", num_keys); } if (NO_ERROR != crypto_engine->ValidateKeybox()) { @@ -405,7 +408,8 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, } if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0) { + signature == NULL || signature_length == 0 || + num_keys == 0) { LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return OEMCrypto_ERROR_INVALID_CONTEXT; } @@ -415,10 +419,10 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, if (!RangeCheck(message, message_length, key_array[i].key_id, key_array[i].key_id_length, true) || !RangeCheck(message, message_length, key_array[i].key_control, - wvcdm::KEY_CONTROL_SIZE, true) || + wvcdm::KEY_CONTROL_SIZE, false) || !RangeCheck(message, message_length, key_array[i].key_control_iv, wvcdm::KEY_IV_SIZE, true)) { - LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE]"); + LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } } @@ -426,6 +430,7 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, // Validate message signature if (!session_ctx->ValidateMessage(message, message_length, signature, signature_length)) { + LOGE("[OEMCrypto_RefreshKeys(): signature was invalid]"); return OEMCrypto_ERROR_SIGNATURE_FAILURE; } @@ -435,24 +440,28 @@ OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, std::vector key_control; std::vector key_control_iv; for (unsigned int i = 0; i < num_keys; i++) { - // TODO(gmorgan): key_id may be null if special control key type (TBS) if (key_array[i].key_id != NULL) { key_id.assign(key_array[i].key_id, key_array[i].key_id + key_array[i].key_id_length); - } else { - key_id.clear(); - } - if (key_array[i].key_control != NULL) { key_control.assign(key_array[i].key_control, key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE); - key_control_iv.assign(key_array[i].key_control_iv, - key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE); + if (key_array[i].key_control_iv == NULL ) { + key_control_iv.clear(); + } else { + key_control_iv.assign(key_array[i].key_control_iv, + key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE); + } } else { - key_control.clear(); + // key_id could be null if special control key type + // key_control is not encrypted in this case + key_id.clear(); key_control_iv.clear(); + key_control.assign(key_array[i].key_control, + key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE); } if (!session_ctx->RefreshKey(key_id, key_control, key_control_iv)) { + LOGE("[OEMCrypto_RefreshKeys(): error in key %i]", i); status = false; break; } @@ -502,12 +511,13 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, bool is_encrypted, const uint8_t* iv, size_t block_offset, - const OEMCrypto_DestBufferDesc* out_buffer) { + const OEMCrypto_DestBufferDesc* out_buffer, + uint8_t subsample_flags) { if (trace_all_calls) { printf("-- OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session,\n"); } wvoec_mock::BufferType buffer_type = kBufferTypeDirect; - void* destination = NULL; + uint8_t* destination = NULL; size_t max_length = 0; switch (out_buffer->type) { case OEMCrypto_BufferType_Clear: @@ -517,7 +527,7 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, break; case OEMCrypto_BufferType_Secure: buffer_type = kBufferTypeSecure; - destination = (out_buffer->buffer.secure.handle + destination = ((uint8_t*)out_buffer->buffer.secure.handle + out_buffer->buffer.secure.offset); max_length = out_buffer->buffer.secure.max_length; break; @@ -735,58 +745,89 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, } session_ctx->FlushNonces(); - // Decrypt key and verify signature. - if (!session_ctx->LoadRSAKey(enc_rsa_key, enc_rsa_key_length, - enc_rsa_key_iv, message, message_length, - signature, signature_length)) { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; + // Decrypt RSA key. + uint8_t* pkcs8_rsa_key = new uint8_t[enc_rsa_key_length]; + OEMCryptoResult result = OEMCrypto_SUCCESS; + if (!session_ctx->DecryptRSAKey(enc_rsa_key, enc_rsa_key_length, + enc_rsa_key_iv, pkcs8_rsa_key)) { + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; + if( result == OEMCrypto_SUCCESS) { + if (padding > 16) { + LOGE("[RewrapRSAKey(): Encrypted RSA has bad padding: %d]", padding); + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + size_t rsa_key_length = enc_rsa_key_length - padding; + // verify signature, verify RSA key, and load it. + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->LoadRSAKey(pkcs8_rsa_key, rsa_key_length, + message, message_length, + signature, signature_length)) { + result = OEMCrypto_ERROR_SIGNATURE_FAILURE; // return OEMCrypto_ERROR_INVALID_RSA_KEY; + } } // Now we generate a wrapped keybox. WrappedRSAKey* wrapped = reinterpret_cast(wrapped_rsa_key); // Pick a random context and IV for generating keys. - if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } - if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const std::vector mac_ctx_str(wrapped->context, - wrapped->context + sizeof(wrapped->context)); + const std::vector context(wrapped->context, + wrapped->context + sizeof(wrapped->context)); // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(mac_ctx_str, mac_ctx_str)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + context, context)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } // Encrypt rsa key with keybox. - if (!session_ctx->EncryptRSAKey(wrapped->enc_rsa_key, - enc_rsa_key_length, - wrapped->iv)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->EncryptRSAKey(pkcs8_rsa_key, enc_rsa_key_length, + wrapped->iv, wrapped->enc_rsa_key)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } + delete[] pkcs8_rsa_key; - size_t sig_length = sizeof(wrapped->signature); - if (!session_ctx->GenerateSignature(wrapped->context, // start signing here. - buffer_size - sizeof(wrapped->signature), - wrapped->signature, - &sig_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + // The wrapped keybox must be signed with the same key we verify with. I'll + // pick the server key, so I don't have to modify LoadRSAKey. + if( result == OEMCrypto_SUCCESS) { + size_t sig_length = sizeof(wrapped->signature); + if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0], + SHA256_DIGEST_LENGTH, wrapped->context, + buffer_size - sizeof(wrapped->signature), wrapped->signature, + &sig_length)) { + result = OEMCrypto_ERROR_UNKNOWN_FAILURE; + } } - if (trace_all_calls) { dump_hex("wrapped_rsa_key", wrapped_rsa_key, *wrapped_rsa_key_length); dump_hex("signature", wrapped->signature, sizeof(wrapped->signature)); dump_hex("context", wrapped->context, sizeof(wrapped->context)); dump_hex("iv", wrapped->iv, sizeof(wrapped->iv)); } - return OEMCrypto_SUCCESS; + return result; } extern "C" OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, const uint8_t* wrapped_rsa_key, size_t wrapped_rsa_key_length) { + if (wrapped_rsa_key == NULL) { + LOGE("[OEMCrypto_LoadDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); + return OEMCrypto_ERROR_INVALID_CONTEXT; + } const WrappedRSAKey* wrapped = reinterpret_cast(wrapped_rsa_key); if (trace_all_calls) { @@ -796,39 +837,53 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, dump_hex("context", wrapped->context, sizeof(wrapped->context)); dump_hex("iv", wrapped->iv, sizeof(wrapped->iv)); } - - if (wrapped_rsa_key == NULL) { - LOGE("[OEMCrypto_LoadDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); + LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } SessionContext* session_ctx = crypto_engine->FindSession(session); if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); + LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); return OEMCrypto_ERROR_INVALID_SESSION; } - const std::vector mac_ctx_str(wrapped->context, - wrapped->context + sizeof(wrapped->context)); + const std::vector context(wrapped->context, + wrapped->context + sizeof(wrapped->context)); // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(mac_ctx_str, mac_ctx_str)) { + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), + context, context)) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - // Decrypt key and verify signature. - if (!session_ctx->LoadRSAKey(wrapped->enc_rsa_key, - wrapped_rsa_key_length - sizeof(WrappedRSAKey), - wrapped->iv, - wrapped->context, - wrapped_rsa_key_length - sizeof(wrapped->signature), - wrapped->signature, - sizeof(wrapped->signature))) { - return OEMCrypto_ERROR_INVALID_RSA_KEY; + // Decrypt RSA key. + uint8_t* pkcs8_rsa_key = new uint8_t[wrapped_rsa_key_length + - sizeof(wrapped->signature)]; + size_t enc_rsa_key_length = wrapped_rsa_key_length - sizeof(WrappedRSAKey); + OEMCryptoResult result = OEMCrypto_SUCCESS; + if (!session_ctx->DecryptRSAKey(wrapped->enc_rsa_key, enc_rsa_key_length, + wrapped->iv, pkcs8_rsa_key)) { + result = OEMCrypto_ERROR_INVALID_RSA_KEY; } - return OEMCrypto_SUCCESS; + size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; + if( result == OEMCrypto_SUCCESS) { + if (padding > 16) { + LOGE("[LoadDeviceRSAKey(): Encrypted RSA has bad padding: %d]", padding); + result = OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + size_t rsa_key_length = enc_rsa_key_length - padding; + // verify signature. + if( result == OEMCrypto_SUCCESS) { + if (!session_ctx->LoadRSAKey(pkcs8_rsa_key, rsa_key_length, + wrapped->context, + wrapped_rsa_key_length - sizeof(wrapped->signature), + wrapped->signature, + sizeof(wrapped->signature))) { + result = OEMCrypto_ERROR_SIGNATURE_FAILURE; + // return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + } + delete[] pkcs8_rsa_key; + return result; } extern "C" @@ -919,8 +974,10 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey( return OEMCrypto_ERROR_UNKNOWN_FAILURE; } if (trace_all_calls) { - dump_hex("mac_key", &session_ctx->mac_key()[0], - session_ctx->mac_key().size()); + dump_hex("mac_key_server", &session_ctx->mac_key_server()[0], + session_ctx->mac_key_server().size()); + dump_hex("mac_key", &session_ctx->mac_key_client()[0], + session_ctx->mac_key_client().size()); dump_hex("enc_key", &session_ctx->encryption_key()[0], session_ctx->encryption_key().size()); } diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 27a46244..f2e99e87 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -27,6 +27,18 @@ using namespace std; +namespace { +// Use random generated or static test vectors +bool g_random = true; +// Enable/disable console output of test vectors +bool g_verbose = false; + +const size_t kNumKeys = 4; +const size_t kDuration = 2; +const size_t kLongDuration = 5; +const size_t kBufferMaxLength = 256; +} + namespace wvoec { typedef struct { @@ -46,11 +58,10 @@ typedef struct { KeyControlBlock control; } MessageKeyData; -template struct MessageData { - MessageKeyData keys[kNumberKeys]; + MessageKeyData keys[kNumKeys]; uint8_t mac_key_iv[wvcdm::KEY_IV_SIZE]; - uint8_t mac_key[wvcdm::MAC_KEY_SIZE]; + uint8_t mac_keys[2*wvcdm::MAC_KEY_SIZE]; }; const size_t kMaxTestRSAKeyLength = 2000; // Rough estimate. @@ -93,282 +104,10 @@ const wvoec_mock::WidevineKeybox kDefaultKeybox = { } }; -static const uint8_t kTestRsaPrivateKey1_3072[] = { - 0x30, 0x82, 0x06, 0xe3, 0x02, 0x01, 0x00, 0x02, - 0x82, 0x01, 0x81, 0x00, 0xa5, 0x62, 0x07, 0xdf, - 0xc8, 0x84, 0x74, 0xe1, 0x2a, 0xb7, 0xbb, 0xc0, - 0x78, 0x76, 0xbe, 0x13, 0x3b, 0xe6, 0x2c, 0x09, - 0x9d, 0x35, 0x3f, 0xf3, 0x0f, 0xe9, 0x61, 0x96, - 0x20, 0x53, 0x6e, 0x78, 0x62, 0xe0, 0x10, 0xd2, - 0xca, 0xe4, 0xdd, 0xd5, 0x96, 0xaf, 0x9a, 0xd7, - 0x08, 0x47, 0xe4, 0x55, 0x1b, 0x83, 0xbe, 0x10, - 0x66, 0x74, 0x08, 0xf2, 0x49, 0x79, 0xea, 0x29, - 0x46, 0xc2, 0x65, 0x97, 0xa6, 0xcc, 0x4b, 0xa4, - 0x08, 0xc3, 0x04, 0x17, 0x01, 0xb5, 0x11, 0x53, - 0xe9, 0x68, 0x34, 0x3c, 0x26, 0x56, 0x44, 0x37, - 0x5c, 0xb4, 0x7a, 0x1d, 0x5d, 0x6c, 0x58, 0xc2, - 0x82, 0xa0, 0x92, 0xf1, 0x14, 0xf1, 0x22, 0xff, - 0x64, 0xde, 0xdf, 0xb3, 0x3d, 0x9d, 0xa5, 0x86, - 0xcd, 0xa0, 0x0a, 0x63, 0x08, 0xdd, 0x60, 0x5d, - 0xfd, 0xa4, 0x01, 0xe3, 0xb6, 0x0e, 0x85, 0xe4, - 0xc3, 0x37, 0x61, 0xd0, 0xe7, 0x12, 0xe9, 0xc4, - 0xde, 0xf2, 0x59, 0x11, 0xe3, 0x5b, 0x02, 0x9f, - 0x24, 0xb9, 0xb0, 0xbb, 0x31, 0xa0, 0xee, 0x6a, - 0x2c, 0xb4, 0x30, 0xff, 0xe0, 0xf0, 0x93, 0xee, - 0x3a, 0xae, 0xb2, 0x2e, 0x84, 0xa0, 0x47, 0x42, - 0x51, 0xbb, 0xfa, 0xbb, 0x90, 0x97, 0x2c, 0x77, - 0x45, 0xee, 0x2c, 0xfb, 0xec, 0x5d, 0xd8, 0xca, - 0x49, 0x94, 0x53, 0x5d, 0x37, 0xaf, 0x86, 0x47, - 0xda, 0xe2, 0xbd, 0xf0, 0x5f, 0x07, 0x53, 0x8a, - 0x10, 0xd0, 0x9a, 0xd0, 0x7f, 0xe9, 0xef, 0xf6, - 0xda, 0xea, 0x1e, 0x2e, 0x54, 0xec, 0x44, 0xde, - 0x3a, 0xe1, 0xc8, 0xdb, 0x17, 0xe8, 0xc9, 0x3a, - 0x81, 0x11, 0x4d, 0xb7, 0x2d, 0x09, 0x83, 0xab, - 0x30, 0xb7, 0xf5, 0x1b, 0x03, 0x86, 0x21, 0xa9, - 0xf5, 0xca, 0x15, 0x26, 0xaf, 0x39, 0xf3, 0x5d, - 0x01, 0x7d, 0xe3, 0x19, 0x54, 0xd1, 0x2e, 0x10, - 0x16, 0x9c, 0xee, 0xc3, 0xbd, 0xcc, 0xdb, 0x02, - 0x82, 0xd0, 0x60, 0x0b, 0x42, 0x72, 0x85, 0xec, - 0xdc, 0x41, 0x7c, 0xf1, 0x34, 0xd8, 0x27, 0x21, - 0xf9, 0xa6, 0x82, 0x40, 0xd3, 0xc5, 0xc9, 0xf9, - 0x6b, 0xc9, 0x12, 0x64, 0xe4, 0x3a, 0x3b, 0xc9, - 0x8f, 0x3c, 0xd0, 0x2c, 0xb8, 0xb8, 0xf3, 0x05, - 0x4a, 0xe9, 0x4c, 0x46, 0x2b, 0xb6, 0xe1, 0xed, - 0x82, 0xb2, 0xf0, 0xd1, 0x72, 0x71, 0x04, 0x35, - 0x19, 0xc1, 0x16, 0x17, 0xd6, 0x75, 0xe0, 0xab, - 0xde, 0x8f, 0xe1, 0xc1, 0x49, 0x68, 0x0c, 0xc8, - 0xce, 0x6d, 0x87, 0x50, 0x04, 0xb5, 0xd7, 0x24, - 0xf4, 0x2e, 0x0c, 0x11, 0x35, 0xb2, 0x67, 0x85, - 0x1b, 0x38, 0xff, 0x2f, 0x71, 0xf5, 0x30, 0x18, - 0x1e, 0x6f, 0xd7, 0xf0, 0x33, 0x61, 0x53, 0x7e, - 0x55, 0x7f, 0x0d, 0x60, 0x83, 0xf3, 0x8a, 0x2b, - 0x67, 0xd5, 0xf0, 0x2e, 0x23, 0x23, 0x60, 0x0b, - 0x83, 0x9c, 0xc2, 0x87, 0x02, 0x03, 0x01, 0x00, - 0x01, 0x02, 0x82, 0x01, 0x80, 0x5a, 0x09, 0x3f, - 0x9e, 0x2e, 0x4d, 0x26, 0x50, 0x7b, 0x70, 0x21, - 0xb0, 0x0c, 0x25, 0x21, 0x1f, 0xd9, 0x89, 0x5a, - 0xca, 0x35, 0x23, 0x0b, 0x58, 0xa9, 0x7d, 0xf6, - 0x19, 0xc4, 0x29, 0x87, 0xc7, 0xd4, 0x94, 0x85, - 0xb4, 0x2c, 0xaf, 0x62, 0xb1, 0xe8, 0x62, 0x5b, - 0xda, 0xdb, 0x70, 0x40, 0x37, 0xb1, 0x4e, 0x0c, - 0xc8, 0x62, 0xee, 0xa2, 0xfc, 0x3c, 0xd2, 0x39, - 0x90, 0x15, 0x2c, 0xba, 0x20, 0x50, 0xb7, 0x82, - 0x2a, 0xa0, 0x76, 0x83, 0x20, 0x7f, 0x56, 0x73, - 0x43, 0x8a, 0x9b, 0xa7, 0x6c, 0x63, 0xb6, 0xad, - 0x56, 0xb2, 0x8a, 0xb2, 0xbc, 0x8f, 0xe2, 0xef, - 0x83, 0x9d, 0x98, 0x0b, 0xc7, 0x62, 0x0e, 0x51, - 0x6e, 0x57, 0x1d, 0x1b, 0x0e, 0x3a, 0xea, 0x3b, - 0x76, 0x63, 0x35, 0xd0, 0xd1, 0xcf, 0xbe, 0xad, - 0xbb, 0x1d, 0xde, 0x0f, 0x05, 0x48, 0x55, 0x29, - 0xc1, 0xbc, 0x21, 0xc7, 0x87, 0xf2, 0x75, 0x12, - 0x7d, 0x92, 0x9e, 0xbf, 0xad, 0x04, 0x68, 0xc4, - 0xc9, 0x9d, 0x35, 0xd6, 0xa8, 0x62, 0xc1, 0x69, - 0x6a, 0xb6, 0x41, 0xb7, 0x37, 0x66, 0xdf, 0xb2, - 0xb9, 0x8c, 0x8b, 0x15, 0x08, 0x4c, 0x3d, 0xf1, - 0xed, 0x82, 0x0f, 0xe3, 0xd5, 0xff, 0x46, 0xbd, - 0xf7, 0x85, 0x43, 0xc0, 0x8b, 0xba, 0x47, 0xf1, - 0x41, 0x57, 0xc3, 0x7f, 0x8b, 0x0d, 0x48, 0xea, - 0xc2, 0xed, 0xc0, 0x69, 0x84, 0xb6, 0x32, 0x08, - 0x49, 0x74, 0x14, 0x84, 0xa4, 0x1b, 0x48, 0x5b, - 0xec, 0xd3, 0x0b, 0x12, 0x2b, 0x4c, 0x9e, 0x5c, - 0x01, 0x60, 0xad, 0xef, 0xcb, 0x2b, 0x56, 0x84, - 0x07, 0xfa, 0x62, 0xc6, 0x08, 0x92, 0x98, 0x70, - 0xc9, 0x5b, 0x18, 0xc8, 0xfa, 0x27, 0x0c, 0xe2, - 0xbd, 0xfb, 0x3e, 0x43, 0xa5, 0xb7, 0x06, 0x2c, - 0x4e, 0xf1, 0x07, 0x5d, 0x8d, 0xdd, 0x53, 0xc5, - 0x8c, 0x4a, 0xf2, 0x2f, 0x8e, 0x80, 0x96, 0x16, - 0xc0, 0xfc, 0xf9, 0x20, 0x4f, 0x35, 0xc7, 0x53, - 0x8b, 0x2d, 0x37, 0x43, 0x93, 0x3d, 0x74, 0x3f, - 0x63, 0xf7, 0x0b, 0xbd, 0x46, 0xe4, 0x51, 0x67, - 0x33, 0x57, 0x15, 0xf5, 0x59, 0x27, 0x66, 0xe8, - 0xe2, 0x4b, 0xa3, 0x93, 0x03, 0x8a, 0x9c, 0x05, - 0x13, 0xf2, 0xcb, 0xf7, 0x9c, 0x68, 0xe7, 0x16, - 0x4b, 0x8e, 0x59, 0x71, 0x2b, 0x73, 0x9b, 0xb9, - 0xae, 0x50, 0xfa, 0xd7, 0xd3, 0x34, 0x17, 0x1d, - 0x62, 0x88, 0xbd, 0x8c, 0xba, 0x5a, 0x6b, 0x6a, - 0x5e, 0xb3, 0xa5, 0x80, 0xca, 0xbb, 0xb9, 0xb5, - 0xa8, 0x2e, 0xb1, 0x61, 0x6e, 0xd5, 0xd6, 0x62, - 0x98, 0x4a, 0xb0, 0xb8, 0x76, 0xa9, 0x19, 0x5c, - 0xe2, 0xbe, 0xb3, 0x9b, 0x4a, 0x39, 0xf5, 0xe6, - 0xbb, 0x11, 0x6e, 0x13, 0x13, 0x38, 0xb8, 0x1f, - 0x21, 0x19, 0xf5, 0xa7, 0x76, 0x93, 0xb3, 0x56, - 0xfa, 0xcc, 0x74, 0xbc, 0x19, 0x02, 0x81, 0xc1, - 0x00, 0xd1, 0xd1, 0x72, 0x57, 0xe5, 0xb0, 0x1c, - 0x09, 0x05, 0xbb, 0x55, 0x89, 0x3c, 0x4a, 0x81, - 0x90, 0x9a, 0xf9, 0x32, 0x63, 0x41, 0xad, 0x6a, - 0x5f, 0x65, 0x94, 0x92, 0xcc, 0xf7, 0xc7, 0x53, - 0x93, 0xa0, 0xf7, 0xbe, 0x48, 0x82, 0x63, 0x31, - 0x7b, 0xd0, 0x82, 0x09, 0xbb, 0x0a, 0xbc, 0x60, - 0xc9, 0x4d, 0x83, 0xe4, 0x5d, 0x50, 0xe6, 0x5f, - 0x8b, 0x47, 0x07, 0xa3, 0x3a, 0x36, 0x97, 0xaa, - 0x21, 0x70, 0x7f, 0xd5, 0x6c, 0xb0, 0x56, 0xf5, - 0x5c, 0x48, 0x74, 0x2a, 0xdd, 0xfe, 0x94, 0x83, - 0x05, 0xe0, 0x3d, 0x5d, 0xdd, 0x5a, 0x05, 0xcb, - 0x47, 0xd7, 0xf9, 0x89, 0x55, 0xaa, 0x0b, 0x21, - 0xc0, 0x71, 0x5d, 0xe1, 0x4c, 0x6a, 0x45, 0x86, - 0x86, 0xf2, 0xb9, 0x38, 0x6a, 0x56, 0x51, 0x0d, - 0x7d, 0xac, 0x30, 0x31, 0xca, 0x2d, 0xaa, 0xaa, - 0xba, 0xcc, 0x12, 0x40, 0xc1, 0x0d, 0xa6, 0xc1, - 0x7d, 0x22, 0xec, 0xb6, 0x51, 0x45, 0xfe, 0x4e, - 0xbb, 0x4a, 0xd2, 0xba, 0x9b, 0xa2, 0xcc, 0x28, - 0x2b, 0x01, 0x53, 0x53, 0xf3, 0xa9, 0x5a, 0x8f, - 0xeb, 0xb7, 0xb8, 0x62, 0x6b, 0x8a, 0x79, 0x24, - 0xcc, 0x86, 0x34, 0x45, 0xe2, 0xad, 0x1d, 0xd0, - 0x4c, 0xc9, 0x77, 0x2a, 0xf9, 0x1a, 0xe8, 0x58, - 0x78, 0x51, 0x8a, 0xea, 0x3f, 0x90, 0x36, 0x46, - 0x2a, 0xc0, 0x71, 0x41, 0x83, 0x2c, 0x48, 0xee, - 0xc5, 0x02, 0x81, 0xc1, 0x00, 0xc9, 0xc8, 0xce, - 0xc4, 0x50, 0xb2, 0x26, 0xcb, 0x35, 0x78, 0x55, - 0x3c, 0xcc, 0xf0, 0x7e, 0xba, 0xad, 0xeb, 0x58, - 0xe9, 0xb5, 0x78, 0x2f, 0x43, 0x5f, 0x07, 0x47, - 0x56, 0x05, 0x41, 0x38, 0x71, 0xe1, 0x58, 0x62, - 0xb1, 0x8e, 0xbc, 0xf9, 0x80, 0x04, 0x22, 0x39, - 0x22, 0x24, 0x28, 0x86, 0x9c, 0x00, 0x44, 0x5f, - 0xc4, 0x97, 0xe6, 0x71, 0x5f, 0x1f, 0x58, 0xea, - 0x75, 0x18, 0x0c, 0x23, 0x63, 0x09, 0xc5, 0x98, - 0xc4, 0x6d, 0x23, 0xc2, 0x2c, 0x93, 0x6a, 0x26, - 0xe4, 0x3d, 0x8d, 0xa1, 0x39, 0x70, 0x34, 0x25, - 0xcd, 0xbc, 0x82, 0x78, 0x2b, 0xf3, 0x7e, 0x81, - 0xb6, 0x5f, 0xc5, 0x69, 0xd0, 0x81, 0x69, 0x50, - 0x2f, 0x17, 0x0c, 0x17, 0x3c, 0x0b, 0x45, 0x38, - 0xce, 0xe3, 0xbf, 0x8a, 0x50, 0x0a, 0x00, 0x74, - 0x7e, 0x7a, 0xd8, 0x55, 0x52, 0x6b, 0x82, 0xfb, - 0x34, 0x15, 0x73, 0x6a, 0xf4, 0x51, 0x9b, 0x9f, - 0xa0, 0x45, 0xb9, 0x76, 0xe5, 0xd3, 0xd5, 0xf4, - 0xa9, 0xa4, 0xcd, 0x42, 0x2f, 0x29, 0x89, 0xec, - 0x28, 0x5f, 0x03, 0x45, 0x27, 0xaf, 0x8c, 0x39, - 0x3e, 0x59, 0x9d, 0xaf, 0x27, 0x5d, 0x17, 0x53, - 0x17, 0xeb, 0x8d, 0x7f, 0x3d, 0xb8, 0x2a, 0x50, - 0x1e, 0xb5, 0xc5, 0x04, 0xab, 0x9c, 0xa7, 0xaa, - 0x86, 0x41, 0xb9, 0x36, 0x29, 0x9e, 0xd2, 0xd8, - 0xde, 0x5f, 0xde, 0x80, 0xdb, 0x02, 0x81, 0xc0, - 0x03, 0xf3, 0x5f, 0xa5, 0xcc, 0x0b, 0x5e, 0xdb, - 0xc4, 0xa1, 0xdc, 0x60, 0x73, 0x24, 0x2c, 0x00, - 0x5f, 0x0a, 0xa6, 0x2a, 0x3c, 0x48, 0x59, 0xa2, - 0x66, 0x35, 0x3f, 0xf6, 0x60, 0x0b, 0xfe, 0xc4, - 0xde, 0xd9, 0x0b, 0x5a, 0x2e, 0x2a, 0x53, 0xfa, - 0x32, 0xd8, 0xdf, 0xfa, 0x07, 0x9f, 0xb8, 0x6a, - 0xd1, 0xec, 0xd3, 0xd5, 0xf5, 0xfa, 0x00, 0x7e, - 0x8c, 0xdd, 0xd5, 0xf2, 0xf8, 0xa8, 0x2e, 0x69, - 0xe6, 0xc6, 0x61, 0x6c, 0x64, 0x7d, 0x9e, 0xad, - 0x18, 0x28, 0x27, 0xce, 0x7a, 0x46, 0xad, 0x98, - 0xe4, 0xba, 0x03, 0x14, 0x71, 0xe7, 0x7e, 0x06, - 0x62, 0x48, 0xae, 0x8f, 0x50, 0x5e, 0x59, 0x4a, - 0x58, 0x58, 0x1e, 0x2f, 0xe4, 0x28, 0x5e, 0xfa, - 0x17, 0x83, 0xe9, 0x4e, 0x07, 0x46, 0x0b, 0x6c, - 0xfc, 0x5b, 0x03, 0xf4, 0xfc, 0x9b, 0x24, 0x0f, - 0xd4, 0x5b, 0xdb, 0xa0, 0x46, 0xf3, 0x86, 0xdd, - 0x26, 0x55, 0x32, 0xb1, 0xa1, 0x11, 0xc2, 0xc5, - 0xc0, 0x08, 0xeb, 0xbe, 0x96, 0x78, 0x25, 0xa1, - 0x79, 0xaa, 0xe9, 0xff, 0xc2, 0x86, 0x94, 0x03, - 0x2a, 0x38, 0x6c, 0x91, 0xfd, 0xcf, 0x7e, 0x23, - 0xe3, 0xbb, 0x04, 0x3d, 0xda, 0x68, 0x9f, 0x4d, - 0x72, 0xd5, 0xad, 0x97, 0x77, 0x2c, 0x3c, 0xce, - 0x37, 0x2a, 0xd8, 0x72, 0x4d, 0xf2, 0xd7, 0xab, - 0x62, 0x68, 0x3f, 0x85, 0x8a, 0xc5, 0xec, 0xc9, - 0x02, 0x81, 0xc1, 0x00, 0x92, 0x43, 0x0c, 0x1d, - 0x20, 0xa1, 0x01, 0x9d, 0xaa, 0x54, 0x5e, 0xf4, - 0x83, 0x58, 0x8f, 0x83, 0xa1, 0x2d, 0x46, 0x75, - 0xa1, 0x24, 0x4c, 0x9d, 0xf8, 0xf3, 0xbd, 0xb1, - 0x8c, 0x7d, 0x89, 0xfc, 0x81, 0xeb, 0x1f, 0x1e, - 0xb4, 0xe8, 0x25, 0xb1, 0xb5, 0x4d, 0x59, 0x3c, - 0x76, 0x19, 0x29, 0xf9, 0x49, 0xf8, 0x45, 0xb2, - 0xaa, 0xa8, 0x4e, 0xe5, 0x34, 0x43, 0xaf, 0x2e, - 0xd1, 0x0f, 0x7b, 0x56, 0xfe, 0x6e, 0x4c, 0x1d, - 0x95, 0x3e, 0xa6, 0x30, 0xc9, 0x69, 0xd8, 0x66, - 0xf8, 0x77, 0x00, 0xb6, 0x31, 0xae, 0x9a, 0xf8, - 0x55, 0xfb, 0xfc, 0x3f, 0x5f, 0x70, 0x03, 0x75, - 0xbe, 0x55, 0xca, 0x2d, 0x68, 0xa0, 0x7d, 0x8e, - 0xa4, 0x96, 0x0f, 0x01, 0x66, 0xe9, 0xf6, 0x13, - 0x80, 0xe2, 0x05, 0xcf, 0x9e, 0x70, 0x56, 0x00, - 0x97, 0xea, 0xd7, 0x6d, 0xb6, 0xa0, 0x6a, 0x95, - 0x86, 0x36, 0xf2, 0xff, 0xc5, 0x67, 0x98, 0x7d, - 0x04, 0x0d, 0x3b, 0x31, 0xbc, 0x2b, 0x09, 0xfd, - 0x2d, 0x87, 0xda, 0xc1, 0x74, 0xca, 0x94, 0x73, - 0x6e, 0xeb, 0x5f, 0xe5, 0x34, 0x49, 0xdf, 0xf4, - 0x61, 0xe0, 0xfa, 0x64, 0xfe, 0x05, 0x3a, 0x25, - 0xcc, 0x87, 0xf4, 0x03, 0x38, 0xca, 0xf2, 0xe8, - 0x4f, 0xb9, 0x4f, 0x79, 0x55, 0x43, 0xf3, 0x46, - 0xfd, 0xbc, 0xd2, 0x95, 0xb8, 0x99, 0xfc, 0xb8, - 0xb3, 0xa5, 0x04, 0xa1, 0x02, 0x81, 0xc0, 0x47, - 0xc6, 0x9c, 0x18, 0x54, 0xe5, 0xbb, 0xf9, 0xf4, - 0x38, 0xd2, 0xc0, 0xd1, 0x1a, 0xcc, 0xdb, 0x06, - 0x87, 0x75, 0x1f, 0x13, 0xa2, 0x7f, 0x8b, 0x45, - 0x54, 0xcb, 0x43, 0xf8, 0xbb, 0x94, 0xd6, 0x2e, - 0x56, 0x5c, 0x69, 0x6d, 0x83, 0xb5, 0x45, 0x46, - 0x68, 0x5c, 0x76, 0x1e, 0x6c, 0x0c, 0x53, 0x59, - 0xcc, 0x19, 0xc7, 0x81, 0x62, 0x66, 0x92, 0x02, - 0x8f, 0xa6, 0xdb, 0x50, 0x1c, 0x67, 0xfc, 0x82, - 0x56, 0x2b, 0x4b, 0x1f, 0x97, 0x87, 0xc4, 0x7d, - 0x20, 0xda, 0xd3, 0x3f, 0x28, 0xf9, 0x55, 0xfe, - 0x84, 0x50, 0xc5, 0x3b, 0xd4, 0xaf, 0xf5, 0x3d, - 0x43, 0xce, 0xdc, 0x55, 0x11, 0x87, 0xdb, 0x72, - 0x66, 0xcc, 0x83, 0xc4, 0x8b, 0x20, 0xae, 0x59, - 0x4d, 0xeb, 0xac, 0xb5, 0x4a, 0xec, 0x66, 0x09, - 0x37, 0x55, 0x14, 0x21, 0x57, 0xff, 0x0a, 0xac, - 0xda, 0xb1, 0xae, 0x31, 0xab, 0x41, 0x30, 0x65, - 0x02, 0x83, 0xd1, 0xdb, 0x65, 0xb7, 0x52, 0xa7, - 0x21, 0x9f, 0x1f, 0x8f, 0x69, 0x23, 0x3b, 0xb8, - 0xf9, 0x6d, 0xe7, 0xc1, 0x53, 0x9f, 0x8f, 0x67, - 0xfc, 0x6e, 0x20, 0x18, 0x31, 0x89, 0xe7, 0xbb, - 0xd4, 0xc1, 0x03, 0x67, 0xd6, 0xa5, 0x76, 0xc9, - 0xea, 0x97, 0x93, 0x02, 0xca, 0x44, 0x52, 0x55, - 0x0f, 0xed, 0x55, 0xb5, 0x49, 0xd6, 0x94, 0x59, - 0xee, 0xcc, 0x1b, 0x5a, 0x00, 0x3d, 0xcd }; +/* Note: Key 1 was 3072 bits. We are only generating 2048 bit keys, + so we do not need to test with 3072 bit keys. */ -static const uint8_t kTestRsaPublicKey1_3072[] = { - 0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, 0x81, - 0x00, 0xa5, 0x62, 0x07, 0xdf, 0xc8, 0x84, 0x74, - 0xe1, 0x2a, 0xb7, 0xbb, 0xc0, 0x78, 0x76, 0xbe, - 0x13, 0x3b, 0xe6, 0x2c, 0x09, 0x9d, 0x35, 0x3f, - 0xf3, 0x0f, 0xe9, 0x61, 0x96, 0x20, 0x53, 0x6e, - 0x78, 0x62, 0xe0, 0x10, 0xd2, 0xca, 0xe4, 0xdd, - 0xd5, 0x96, 0xaf, 0x9a, 0xd7, 0x08, 0x47, 0xe4, - 0x55, 0x1b, 0x83, 0xbe, 0x10, 0x66, 0x74, 0x08, - 0xf2, 0x49, 0x79, 0xea, 0x29, 0x46, 0xc2, 0x65, - 0x97, 0xa6, 0xcc, 0x4b, 0xa4, 0x08, 0xc3, 0x04, - 0x17, 0x01, 0xb5, 0x11, 0x53, 0xe9, 0x68, 0x34, - 0x3c, 0x26, 0x56, 0x44, 0x37, 0x5c, 0xb4, 0x7a, - 0x1d, 0x5d, 0x6c, 0x58, 0xc2, 0x82, 0xa0, 0x92, - 0xf1, 0x14, 0xf1, 0x22, 0xff, 0x64, 0xde, 0xdf, - 0xb3, 0x3d, 0x9d, 0xa5, 0x86, 0xcd, 0xa0, 0x0a, - 0x63, 0x08, 0xdd, 0x60, 0x5d, 0xfd, 0xa4, 0x01, - 0xe3, 0xb6, 0x0e, 0x85, 0xe4, 0xc3, 0x37, 0x61, - 0xd0, 0xe7, 0x12, 0xe9, 0xc4, 0xde, 0xf2, 0x59, - 0x11, 0xe3, 0x5b, 0x02, 0x9f, 0x24, 0xb9, 0xb0, - 0xbb, 0x31, 0xa0, 0xee, 0x6a, 0x2c, 0xb4, 0x30, - 0xff, 0xe0, 0xf0, 0x93, 0xee, 0x3a, 0xae, 0xb2, - 0x2e, 0x84, 0xa0, 0x47, 0x42, 0x51, 0xbb, 0xfa, - 0xbb, 0x90, 0x97, 0x2c, 0x77, 0x45, 0xee, 0x2c, - 0xfb, 0xec, 0x5d, 0xd8, 0xca, 0x49, 0x94, 0x53, - 0x5d, 0x37, 0xaf, 0x86, 0x47, 0xda, 0xe2, 0xbd, - 0xf0, 0x5f, 0x07, 0x53, 0x8a, 0x10, 0xd0, 0x9a, - 0xd0, 0x7f, 0xe9, 0xef, 0xf6, 0xda, 0xea, 0x1e, - 0x2e, 0x54, 0xec, 0x44, 0xde, 0x3a, 0xe1, 0xc8, - 0xdb, 0x17, 0xe8, 0xc9, 0x3a, 0x81, 0x11, 0x4d, - 0xb7, 0x2d, 0x09, 0x83, 0xab, 0x30, 0xb7, 0xf5, - 0x1b, 0x03, 0x86, 0x21, 0xa9, 0xf5, 0xca, 0x15, - 0x26, 0xaf, 0x39, 0xf3, 0x5d, 0x01, 0x7d, 0xe3, - 0x19, 0x54, 0xd1, 0x2e, 0x10, 0x16, 0x9c, 0xee, - 0xc3, 0xbd, 0xcc, 0xdb, 0x02, 0x82, 0xd0, 0x60, - 0x0b, 0x42, 0x72, 0x85, 0xec, 0xdc, 0x41, 0x7c, - 0xf1, 0x34, 0xd8, 0x27, 0x21, 0xf9, 0xa6, 0x82, - 0x40, 0xd3, 0xc5, 0xc9, 0xf9, 0x6b, 0xc9, 0x12, - 0x64, 0xe4, 0x3a, 0x3b, 0xc9, 0x8f, 0x3c, 0xd0, - 0x2c, 0xb8, 0xb8, 0xf3, 0x05, 0x4a, 0xe9, 0x4c, - 0x46, 0x2b, 0xb6, 0xe1, 0xed, 0x82, 0xb2, 0xf0, - 0xd1, 0x72, 0x71, 0x04, 0x35, 0x19, 0xc1, 0x16, - 0x17, 0xd6, 0x75, 0xe0, 0xab, 0xde, 0x8f, 0xe1, - 0xc1, 0x49, 0x68, 0x0c, 0xc8, 0xce, 0x6d, 0x87, - 0x50, 0x04, 0xb5, 0xd7, 0x24, 0xf4, 0x2e, 0x0c, - 0x11, 0x35, 0xb2, 0x67, 0x85, 0x1b, 0x38, 0xff, - 0x2f, 0x71, 0xf5, 0x30, 0x18, 0x1e, 0x6f, 0xd7, - 0xf0, 0x33, 0x61, 0x53, 0x7e, 0x55, 0x7f, 0x0d, - 0x60, 0x83, 0xf3, 0x8a, 0x2b, 0x67, 0xd5, 0xf0, - 0x2e, 0x23, 0x23, 0x60, 0x0b, 0x83, 0x9c, 0xc2, - 0x87, 0x02, 0x03, 0x01, 0x00, 0x01 }; - -static const uint8_t kTestRsaPrivateKey2_2048[] = { +static const uint8_t kTestPKCS1RSAPrivateKey2_2048[] = { 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa7, 0x00, 0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a, 0x40, 0xb4, @@ -519,7 +258,162 @@ static const uint8_t kTestRsaPrivateKey2_2048[] = { 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18, 0x56, 0xfe, 0x39, 0x28, 0x33, 0xe0, 0xdb, 0x03 }; -static const uint8_t kTestRsaPublicKey2_2048[] = { +// 2048 bit RSA key in PKCS#8 PrivateKeyInfo +static const char 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 }; + +static const uint8_t kTestRSAPublicKey2_2048[] = { 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa7, 0x00, 0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a, 0x40, 0xb4, 0xe1, 0x15, 0x94, @@ -555,7 +449,7 @@ static const uint8_t kTestRsaPublicKey2_2048[] = { 0x6b, 0xbb, 0xbb, 0x2c, 0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01 }; -static const uint8_t kTestRsaPrivateKey3_2048[] = { +static const uint8_t kTestPKCS1RSAPrivateKey3_2048[] = { 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa5, 0xd0, 0xd7, 0x3e, 0x0e, 0x2d, 0xfb, 0x43, 0x51, 0x99, 0xea, 0x40, @@ -706,7 +600,163 @@ static const uint8_t kTestRsaPrivateKey3_2048[] = { 0x98, 0x18, 0x0e, 0x65, 0xb6, 0x4b, 0x69, 0x0b, 0x21, 0xdc, 0x86, 0x17, 0x6e, 0xc8, 0xee, 0x24 }; -static const uint8_t kTestRsaPublicKey3_2048[] = { +// 2048 bit RSA key in PKCS#8 PrivateKeyInfo +static const char kTestRSAPKCS8PrivateKeyInfo3_2048[] = { + 0x30, 0x82, 0x04, 0xbe, 0x02, 0x01, 0x00, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x04, 0xa8, 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, + 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa5, 0xd0, + 0xd7, 0x3e, 0x0e, 0x2d, 0xfb, 0x43, 0x51, 0x99, + 0xea, 0x40, 0x1e, 0x2d, 0x89, 0xe4, 0xa2, 0x3e, + 0xfc, 0x51, 0x3d, 0x0e, 0x83, 0xa7, 0xe0, 0xa5, + 0x41, 0x04, 0x1e, 0x14, 0xc5, 0xa7, 0x5c, 0x61, + 0x36, 0x44, 0xb3, 0x08, 0x05, 0x5b, 0x14, 0xde, + 0x01, 0x0c, 0x32, 0x3c, 0x9a, 0x91, 0x00, 0x50, + 0xa8, 0x1d, 0xcc, 0x9f, 0x8f, 0x35, 0xb7, 0xc2, + 0x75, 0x08, 0x32, 0x8b, 0x10, 0x3a, 0x86, 0xf9, + 0xd7, 0x78, 0xa3, 0x9d, 0x74, 0x10, 0xc6, 0x24, + 0xb1, 0x7f, 0xa5, 0xbf, 0x5f, 0xc2, 0xd7, 0x15, + 0xa3, 0x1d, 0xe0, 0x15, 0x6b, 0x1b, 0x0e, 0x38, + 0xba, 0x34, 0xbc, 0x95, 0x47, 0x94, 0x40, 0x70, + 0xac, 0x99, 0x1f, 0x0b, 0x8e, 0x56, 0x93, 0x36, + 0x2b, 0x6d, 0x04, 0xe7, 0x95, 0x1a, 0x37, 0xda, + 0x16, 0x57, 0x99, 0xee, 0x03, 0x68, 0x16, 0x31, + 0xaa, 0xc3, 0xb7, 0x92, 0x75, 0x53, 0xfc, 0xf6, + 0x20, 0x55, 0x44, 0xf8, 0xd4, 0x8d, 0x78, 0x15, + 0xc7, 0x1a, 0xb6, 0xde, 0x6c, 0xe8, 0x49, 0x5d, + 0xaf, 0xa8, 0x4e, 0x6f, 0x7c, 0xe2, 0x6a, 0x4c, + 0xd5, 0xe7, 0x8c, 0x8f, 0x0b, 0x5d, 0x3a, 0x09, + 0xd6, 0xb3, 0x44, 0xab, 0xe0, 0x35, 0x52, 0x7c, + 0x66, 0x85, 0xa4, 0x40, 0xd7, 0x20, 0xec, 0x24, + 0x05, 0x06, 0xd9, 0x84, 0x51, 0x5a, 0xd2, 0x38, + 0xd5, 0x1d, 0xea, 0x70, 0x2a, 0x21, 0xe6, 0x82, + 0xfd, 0xa4, 0x46, 0x1c, 0x4f, 0x59, 0x6e, 0x29, + 0x3d, 0xae, 0xb8, 0x8e, 0xee, 0x77, 0x1f, 0x15, + 0x33, 0xcf, 0x94, 0x1d, 0x87, 0x3c, 0x37, 0xc5, + 0x89, 0xe8, 0x7d, 0x85, 0xb3, 0xbc, 0xe8, 0x62, + 0x6a, 0x84, 0x7f, 0xfe, 0x9a, 0x85, 0x3f, 0x39, + 0xe8, 0xaa, 0x16, 0xa6, 0x8f, 0x87, 0x7f, 0xcb, + 0xc1, 0xd6, 0xf2, 0xec, 0x2b, 0xa7, 0xdd, 0x49, + 0x98, 0x7b, 0x6f, 0xdd, 0x69, 0x6d, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x43, + 0x8f, 0x19, 0x83, 0xb1, 0x27, 0x4e, 0xee, 0x98, + 0xba, 0xcb, 0x54, 0xa0, 0x77, 0x11, 0x6d, 0xd4, + 0x25, 0x31, 0x8c, 0xb0, 0x01, 0xcf, 0xe6, 0x80, + 0x83, 0x14, 0x40, 0x67, 0x39, 0x33, 0x67, 0x03, + 0x1e, 0xa0, 0x8b, 0xd1, 0x1d, 0xfd, 0x80, 0xa4, + 0xb9, 0xe7, 0x57, 0x5e, 0xc8, 0x8e, 0x79, 0x71, + 0xd5, 0x6b, 0x09, 0xe9, 0x2b, 0x41, 0xa0, 0x33, + 0x64, 0xc9, 0x66, 0x33, 0xa1, 0xb1, 0x55, 0x07, + 0x55, 0x98, 0x53, 0x10, 0xe6, 0xc0, 0x39, 0x6d, + 0x61, 0xd9, 0xe8, 0x16, 0x52, 0x28, 0xe4, 0x2b, + 0xda, 0x27, 0x01, 0xaf, 0x21, 0x4a, 0xe8, 0x55, + 0x1d, 0x0b, 0xd1, 0x1c, 0xdc, 0xfd, 0xb3, 0x0b, + 0xa6, 0x5c, 0xcc, 0x6e, 0x77, 0xb8, 0xe0, 0xd1, + 0x4e, 0x0a, 0xd7, 0x7a, 0x5e, 0x18, 0xc3, 0xfb, + 0xe9, 0xa1, 0x9c, 0xc3, 0x9c, 0xd4, 0x4a, 0x7e, + 0x70, 0x72, 0x11, 0x18, 0x24, 0x56, 0x24, 0xdf, + 0xf8, 0xba, 0xac, 0x5b, 0x54, 0xd3, 0xc4, 0x65, + 0x69, 0xc8, 0x79, 0x94, 0x16, 0x88, 0x9a, 0x68, + 0x1c, 0xbc, 0xd4, 0xca, 0xec, 0x5e, 0x07, 0x4a, + 0xc9, 0x54, 0x7a, 0x4b, 0xdb, 0x19, 0x88, 0xf6, + 0xbe, 0x50, 0x9d, 0x9e, 0x9d, 0x88, 0x5b, 0x4a, + 0x23, 0x86, 0x2b, 0xa9, 0xa6, 0x6c, 0x70, 0x7d, + 0xe1, 0x11, 0xba, 0xbf, 0x03, 0x2e, 0xf1, 0x46, + 0x7e, 0x1b, 0xed, 0x06, 0x11, 0x57, 0xad, 0x4a, + 0xcb, 0xe5, 0xb1, 0x11, 0x05, 0x0a, 0x30, 0xb1, + 0x73, 0x79, 0xcd, 0x7a, 0x04, 0xcc, 0x70, 0xe9, + 0x95, 0xe4, 0x27, 0xc2, 0xd5, 0x2d, 0x92, 0x44, + 0xdf, 0xb4, 0x94, 0xa8, 0x73, 0xa1, 0x4a, 0xc3, + 0xcc, 0xc4, 0x0e, 0x8d, 0xa1, 0x6a, 0xc2, 0xd8, + 0x03, 0x7f, 0xfa, 0xa7, 0x76, 0x0d, 0xad, 0x87, + 0x88, 0xa0, 0x77, 0xaf, 0x3b, 0x23, 0xd1, 0x66, + 0x0b, 0x31, 0x2b, 0xaf, 0xef, 0xd5, 0x41, 0x02, + 0x81, 0x81, 0x00, 0xdb, 0xc1, 0xe7, 0xdd, 0xba, + 0x3c, 0x1f, 0x9c, 0x64, 0xca, 0xa0, 0x63, 0xdb, + 0xd2, 0x47, 0x5c, 0x6e, 0x8a, 0xa3, 0x16, 0xd5, + 0xda, 0xc2, 0x25, 0x64, 0x0a, 0x02, 0xbc, 0x7d, + 0x7f, 0x50, 0xab, 0xe0, 0x66, 0x03, 0x53, 0x7d, + 0x77, 0x6d, 0x6c, 0x61, 0x58, 0x09, 0x73, 0xcd, + 0x18, 0xe9, 0x53, 0x0b, 0x5c, 0xa2, 0x71, 0x14, + 0x02, 0xfd, 0x55, 0xda, 0xe9, 0x77, 0x24, 0x7c, + 0x2a, 0x4e, 0xb9, 0xd9, 0x5d, 0x58, 0xf6, 0x26, + 0xd0, 0xd8, 0x3d, 0xcf, 0x8c, 0x89, 0x65, 0x6c, + 0x35, 0x19, 0xb6, 0x63, 0xff, 0xa0, 0x71, 0x49, + 0xcd, 0x6d, 0x5b, 0x3d, 0x8f, 0xea, 0x6f, 0xa9, + 0xba, 0x43, 0xe5, 0xdd, 0x39, 0x3a, 0x78, 0x8f, + 0x07, 0xb8, 0xab, 0x58, 0x07, 0xb7, 0xd2, 0xf8, + 0x07, 0x02, 0x9b, 0x79, 0x26, 0x32, 0x22, 0x38, + 0x91, 0x01, 0x90, 0x81, 0x29, 0x94, 0xad, 0x77, + 0xeb, 0x86, 0xb9, 0x02, 0x81, 0x81, 0x00, 0xc1, + 0x29, 0x88, 0xbd, 0x96, 0x31, 0x33, 0x7b, 0x77, + 0x5d, 0x32, 0x12, 0x5e, 0xdf, 0x28, 0x0c, 0x96, + 0x0d, 0xa8, 0x22, 0xdf, 0xd3, 0x35, 0xd7, 0xb0, + 0x41, 0xcb, 0xe7, 0x94, 0x8a, 0xa4, 0xed, 0xd2, + 0xfb, 0xd2, 0xf3, 0xf2, 0x95, 0xff, 0xd8, 0x33, + 0x3f, 0x8c, 0xd7, 0x65, 0xe4, 0x0c, 0xcc, 0xfe, + 0x32, 0x66, 0xfa, 0x50, 0xe2, 0xcf, 0xf0, 0xbe, + 0x05, 0xb1, 0xbc, 0xbe, 0x44, 0x09, 0xb4, 0xfe, + 0x95, 0x06, 0x18, 0xd7, 0x59, 0xc6, 0xef, 0x2d, + 0x22, 0xa0, 0x73, 0x5e, 0x77, 0xdf, 0x8d, 0x09, + 0x2c, 0xb8, 0xcc, 0xeb, 0x10, 0x4d, 0xa7, 0xd0, + 0x4b, 0x46, 0xba, 0x7d, 0x8b, 0x6a, 0x55, 0x47, + 0x55, 0xd3, 0xd7, 0xb1, 0x88, 0xfd, 0x27, 0x3e, + 0xf9, 0x5b, 0x7b, 0xae, 0x6d, 0x08, 0x9f, 0x0c, + 0x2a, 0xe1, 0xdd, 0xb9, 0xe3, 0x55, 0x13, 0x55, + 0xa3, 0x6d, 0x06, 0xbb, 0xe0, 0x1e, 0x55, 0x02, + 0x81, 0x80, 0x61, 0x73, 0x3d, 0x64, 0xff, 0xdf, + 0x05, 0x8d, 0x8e, 0xcc, 0xa4, 0x0f, 0x64, 0x3d, + 0x7d, 0x53, 0xa9, 0xd9, 0x64, 0xb5, 0x0d, 0xa4, + 0x72, 0x8f, 0xae, 0x2b, 0x1a, 0x47, 0x87, 0xc7, + 0x5b, 0x78, 0xbc, 0x8b, 0xc0, 0x51, 0xd7, 0xc3, + 0x8c, 0x0c, 0x91, 0xa6, 0x3e, 0x9a, 0xd1, 0x8a, + 0x88, 0x7d, 0x40, 0xfe, 0x95, 0x32, 0x5b, 0xd3, + 0x6f, 0x90, 0x11, 0x01, 0x92, 0xc9, 0xe5, 0x1d, + 0xc5, 0xc7, 0x78, 0x72, 0x82, 0xae, 0xb5, 0x4b, + 0xcb, 0x78, 0xad, 0x7e, 0xfe, 0xb6, 0xb1, 0x23, + 0x63, 0x01, 0x94, 0x9a, 0x99, 0x05, 0x63, 0xda, + 0xea, 0xf1, 0x98, 0xfd, 0x26, 0xd2, 0xd9, 0x8b, + 0x35, 0xec, 0xcb, 0x0b, 0x43, 0xb8, 0x8e, 0x84, + 0xb8, 0x09, 0x93, 0x81, 0xe8, 0xac, 0x6f, 0x3c, + 0x7c, 0x95, 0x81, 0x45, 0xc4, 0xd9, 0x94, 0x08, + 0x09, 0x8f, 0x91, 0x17, 0x65, 0x4c, 0xff, 0x6e, + 0xbc, 0x51, 0x02, 0x81, 0x81, 0x00, 0xc1, 0x0d, + 0x9d, 0xd8, 0xbd, 0xaf, 0x56, 0xe0, 0xe3, 0x1f, + 0x85, 0xd7, 0xce, 0x72, 0x02, 0x38, 0xf2, 0x0f, + 0x9c, 0x27, 0x9e, 0xc4, 0x1d, 0x60, 0x00, 0x8d, + 0x02, 0x19, 0xe5, 0xdf, 0xdb, 0x8e, 0xc5, 0xfb, + 0x61, 0x8e, 0xe6, 0xb8, 0xfc, 0x07, 0x3c, 0xd1, + 0x1b, 0x16, 0x7c, 0x83, 0x3c, 0x37, 0xf5, 0x26, + 0xb2, 0xbd, 0x22, 0xf2, 0x4d, 0x19, 0x33, 0x11, + 0xc5, 0xdd, 0xf9, 0xdb, 0x4e, 0x48, 0x52, 0xd8, + 0xe6, 0x4b, 0x15, 0x90, 0x68, 0xbe, 0xca, 0xc1, + 0x7c, 0xd3, 0x51, 0x6b, 0x45, 0x46, 0x54, 0x11, + 0x1a, 0x71, 0xd3, 0xcd, 0x6b, 0x8f, 0x79, 0x22, + 0x83, 0x02, 0x08, 0x4f, 0xba, 0x6a, 0x98, 0xed, + 0x32, 0xd8, 0xb4, 0x5b, 0x51, 0x88, 0x53, 0xec, + 0x2c, 0x7e, 0xa4, 0x89, 0xdc, 0xbf, 0xf9, 0x0d, + 0x32, 0xc8, 0xc3, 0xec, 0x6d, 0x2e, 0xf1, 0xbc, + 0x70, 0x4e, 0xf6, 0x9e, 0xbc, 0x31, 0x02, 0x81, + 0x81, 0x00, 0xd3, 0x35, 0x1b, 0x19, 0x75, 0x3f, + 0x61, 0xf2, 0x55, 0x03, 0xce, 0x25, 0xa9, 0xdf, + 0x0c, 0x0a, 0x3b, 0x47, 0x42, 0xdc, 0x38, 0x4b, + 0x13, 0x4d, 0x1f, 0x86, 0x58, 0x4f, 0xd8, 0xee, + 0xfa, 0x76, 0x15, 0xfb, 0x6e, 0x55, 0x31, 0xf2, + 0xd2, 0x62, 0x32, 0xa5, 0xc4, 0x23, 0x5e, 0x08, + 0xa9, 0x83, 0x07, 0xac, 0x8c, 0xa3, 0x7e, 0x18, + 0xc0, 0x1c, 0x57, 0x63, 0x8d, 0x05, 0x17, 0x47, + 0x1b, 0xd3, 0x74, 0x73, 0x20, 0x04, 0xfb, 0xc8, + 0x1a, 0x43, 0x04, 0x36, 0xc8, 0x19, 0xbe, 0xdc, + 0xa6, 0xe5, 0x0f, 0x25, 0x62, 0x24, 0x96, 0x92, + 0xb6, 0xb3, 0x97, 0xad, 0x57, 0x9a, 0x90, 0x37, + 0x4e, 0x31, 0x44, 0x74, 0xfa, 0x7c, 0xb4, 0xea, + 0xfc, 0x15, 0xa7, 0xb0, 0x51, 0xcc, 0xee, 0x1e, + 0xed, 0x5b, 0x98, 0x18, 0x0e, 0x65, 0xb6, 0x4b, + 0x69, 0x0b, 0x21, 0xdc, 0x86, 0x17, 0x6e, 0xc8, + 0xee, 0x24 }; + +static const uint8_t kTestRSAPublicKey3_2048[] = { 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa5, 0xd0, 0xd7, 0x3e, 0x0e, 0x2d, 0xfb, 0x43, 0x51, 0x99, 0xea, 0x40, 0x1e, 0x2d, 0x89, @@ -749,9 +799,530 @@ static void dump_openssl_error() { } } +class Session { + public: + Session() : valid_(false), open_(false) {} + + Session(string sname) : valid_(true), open_(false), sname_(sname), + mac_key_server_(wvcdm::MAC_KEY_SIZE), + mac_key_client_(wvcdm::MAC_KEY_SIZE), + enc_key_(wvcdm::KEY_SIZE), public_rsa_(0) {} + + bool isValid() { return valid_; } + bool isOpen() { return open_; } + bool successStatus() { return (OEMCrypto_SUCCESS == session_status_); } + OEMCryptoResult getStatus() { return session_status_; } + uint32_t get_nonce() { 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_); + EXPECT_TRUE(!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; + } + } + + void GenerateNonce(uint32_t* nonce) { + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_GenerateNonce(session_id(), nonce)); + } + + void GenerateDerivedKeys() { + GenerateNonce(&nonce_); + vector mac_context = wvcdm::a2b_hex( + "41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff" + "de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873" + "4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a" + "230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635" + "34333231180120002a0c31383836373837343035000000000100"); + vector enc_context = wvcdm::a2b_hex( + "454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95" + "c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb" + "e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408" + "0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231" + "180120002a0c31383836373837343035000000000080"); + OEMCryptoResult sts; + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_GenerateDerivedKeys( + session_id(), + &mac_context[0], mac_context.size(), + &enc_context[0], enc_context.size())); + mac_key_server_ = wvcdm::a2b_hex( + "9D41F0A77A76E071841C33B06104D106641421E651FBE55F0AED453CDA7713AC"); + mac_key_client_ = wvcdm::a2b_hex( + "125283F299AF42C191E1A989846B388BB16A6E50B2F67D4F876A3C1F662CD5C8"); + enc_key_ = wvcdm::a2b_hex("D0BFC35DA9E33436E81C4229E78CB9F4"); + } + + void LoadTestKeys(uint32_t duration, uint32_t control) { + MessageData data; + FillSimpleMessage(&data, duration, control); + MessageData encrypted; + EncryptMessage(data, &encrypted); + std::vector signature; + ServerSignMessage(encrypted, &signature); + OEMCrypto_KeyObject key_array[kNumKeys]; + + const uint8_t* message_ptr = reinterpret_cast(&encrypted); + FillKeyArray(encrypted, key_array); + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_LoadKeys(session_id(), message_ptr, sizeof(encrypted), + &signature[0], signature.size(), + encrypted.mac_key_iv, encrypted.mac_keys, + kNumKeys, key_array)); + // Update new generated keys. + memcpy(&mac_key_server_[0], data.mac_keys, wvcdm::MAC_KEY_SIZE); + memcpy(&mac_key_client_[0], data.mac_keys+wvcdm::MAC_KEY_SIZE, + wvcdm::MAC_KEY_SIZE); + } + + void RefreshTestKeys(const int key_count, uint32_t control_bits, uint32_t nonce, + bool expect_good) { + MessageData data; + + FillRefreshMessage(&data, key_count, control_bits, nonce); + + std::vector signature; + ServerSignMessage(data, &signature); + OEMCrypto_KeyRefreshObject key_array[key_count]; + + const uint8_t* message_ptr = reinterpret_cast(&data); + FillRefreshArray(data, key_array, key_count); + OEMCryptoResult sts = OEMCrypto_RefreshKeys(session_id(), message_ptr, sizeof(data), + &signature[0], signature.size(), + key_count, key_array); + if( expect_good ) { + ASSERT_EQ(OEMCrypto_SUCCESS,sts); + } else { + ASSERT_NE(OEMCrypto_SUCCESS,sts); + } + +#if 1 // Each of these tests take 5 seconds, so we might want to turn them off. + + // TODO(fredgc): change this to key 1. + + // TODO(fredgc): make sure duration is reset. + // Select the key (from FillSimpleMessage) + vector keyId = wvcdm::a2b_hex("000000000000000000000000"); + sts = OEMCrypto_SelectKey(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(session_id(), &encryptedData[0], + encryptedData.size(), true, &encryptionIv[0], 0, + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, + unencryptedData.size())); + + sleep(1); // Should still be valid key. + + memset(outputBuffer, 0, sizeof(outputBuffer)); + destBuffer.type = OEMCrypto_BufferType_Clear; + destBuffer.buffer.clear.address = outputBuffer; + destBuffer.buffer.clear.max_length = sizeof(outputBuffer); + + // Decrypt the data + sts = OEMCrypto_DecryptCTR(session_id(), &encryptedData[0], + encryptedData.size(), true, &encryptionIv[0], 0, + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, + unencryptedData.size())); + + sleep(3); // Should be after first expiration. + + memset(outputBuffer, 0, sizeof(outputBuffer)); + destBuffer.type = OEMCrypto_BufferType_Clear; + destBuffer.buffer.clear.address = outputBuffer; + destBuffer.buffer.clear.max_length = sizeof(outputBuffer); + + // Decrypt the data + sts = OEMCrypto_DecryptCTR(session_id(), &encryptedData[0], + encryptedData.size(), true, &encryptionIv[0], 0, + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); + if( expect_good) { + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, + unencryptedData.size())); + } else { + ASSERT_NE(OEMCrypto_SUCCESS, sts); + ASSERT_NE(0, memcmp(&unencryptedData[0], outputBuffer, + unencryptedData.size())); + } + + +#endif + } + + void FillSimpleMessage(MessageData* data, uint32_t duration, uint32_t control) { + OEMCrypto_GetRandom(data->mac_key_iv, sizeof(data->mac_key_iv)); + OEMCrypto_GetRandom(data->mac_keys, sizeof(data->mac_keys)); + for (unsigned int i = 0; i < kNumKeys; i++) { + memset(data->keys[i].key_id, i, kTestKeyIdLength); + OEMCrypto_GetRandom(data->keys[i].key_data, + sizeof(data->keys[i].key_data)); + data->keys[i].key_data_length = wvcdm::KEY_SIZE; + OEMCrypto_GetRandom(data->keys[i].key_iv, sizeof(data->keys[i].key_iv)); + OEMCrypto_GetRandom(data->keys[i].control_iv, + sizeof(data->keys[i].control_iv)); + memcpy(data->keys[i].control.verification, "kctl", 4); + data->keys[i].control.duration = htonl(duration); + data->keys[i].control.nonce = htonl(nonce_); + data->keys[i].control.control_bits = htonl(control); + } + // 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()); + } + + void FillRefreshMessage(MessageData* data, int key_count, + uint32_t control_bits, uint32_t nonce) { + for (unsigned int i = 0; i < kNumKeys; i++) { + memset(data->keys[i].key_id, i, kTestKeyIdLength); + memcpy(data->keys[i].control.verification, "kctl", 4); + data->keys[i].control.duration = htonl(kLongDuration); + data->keys[i].control.nonce = htonl(nonce); + data->keys[i].control.control_bits = htonl(control_bits); + } + } + + void EncryptMessage(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_keys[0], &encrypted->mac_keys[0], + 2*wvcdm::MAC_KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT); + + for (unsigned int i = 0; i < kNumKeys; 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], data.keys[i].key_data_length, + &aes_key, iv_buffer, AES_ENCRYPT); + } + } + + void EncryptMessage(RSAPrivateKeyMessage* data, + RSAPrivateKeyMessage* encrypted) { + *encrypted = *data; + size_t padding = wvcdm::KEY_SIZE-(data->rsa_key_length % wvcdm::KEY_SIZE); + memset(data->rsa_key + data->rsa_key_length, + static_cast(padding), padding); + encrypted->rsa_key_length = data->rsa_key_length + padding; + uint8_t iv_buffer[16]; + memcpy(iv_buffer, &data->rsa_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->rsa_key[0], &encrypted->rsa_key[0], + encrypted->rsa_key_length, &aes_key, iv_buffer, + AES_ENCRYPT); + } + + template + void ServerSignMessage(const T& data, std::vector* signature) { + signature->resize(SHA256_DIGEST_LENGTH); + unsigned int md_len = SHA256_DIGEST_LENGTH; + HMAC(EVP_sha256(), &mac_key_server_[0], SHA256_DIGEST_LENGTH, + reinterpret_cast(&data), sizeof(data), + &(signature->front()), &md_len); + } + + void ClientSignMessage(const vector &data, + std::vector* signature) { + signature->resize(SHA256_DIGEST_LENGTH); + unsigned int md_len = SHA256_DIGEST_LENGTH; + HMAC(EVP_sha256(), &mac_key_client_[0], SHA256_DIGEST_LENGTH, + &(data.front()), data.size(), &(signature->front()), &md_len); + } + + void FillKeyArray(const MessageData& data, + OEMCrypto_KeyObject* key_array) { + for (unsigned int i = 0; i < kNumKeys; 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_data_length = data.keys[i].key_data_length; + key_array[i].key_control_iv = data.keys[i].control_iv; + key_array[i].key_control + = reinterpret_cast(&data.keys[i].control); + } + } + + void FillRefreshArray(const MessageData& data, + OEMCrypto_KeyRefreshObject* key_array, const int key_count) { + for (int i = 0; i < key_count; i++) { + if( key_count > 1 ) { + key_array[i].key_id = data.keys[i].key_id; + key_array[i].key_id_length = kTestKeyIdLength; + } else { + key_array[i].key_id = NULL; + key_array[i].key_id_length = 0; + } + // TODO(fredgc): Is this valid? Is key control encrypted on renewal? + // key_array[i].key_control_iv = data.keys[i].control_iv; + key_array[i].key_control_iv = NULL; + key_array[i].key_control + = reinterpret_cast(&data.keys[i].control); + } + } + + void MakeRSACertificate(struct RSAPrivateKeyMessage* encrypted, + std::vector* signature) { + 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); + ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts); + ASSERT_EQ(static_cast(32), gen_signature_length); + static const uint32_t SignatureBufferMaxLength = 256; + uint8_t gen_signature[SignatureBufferMaxLength]; + sts = OEMCrypto_GenerateSignature(session_id(), &context[0], + context.size(), gen_signature, + &gen_signature_length); + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + std::vector expected_signature; + ClientSignMessage(context, &expected_signature); + ASSERT_EQ(0, memcmp(&expected_signature[0], gen_signature, + expected_signature.size())); + + // 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. + + struct RSAPrivateKeyMessage message; + memcpy(message.rsa_key, kTestRSAPKCS8PrivateKeyInfo2_2048, + sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048)); + OEMCrypto_GetRandom(message.rsa_key_iv, wvcdm::KEY_IV_SIZE); + message.rsa_key_length = sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048); + message.nonce = nonce_; + + EncryptMessage(&message, encrypted); + ServerSignMessage(*encrypted, signature); + } + + void RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted, + const std::vector& signature, + vector* wrapped_key) { + size_t wrapped_key_length = 0; + const uint8_t* message_ptr = reinterpret_cast(&encrypted); + ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, + OEMCrypto_RewrapDeviceRSAKey(session_id(), message_ptr, + sizeof(encrypted), &signature[0], + signature.size(), &encrypted.nonce, + encrypted.rsa_key, + encrypted.rsa_key_length, + encrypted.rsa_key_iv, NULL, + &wrapped_key_length)); + wrapped_key->clear(); + wrapped_key->resize(wrapped_key_length); + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_RewrapDeviceRSAKey(session_id(), message_ptr, + sizeof(encrypted), &signature[0], + signature.size(), &encrypted.nonce, + encrypted.rsa_key, + encrypted.rsa_key_length, + encrypted.rsa_key_iv, + &(wrapped_key->front()), + &wrapped_key_length)); + } + + bool PreparePublicKey(const uint8_t key[], size_t length) { + uint8_t const* p = key; + public_rsa_ = d2i_RSAPublicKey(0, &p , length); + if (!public_rsa_) { + cout << "d2i_RSAPrivateKey failed. "; + dump_openssl_error(); + return false; + } + return true; + } + + bool VerifyRSASignature(const uint8_t* message, + size_t message_length, + uint8_t* signature, + size_t* signature_length) { + if (!public_rsa_) { + cout << "No public RSA key loaded in test code.\n"; + return false; + } + if (*signature_length != static_cast(RSA_size(public_rsa_))) { + cout << "Signature size is wrong. " << *signature_length + << ", should be " << RSA_size(public_rsa_) << "\n"; + return false; + } + + // Hash the message using SHA1. + uint8_t hash[SHA_DIGEST_LENGTH]; + if (!SHA1(message, message_length, hash)) { + cout << "Error computing SHA1. "; + dump_openssl_error(); + return false; + } + + // Decrypt signature to padded digest. + uint8_t padded_digest[*signature_length]; + int status; + status = RSA_public_decrypt(*signature_length, signature, padded_digest, + public_rsa_, RSA_NO_PADDING); + if (status == -1) { + cout << "VerifyRSASignature. in RSA_Public_digest "; + dump_openssl_error(); + return false; + } + status = RSA_verify_PKCS1_PSS(public_rsa_, hash, EVP_sha1(), + padded_digest, SHA_DIGEST_LENGTH); + if (status != 1) { + cout << "VerifyRSASignature. in RSA_verify_PKCS1_PSS "; + dump_openssl_error(); + return false; + } + return true; + } + + bool GenerateRSASessionKey(vector* enc_session_key, + vector* mac_context, + vector* enc_context) { + if (!public_rsa_) { + cout << "No public RSA key loaded in test code.\n"; + return false; + } + vector session_key = wvcdm::a2b_hex( + "6fa479c731d2770b6a61a5d1420bb9d1"); + *mac_context = wvcdm::a2b_hex( + "41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff" + "de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873" + "4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a" + "230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635" + "34333231180120002a0c31383836373837343035000000000100"); + *enc_context = wvcdm::a2b_hex( + "454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95" + "c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb" + "e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408" + "0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231" + "180120002a0c31383836373837343035000000000080"); + + enc_session_key->assign(RSA_size(public_rsa_), 0); + int status = RSA_public_encrypt(session_key.size(), + &session_key[0], + &(enc_session_key->front()), + public_rsa_, RSA_PKCS1_OAEP_PADDING); + if (status != RSA_size(public_rsa_)) { + cout << "GenerateRSASessionKey error encrypting session key. "; + dump_openssl_error(); + return false; + } + return true; + } + + void InstallRSASessionTestKey(const vector& wrapped_rsa_key) { + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_LoadDeviceRSAKey(session_id(), &wrapped_rsa_key[0], + wrapped_rsa_key.size())); + GenerateNonce(&nonce_); + vector enc_session_key; + vector mac_context; + vector enc_context; + ASSERT_TRUE(PreparePublicKey(kTestRSAPublicKey2_2048, + sizeof(kTestRSAPublicKey2_2048))); + ASSERT_TRUE(GenerateRSASessionKey(&enc_session_key, &mac_context, + &enc_context)); + + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_DeriveKeysFromSessionKey( + session_id(), &enc_session_key[0], enc_session_key.size(), + &mac_context[0], mac_context.size(), + &enc_context[0], enc_context.size())); + + mac_key_server_ = wvcdm::a2b_hex( + "B09CB4482675123B66F7A8303D803F6042F43404ED3DE020811CFC13BCDF4C65"); + mac_key_client_ = wvcdm::a2b_hex( + "B09CB4482675123B66F7A8303D803F6042F43404ED3DE020811CFC13BCDF4C65"); + enc_key_ = wvcdm::a2b_hex("CB477D09014D72C9B8DCE76C33EA43B3"); + } + + private: + bool valid_; + bool open_; + string sname_; + OEMCrypto_SESSION session_id_; + OEMCryptoResult session_status_; + vector mac_key_server_; + vector mac_key_client_; + vector enc_key_; + uint32_t nonce_; + RSA* public_rsa_; +}; + class OEMCryptoClientTest : public ::testing::Test { protected: - class Session; OEMCryptoClientTest() : alive_(false) {} @@ -812,371 +1383,6 @@ class OEMCryptoClientTest : public ::testing::Test { ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid()); } - 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), public_rsa_(0) {} - - 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_); - EXPECT_TRUE(!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; - } - } - - void GenerateNonce(uint32_t* nonce) { - ASSERT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_GenerateNonce(session_id(), nonce)); - } - - void GenerateDerivedKeys() { - GenerateNonce(&nonce_); - vector mac_context = wvcdm::a2b_hex( - "41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff" - "de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873" - "4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a" - "230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635" - "34333231180120002a0c31383836373837343035000000000100"); - vector enc_context = wvcdm::a2b_hex( - "454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95" - "c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb" - "e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408" - "0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231" - "180120002a0c31383836373837343035000000000080"); - OEMCryptoResult sts; - ASSERT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_GenerateDerivedKeys( - session_id(), - &mac_context[0], mac_context.size(), - &enc_context[0], enc_context.size())); - mac_key_ = wvcdm::a2b_hex( - "9D41F0A77A76E071841C33B06104D106641421E651FBE55F0AED453CDA7713AC"); - enc_key_ = wvcdm::a2b_hex("D0BFC35DA9E33436E81C4229E78CB9F4"); - } - - void LoadTestKeys() { - const unsigned int kNumKeys = 3; - MessageData data; - FillSimpleMessage(&data); - MessageData encrypted; - EncryptMessage(data, &encrypted); - std::vector signature; - SignMessage(encrypted, &signature); - OEMCrypto_KeyObject key_array[kNumKeys]; - - const uint8_t* message_ptr = reinterpret_cast(&encrypted); - FillKeyArray(encrypted, key_array); - - ASSERT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys(session_id(), message_ptr, sizeof(encrypted), - &signature[0], signature.size(), - encrypted.mac_key_iv, encrypted.mac_key, - kNumKeys, key_array)); - } - - template - void FillSimpleMessage(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::MAC_KEY_SIZE); - data->keys[i].key_data_length = 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 EncryptMessage(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], data.keys[i].key_data_length, - &aes_key, iv_buffer, AES_ENCRYPT); - } - } - - void EncryptMessage(RSAPrivateKeyMessage* data, - RSAPrivateKeyMessage* encrypted) { - *encrypted = *data; - size_t padding = wvcdm::KEY_SIZE-(data->rsa_key_length % wvcdm::KEY_SIZE); - memset(data->rsa_key + data->rsa_key_length, - static_cast(padding), padding); - encrypted->rsa_key_length = data->rsa_key_length + padding; - - uint8_t iv_buffer[16]; - memcpy(iv_buffer, &data->rsa_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->rsa_key[0], &encrypted->rsa_key[0], - encrypted->rsa_key_length, &aes_key, iv_buffer, - AES_ENCRYPT); - } - - template - void SignMessage(const T& 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 FillKeyArray(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_data_length = data.keys[i].key_data_length; - key_array[i].key_control_iv = data.keys[i].control_iv; - key_array[i].key_control - = reinterpret_cast(&data.keys[i].control); - } - } - - void MakeRSACertificate(struct RSAPrivateKeyMessage* encrypted, - std::vector* signature) { - 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); - ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts); - ASSERT_EQ(static_cast(32), gen_signature_length); - static const uint32_t SignatureBufferMaxLength = 256; - uint8_t gen_signature[SignatureBufferMaxLength]; - sts = OEMCrypto_GenerateSignature(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. - - struct RSAPrivateKeyMessage message; - memcpy(message.rsa_key, kTestRsaPrivateKey1_3072, - sizeof(kTestRsaPrivateKey1_3072)); - OEMCrypto_GetRandom(message.rsa_key_iv, wvcdm::KEY_IV_SIZE); - message.rsa_key_length = sizeof(kTestRsaPrivateKey1_3072); - message.nonce = nonce_; - - EncryptMessage(&message, encrypted); - SignMessage(*encrypted, signature); - } - - void RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted, - const std::vector& signature, - vector* wrapped_key) { - size_t wrapped_key_length = 0; - const uint8_t* message_ptr = reinterpret_cast(&encrypted); - ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, - OEMCrypto_RewrapDeviceRSAKey(session_id(), message_ptr, - sizeof(encrypted), &signature[0], - signature.size(), &encrypted.nonce, - encrypted.rsa_key, - encrypted.rsa_key_length, - encrypted.rsa_key_iv, NULL, - &wrapped_key_length)); - wrapped_key->clear(); - wrapped_key->resize(wrapped_key_length); - ASSERT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_RewrapDeviceRSAKey(session_id(), message_ptr, - sizeof(encrypted), &signature[0], - signature.size(), &encrypted.nonce, - encrypted.rsa_key, - encrypted.rsa_key_length, - encrypted.rsa_key_iv, - &(wrapped_key->front()), - &wrapped_key_length)); - } - - bool PreparePublicKey(const uint8_t key[], size_t length) { - uint8_t const* p = key; - public_rsa_ = d2i_RSAPublicKey(0, &p , length); - if (!public_rsa_) { - cout << "d2i_RSAPrivateKey failed. "; - dump_openssl_error(); - return false; - } - return true; - } - - bool VerifyRSASignature(const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length) { - if (!public_rsa_) { - cout << "No public RSA key loaded in test code.\n"; - return false; - } - if (*signature_length != static_cast(RSA_size(public_rsa_))) { - cout << "Signature size is wrong. " << *signature_length - << ", should be " << RSA_size(public_rsa_) << "\n"; - return false; - } - - // Hash the message using SHA1. - uint8_t hash[SHA_DIGEST_LENGTH]; - if (!SHA1(message, message_length, hash)) { - cout << "Error computing SHA1. "; - dump_openssl_error(); - return false; - } - - // Decrypt signature to padded digest. - uint8_t padded_digest[*signature_length]; - int status; - status = RSA_public_decrypt(*signature_length, signature, padded_digest, - public_rsa_, RSA_NO_PADDING); - if (status == -1) { - cout << "VerifyRSASignature. in RSA_Public_digest "; - dump_openssl_error(); - return false; - } - status = RSA_verify_PKCS1_PSS(public_rsa_, hash, EVP_sha1(), - padded_digest, SHA_DIGEST_LENGTH); - if (status != 1) { - cout << "VerifyRSASignature. in RSA_verify_PKCS1_PSS "; - dump_openssl_error(); - return false; - } - return true; - } - - bool GenerateRSASessionKey(vector* enc_session_key, - vector* mac_context, - vector* enc_context) { - if (!public_rsa_) { - cout << "No public RSA key loaded in test code.\n"; - return false; - } - vector session_key = wvcdm::a2b_hex( - "6fa479c731d2770b6a61a5d1420bb9d1"); - *mac_context = wvcdm::a2b_hex( - "41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff" - "de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873" - "4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a" - "230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635" - "34333231180120002a0c31383836373837343035000000000100"); - *enc_context = wvcdm::a2b_hex( - "454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95" - "c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb" - "e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408" - "0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231" - "180120002a0c31383836373837343035000000000080"); - - enc_session_key->assign(RSA_size(public_rsa_), 0); - int status = RSA_public_encrypt(session_key.size(), - &session_key[0], - &(enc_session_key->front()), - public_rsa_, RSA_PKCS1_OAEP_PADDING); - if (status != RSA_size(public_rsa_)) { - cout << "GenerateRSASessionKey error encrypting session key. "; - dump_openssl_error(); - return false; - } - return true; - } - - void InstallRSASessionTestKey(const vector& wrapped_rsa_key) { - ASSERT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_LoadDeviceRSAKey(session_id(), &wrapped_rsa_key[0], - wrapped_rsa_key.size())); - GenerateNonce(&nonce_); - vector enc_session_key; - vector mac_context; - vector enc_context; - ASSERT_TRUE(PreparePublicKey(kTestRsaPublicKey1_3072, - sizeof(kTestRsaPublicKey1_3072))); - ASSERT_TRUE(GenerateRSASessionKey(&enc_session_key, &mac_context, - &enc_context)); - - ASSERT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_DeriveKeysFromSessionKey( - session_id(), &enc_session_key[0], enc_session_key.size(), - &mac_context[0], mac_context.size(), - &enc_context[0], enc_context.size())); - - mac_key_ = wvcdm::a2b_hex( - "B09CB4482675123B66F7A8303D803F6042F43404ED3DE020811CFC13BCDF4C65"); - enc_key_ = wvcdm::a2b_hex("CB477D09014D72C9B8DCE76C33EA43B3"); - } - - private: - bool valid_; - bool open_; - string sname_; - OEMCrypto_SESSION session_id_; - OEMCryptoResult session_status_; - vector mac_key_; - vector enc_key_; - uint32_t nonce_; - RSA* public_rsa_; - }; - static Session badSession; Session& findSession(string sname) { @@ -1222,7 +1428,7 @@ class OEMCryptoClientTest : public ::testing::Test { map _sessions; }; -OEMCryptoClientTest::Session OEMCryptoClientTest::badSession; +Session OEMCryptoClientTest::badSession; /////////////////////////////////////////////////// // initialization tests @@ -1504,9 +1710,10 @@ TEST_F(OEMCryptoClientTest, GenerateSignature) { 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)); + std::vector expected_signature; + s.ClientSignMessage(context, &expected_signature); + ASSERT_EQ(0, memcmp(&expected_signature[0], signature, + expected_signature.size())); s.close(); @@ -1527,7 +1734,7 @@ TEST_F(OEMCryptoClientTest, LoadKeyNoNonce) { Session& s = createSession("ONE"); s.open(); s.GenerateDerivedKeys(); - s.LoadTestKeys(); + s.LoadTestKeys(kDuration, 0); s.close(); testTearDown(); } @@ -1539,28 +1746,7 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithNonce) { s.open(); s.GenerateDerivedKeys(); - - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); - data.keys[0].control.control_bits = htonl(wvoec_mock::kControlNonceEnabled); - data.keys[1].control.control_bits = htonl(wvoec_mock::kControlNonceEnabled); - data.keys[2].control.control_bits = htonl(wvoec_mock::kControlNonceEnabled); - - MessageData encrypted; - s.EncryptMessage(data, &encrypted); - std::vector signature; - s.SignMessage(encrypted, &signature); - OEMCrypto_KeyObject key_array[kNumKeys]; - const uint8_t* message_ptr = reinterpret_cast(&encrypted); - s.FillKeyArray(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, - kNumKeys, key_array); - ASSERT_EQ(OEMCrypto_SUCCESS, sts); + s.LoadTestKeys(0, wvoec_mock::kControlNonceEnabled); s.close(); testTearDown(); } @@ -1575,27 +1761,25 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange1) { s.open(); s.GenerateDerivedKeys(); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); - - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); - vector mac_key(encrypted.mac_key, - encrypted.mac_key+sizeof(encrypted.mac_key)); + vector mac_keys(encrypted.mac_keys, + encrypted.mac_keys+sizeof(encrypted.mac_keys)); OEMCryptoResult sts = OEMCrypto_LoadKeys(s.session_id(), message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - &mac_key[0], // Not pointing into buffer. + &mac_keys[0], // Not pointing into buffer. kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); s.close(); @@ -1609,15 +1793,13 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange2) { s.open(); s.GenerateDerivedKeys(); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); - - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); @@ -1629,7 +1811,7 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange2) { message_ptr, sizeof(encrypted), &signature[0], signature.size(), &mac_key_iv[0], // bad. - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); s.close(); @@ -1644,14 +1826,13 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange3) { s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); @@ -1664,7 +1845,7 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange3) { message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); s.close(); @@ -1679,14 +1860,13 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange4) { s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); @@ -1699,7 +1879,7 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange4) { message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); s.close(); @@ -1714,14 +1894,13 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange5) { s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); @@ -1734,7 +1913,7 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange5) { message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); s.close(); @@ -1749,14 +1928,13 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange6) { s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); @@ -1769,7 +1947,7 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange6) { message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); s.close(); @@ -1784,14 +1962,13 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange7) { s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); @@ -1804,7 +1981,7 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadRange7) { message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); s.close(); @@ -1819,18 +1996,17 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadNonce) { s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); data.keys[0].control.control_bits = htonl(wvoec_mock::kControlNonceEnabled); data.keys[1].control.control_bits = htonl(wvoec_mock::kControlNonceEnabled); data.keys[2].control.control_bits = htonl(wvoec_mock::kControlNonceEnabled); data.keys[1].control.nonce = 42; // This one is bad. - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); @@ -1840,7 +2016,7 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadNonce) { message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -1857,15 +2033,14 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadVerification) { s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); data.keys[1].control.verification[2] = 'Z'; - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); @@ -1875,7 +2050,7 @@ TEST_F(OEMCryptoClientTest, LoadKeyWithBadVerification) { message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -1892,14 +2067,13 @@ TEST_F(OEMCryptoClientTest, LoadKeysBadSignature) { s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); @@ -1911,7 +2085,7 @@ TEST_F(OEMCryptoClientTest, LoadKeysBadSignature) { message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -1928,14 +2102,13 @@ TEST_F(OEMCryptoClientTest, LoadKeysWithNoDerivedKeys) { // s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); + MessageData data; + s.FillSimpleMessage(&data, 0, 0); - MessageData encrypted; + MessageData encrypted; s.EncryptMessage(data, &encrypted); std::vector signature; - s.SignMessage(encrypted, &signature); + s.ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s.FillKeyArray(encrypted, key_array); @@ -1945,7 +2118,7 @@ TEST_F(OEMCryptoClientTest, LoadKeysWithNoDerivedKeys) { message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -1954,6 +2127,75 @@ TEST_F(OEMCryptoClientTest, LoadKeysWithNoDerivedKeys) { testTearDown(); } +/////////////////////////////////////////////////// +// Load, Refresh Keys Test +/////////////////////////////////////////////////// + +class OEMCryptoRefreshKeyTest : public OEMCryptoClientTest { + public: + void RefreshWithNonce(const int key_count) { + Session& s = createSession("ONE"); + s.open(); + s.GenerateDerivedKeys(); + s.LoadTestKeys(kDuration, 0); + uint32_t nonce; + s.GenerateNonce(&nonce); + s.RefreshTestKeys(key_count, + htonl(wvoec_mock::kControlNonceEnabled), nonce, + true ); + s.close(); + } + + void RefresNoNonce(const int key_count) { + Session& s = createSession("ONE"); + s.open(); + s.GenerateDerivedKeys(); + s.LoadTestKeys(kDuration, 0); + uint32_t nonce; + s.GenerateNonce(&nonce); + s.RefreshTestKeys(key_count,0, 0, true ); + s.close(); + } + + void RefreshOldNonce(const int key_count) { + Session& s = createSession("ONE"); + s.open(); + s.GenerateDerivedKeys(); + s.LoadTestKeys(kDuration, 0); + uint32_t nonce = s.get_nonce(); + s.RefreshTestKeys(key_count, + htonl(wvoec_mock::kControlNonceEnabled), nonce, + false ); + s.close(); + } + void RefreshBadNonce(const int key_count) { + Session& s = createSession("ONE"); + s.open(); + s.GenerateDerivedKeys(); + s.LoadTestKeys(kDuration, 0); + uint32_t nonce; + s.GenerateNonce(&nonce); + nonce = 42; + s.RefreshTestKeys(key_count, + htonl(wvoec_mock::kControlNonceEnabled), nonce, + false ); + s.close(); + } + +}; + +TEST_F(OEMCryptoRefreshKeyTest, RefreshKeys) { + testSetUp(); + InstallKeybox(kDefaultKeybox); + RefreshWithNonce(1); + RefreshWithNonce(kNumKeys); + RefreshOldNonce(1); + RefreshOldNonce(kNumKeys); + RefreshBadNonce(1); + RefreshBadNonce(kNumKeys); + testTearDown(); +} + /////////////////////////////////////////////////// // Decrypt Tests /////////////////////////////////////////////////// @@ -1966,7 +2208,7 @@ TEST_F(OEMCryptoClientTest, Decrypt) { s.open(); s.GenerateDerivedKeys(); - s.LoadTestKeys(); + s.LoadTestKeys(kDuration, 0); // Select the key (from FillSimpleMessage) vector keyId = wvcdm::a2b_hex("000000000000000000000000"); @@ -2005,7 +2247,65 @@ TEST_F(OEMCryptoClientTest, Decrypt) { // Decrypt the data sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0], encryptedData.size(), true, &encryptionIv[0], 0, - &destBuffer); + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, + unencryptedData.size())); + + s.close(); + testTearDown(); +} + +TEST_F(OEMCryptoClientTest, DecryptZeroDuration) { + OEMCryptoResult sts; + testSetUp(); + InstallKeybox(kDefaultKeybox); + Session& s = createSession("ONE"); + s.open(); + + s.GenerateDerivedKeys(); + s.LoadTestKeys(0, 0); + + // Select the key (from FillSimpleMessage) + 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, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); ASSERT_EQ(OEMCrypto_SUCCESS, sts); ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, unencryptedData.size())); @@ -2022,7 +2322,7 @@ TEST_F(OEMCryptoClientTest, DecryptWithOffset) { s.open(); s.GenerateDerivedKeys(); - s.LoadTestKeys(); + s.LoadTestKeys(kDuration, 0); // Select the key (from FillSimpleMessage) vector keyId = wvcdm::a2b_hex("000000000000000000000000"); @@ -2063,7 +2363,8 @@ TEST_F(OEMCryptoClientTest, DecryptWithOffset) { // Decrypt the data sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0], encryptedData.size(), true, &encryptionIv[0], 5, - &destBuffer); + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); ASSERT_EQ(OEMCrypto_SUCCESS, sts); ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, unencryptedData.size())); @@ -2080,7 +2381,7 @@ TEST_F(OEMCryptoClientTest, DecryptUnencrypted) { s.open(); s.GenerateDerivedKeys(); - s.LoadTestKeys(); + s.LoadTestKeys(kDuration, 0); // Select the key (from FillSimpleMessage) vector keyId = wvcdm::a2b_hex("000000000000000000000000"); @@ -2110,7 +2411,8 @@ TEST_F(OEMCryptoClientTest, DecryptUnencrypted) { // Decrypt the data sts = OEMCrypto_DecryptCTR(s.session_id(), &unencryptedData[0], unencryptedData.size(), false, &encryptionIv[0], 0, - &destBuffer); + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); ASSERT_EQ(OEMCrypto_SUCCESS, sts); ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, unencryptedData.size())); @@ -2151,7 +2453,8 @@ TEST_F(OEMCryptoClientTest, DecryptUnencryptedNoKey) { // Decrypt the data sts = OEMCrypto_DecryptCTR(s.session_id(), &unencryptedData[0], unencryptedData.size(), false, &encryptionIv[0], 0, - &destBuffer); + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); ASSERT_EQ(OEMCrypto_SUCCESS, sts); ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, unencryptedData.size())); @@ -2166,28 +2469,9 @@ TEST_F(OEMCryptoClientTest, DecryptSecureToClear) { InstallKeybox(kDefaultKeybox); Session& s = createSession("ONE"); s.open(); - s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); - data.keys[0].control.control_bits = htonl(wvoec_mock::kControlObserveDataPath - | wvoec_mock::kControlDataPathSecure); - - MessageData encrypted; - s.EncryptMessage(data, &encrypted); - std::vector signature; - s.SignMessage(encrypted, &signature); - OEMCrypto_KeyObject key_array[kNumKeys]; - const uint8_t* message_ptr = reinterpret_cast(&encrypted); - s.FillKeyArray(encrypted, key_array); - sts = OEMCrypto_LoadKeys(s.session_id(), - message_ptr, sizeof(encrypted), - &signature[0], signature.size(), - encrypted.mac_key_iv, - encrypted.mac_key, - kNumKeys, key_array); - ASSERT_EQ(OEMCrypto_SUCCESS, sts); + s.LoadTestKeys(kDuration, wvoec_mock::kControlObserveDataPath + | wvoec_mock::kControlDataPathSecure); // Select the key (from FillSimpleMessage) vector keyId = wvcdm::a2b_hex("000000000000000000000000"); @@ -2226,7 +2510,8 @@ TEST_F(OEMCryptoClientTest, DecryptSecureToClear) { // Decrypt the data sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0], encryptedData.size(), true, &encryptionIv[0], 0, - &destBuffer); + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); ASSERT_NE(OEMCrypto_SUCCESS, sts); ASSERT_NE(0, memcmp(&unencryptedData[0], outputBuffer, unencryptedData.size())); @@ -2242,25 +2527,7 @@ TEST_F(OEMCryptoClientTest, KeyDuration) { Session& s = createSession("ONE"); s.open(); s.GenerateDerivedKeys(); - const unsigned int kNumKeys = 3; - MessageData data; - s.FillSimpleMessage(&data); - data.keys[0].control.control_bits = htonl(wvoec_mock::kControlNonceEnabled); - data.keys[0].control.duration = htonl(2); // 2 seconds. - MessageData encrypted; - s.EncryptMessage(data, &encrypted); - std::vector signature; - s.SignMessage(encrypted, &signature); - OEMCrypto_KeyObject key_array[kNumKeys]; - const uint8_t* message_ptr = reinterpret_cast(&encrypted); - s.FillKeyArray(encrypted, key_array); - sts = OEMCrypto_LoadKeys(s.session_id(), - message_ptr, sizeof(encrypted), - &signature[0], signature.size(), - encrypted.mac_key_iv, - encrypted.mac_key, - kNumKeys, key_array); - ASSERT_EQ(OEMCrypto_SUCCESS, sts); + s.LoadTestKeys(kDuration, wvoec_mock::kControlNonceEnabled); // Select the key (from FillSimpleMessage) vector keyId = wvcdm::a2b_hex("000000000000000000000000"); @@ -2298,7 +2565,8 @@ TEST_F(OEMCryptoClientTest, KeyDuration) { // Decrypt the data sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0], encryptedData.size(), true, &encryptionIv[0], 0, - &destBuffer); + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); ASSERT_EQ(OEMCrypto_SUCCESS, sts); ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, unencryptedData.size())); @@ -2313,7 +2581,8 @@ TEST_F(OEMCryptoClientTest, KeyDuration) { // Decrypt the data sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0], encryptedData.size(), true, &encryptionIv[0], 0, - &destBuffer); + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); ASSERT_EQ(OEMCrypto_SUCCESS, sts); ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, unencryptedData.size())); @@ -2328,7 +2597,8 @@ TEST_F(OEMCryptoClientTest, KeyDuration) { // Decrypt the data sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0], encryptedData.size(), true, &encryptionIv[0], 0, - &destBuffer); + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); ASSERT_NE(OEMCrypto_SUCCESS, sts); ASSERT_NE(0, memcmp(&unencryptedData[0], outputBuffer, unencryptedData.size())); @@ -2364,9 +2634,8 @@ void TestKey(const uint8_t key[], size_t length) { } } TEST_F(OEMCryptoClientTest, ValidateRSATestKeys) { - TestKey(kTestRsaPrivateKey1_3072, sizeof(kTestRsaPrivateKey1_3072)); - TestKey(kTestRsaPrivateKey2_2048, sizeof(kTestRsaPrivateKey2_2048)); - TestKey(kTestRsaPrivateKey3_2048, sizeof(kTestRsaPrivateKey3_2048)); + TestKey(kTestPKCS1RSAPrivateKey2_2048, sizeof(kTestPKCS1RSAPrivateKey2_2048)); + TestKey(kTestPKCS1RSAPrivateKey3_2048, sizeof(kTestPKCS1RSAPrivateKey3_2048)); } TEST_F(OEMCryptoClientTest, CertificateProvision) { @@ -2382,8 +2651,9 @@ TEST_F(OEMCryptoClientTest, CertificateProvision) { vector wrapped_key; s.RewrapRSAKey(encrypted, signature, &wrapped_key); - vector clear_key(kTestRsaPrivateKey1_3072, - kTestRsaPrivateKey1_3072 + sizeof(kTestRsaPrivateKey1_3072)); + vector clear_key(kTestRSAPKCS8PrivateKeyInfo2_2048, + kTestRSAPKCS8PrivateKeyInfo2_2048 + + sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048)); ASSERT_EQ(NULL, find(wrapped_key, clear_key)); s.close(); @@ -2677,12 +2947,10 @@ TEST_F(OEMCryptoClientTest, RSASignature) { ASSERT_EQ(OEMCrypto_SUCCESS, sts); // In the real world, the signature above would just have been used to contact // the license server to get this response. - ASSERT_TRUE(s.PreparePublicKey(kTestRsaPublicKey1_3072, - sizeof(kTestRsaPublicKey1_3072))); + ASSERT_TRUE(s.PreparePublicKey(kTestRSAPublicKey2_2048, + sizeof(kTestRSAPublicKey2_2048))); ASSERT_TRUE(s.VerifyRSASignature(&licenseRequest[0], licenseRequest.size(), signature, &signature_length)); - - s.close(); testTearDown(); @@ -2713,7 +2981,7 @@ TEST_F(OEMCryptoClientTest, CertificateDecrypt) { s.open(); s.InstallRSASessionTestKey(wrapped_rsa_key); - s.LoadTestKeys(); + s.LoadTestKeys(kDuration, 0); // Select the key (from FillSimpleMessage) vector keyId = wvcdm::a2b_hex("000000000000000000000000"); @@ -2752,7 +3020,8 @@ TEST_F(OEMCryptoClientTest, CertificateDecrypt) { // Decrypt the data sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0], encryptedData.size(), true, &encryptionIv[0], 0, - &destBuffer); + &destBuffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); ASSERT_EQ(OEMCrypto_SUCCESS, sts); ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer, unencryptedData.size())); @@ -2779,8 +3048,7 @@ TEST_F(OEMCryptoClientTest, VersionNumber) { class OEMCryptoGenericDRMTest : public OEMCryptoClientTest { protected: - static const unsigned int kNumKeys = 4; - MessageData message_data_; + MessageData message_data_; static const size_t kBufferSize = 160; // multiple of encryption block size. uint8_t clear_buffer_[kBufferSize]; @@ -2789,7 +3057,7 @@ class OEMCryptoGenericDRMTest : public OEMCryptoClientTest { void MakeFourKeys(Session* s) { - s->FillSimpleMessage(&message_data_); + s->FillSimpleMessage(&message_data_, kDuration, 0); message_data_.keys[0].control.control_bits = htonl(wvoec_mock::kControlAllowEncrypt); message_data_.keys[1].control.control_bits = htonl(wvoec_mock::kControlAllowDecrypt); message_data_.keys[2].control.control_bits = htonl(wvoec_mock::kControlAllowSign); @@ -2808,10 +3076,10 @@ class OEMCryptoGenericDRMTest : public OEMCryptoClientTest { } void LoadFourKeys(Session* s) { - MessageData encrypted; + MessageData encrypted; s->EncryptMessage(message_data_, &encrypted); std::vector signature; - s->SignMessage(encrypted, &signature); + s->ServerSignMessage(encrypted, &signature); OEMCrypto_KeyObject key_array[kNumKeys]; const uint8_t* message_ptr = reinterpret_cast(&encrypted); s->FillKeyArray(encrypted, key_array); @@ -2820,7 +3088,7 @@ class OEMCryptoGenericDRMTest : public OEMCryptoClientTest { message_ptr, sizeof(encrypted), &signature[0], signature.size(), encrypted.mac_key_iv, - encrypted.mac_key, + encrypted.mac_keys, kNumKeys, key_array); ASSERT_EQ(OEMCrypto_SUCCESS, sts); } @@ -3017,6 +3285,33 @@ TEST_F(OEMCryptoGenericDRMTest, GenericKeyDecrypt) { testTearDown(); } +TEST_F(OEMCryptoGenericDRMTest, GenericSecureToClear) { + OEMCryptoResult sts; + testSetUp(); + InstallKeybox(kDefaultKeybox); + Session& s = createSession("ONE"); + s.open(); + s.GenerateDerivedKeys(); + MakeFourKeys(&s); + message_data_.keys[1].control.control_bits + |= htonl(wvoec_mock::kControlObserveDataPath + | wvoec_mock::kControlDataPathSecure); + LoadFourKeys(&s); + unsigned int key_index = 1; + uint8_t encrypted[kBufferSize]; + EncryptBuffer(key_index, clear_buffer_, encrypted); + sts = OEMCrypto_SelectKey(s.session_id(), message_data_.keys[key_index].key_id, + kTestKeyIdLength); + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + uint8_t resultant[kBufferSize]; + sts = OEMCrypto_Generic_Decrypt(s.session_id(), encrypted, kBufferSize, iv_, + OEMCrypto_AES_CBC_128_NO_PADDING, resultant); + ASSERT_NE(OEMCrypto_SUCCESS, sts); + ASSERT_NE(0, memcmp(clear_buffer_, resultant, kBufferSize)); + s.close(); + testTearDown(); +} + TEST_F(OEMCryptoGenericDRMTest, GenericKeyBadDecrypt) { testSetUp(); @@ -3113,10 +3408,10 @@ TEST_F(OEMCryptoGenericDRMTest, KeyDurationEncrypt) { s.open(); s.GenerateDerivedKeys(); MakeFourKeys(&s); - message_data_.keys[0].control.duration = htonl(2); // 2 seconds. - message_data_.keys[1].control.duration = htonl(2); // 2 seconds. - message_data_.keys[2].control.duration = htonl(2); // 2 seconds. - message_data_.keys[3].control.duration = htonl(2); // 2 seconds. + message_data_.keys[0].control.duration = htonl(kDuration); + message_data_.keys[1].control.duration = htonl(kDuration); + message_data_.keys[2].control.duration = htonl(kDuration); + message_data_.keys[3].control.duration = htonl(kDuration); LoadFourKeys(&s); uint8_t expected_encrypted[kBufferSize]; @@ -3155,10 +3450,10 @@ TEST_F(OEMCryptoGenericDRMTest, KeyDurationDecrypt) { s.open(); s.GenerateDerivedKeys(); MakeFourKeys(&s); - message_data_.keys[0].control.duration = htonl(2); // 2 seconds. - message_data_.keys[1].control.duration = htonl(2); // 2 seconds. - message_data_.keys[2].control.duration = htonl(2); // 2 seconds. - message_data_.keys[3].control.duration = htonl(2); // 2 seconds. + message_data_.keys[0].control.duration = htonl(kDuration); + message_data_.keys[1].control.duration = htonl(kDuration); + message_data_.keys[2].control.duration = htonl(kDuration); + message_data_.keys[3].control.duration = htonl(kDuration); LoadFourKeys(&s); unsigned int key_index = 1; @@ -3197,10 +3492,10 @@ TEST_F(OEMCryptoGenericDRMTest, KeyDurationSign) { s.GenerateDerivedKeys(); MakeFourKeys(&s); - message_data_.keys[0].control.duration = htonl(2); // 2 seconds. - message_data_.keys[1].control.duration = htonl(2); // 2 seconds. - message_data_.keys[2].control.duration = htonl(2); // 2 seconds. - message_data_.keys[3].control.duration = htonl(2); // 2 seconds. + message_data_.keys[0].control.duration = htonl(kDuration); + message_data_.keys[1].control.duration = htonl(kDuration); + message_data_.keys[2].control.duration = htonl(kDuration); + message_data_.keys[3].control.duration = htonl(kDuration); LoadFourKeys(&s); @@ -3244,10 +3539,10 @@ TEST_F(OEMCryptoGenericDRMTest, KeyDurationVerify) { s.open(); s.GenerateDerivedKeys(); MakeFourKeys(&s); - message_data_.keys[0].control.duration = htonl(2); // 2 seconds. - message_data_.keys[1].control.duration = htonl(2); // 2 seconds. - message_data_.keys[2].control.duration = htonl(2); // 2 seconds. - message_data_.keys[3].control.duration = htonl(2); // 2 seconds. + message_data_.keys[0].control.duration = htonl(kDuration); + message_data_.keys[1].control.duration = htonl(kDuration); + message_data_.keys[2].control.duration = htonl(kDuration); + message_data_.keys[3].control.duration = htonl(kDuration); LoadFourKeys(&s); unsigned int key_index = 3; @@ -3275,7 +3570,4 @@ TEST_F(OEMCryptoGenericDRMTest, KeyDurationVerify) { s.close(); testTearDown(); } - -// TODO(kqyang): Add more unit tests - } // namespace wvoec