Part of Qualcomm L1 OEMCrypto integration
Upgrade to version 2.1 of license protocol in OEMCrypto. related-to-bug: 8621521 Merge of https://widevine-internal-review.googlesource.com/#/c/4952/ from Widevine CDM repository to android repository. Change-Id: I0d85dae1981b7525ab17aec5f21cf668d078bf47
This commit is contained in:
committed by
Jeff Tinker
parent
bb0c62768a
commit
39ea1df671
@@ -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<uint8_t> enc_mac_key_str = std::vector<uint8_t>(
|
||||
enc_mac_key, enc_mac_key + wvcdm::MAC_KEY_SIZE);
|
||||
// V2.1 license protocol: update mac keys after processing license response
|
||||
const std::vector<uint8_t> enc_mac_keys_str = std::vector<uint8_t>(
|
||||
enc_mac_keys, enc_mac_keys + 2*wvcdm::MAC_KEY_SIZE);
|
||||
const std::vector<uint8_t> enc_mac_key_iv_str = std::vector<uint8_t>(
|
||||
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<uint8_t> key_control;
|
||||
std::vector<uint8_t> 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<uint8_t> key_id_str = std::vector<uint8_t>(key_id, key_id + key_id_length);
|
||||
if (!session_ctx->SelectContentKey(key_id_str)) {
|
||||
const std::vector<uint8_t> key_id_vec = std::vector<uint8_t>(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<uint8_t> dev_id_string = crypto_engine->keybox().device_id();
|
||||
if (dev_id_string.empty()) {
|
||||
std::vector<uint8_t> 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<WrappedRSAKey*>(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<uint8_t> mac_ctx_str(wrapped->context,
|
||||
wrapped->context + sizeof(wrapped->context));
|
||||
const std::vector<uint8_t> 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<const WrappedRSAKey*>(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<const WrappedRSAKey*>(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<uint8_t> mac_ctx_str(wrapped->context,
|
||||
wrapped->context + sizeof(wrapped->context));
|
||||
const std::vector<uint8_t> 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<uint8_t> ssn_key_str(enc_session_key,
|
||||
const std::vector<uint8_t> ssn_key_vec(enc_session_key,
|
||||
enc_session_key + enc_session_key_length);
|
||||
const std::vector<uint8_t> mac_ctx_str(mac_key_context,
|
||||
const std::vector<uint8_t> mac_ctx_vec(mac_key_context,
|
||||
mac_key_context + mac_key_context_length);
|
||||
const std::vector<uint8_t> enc_ctx_str(enc_key_context,
|
||||
const std::vector<uint8_t> 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;
|
||||
|
||||
Reference in New Issue
Block a user