diff --git a/libwvdrmengine/Android.mk b/libwvdrmengine/Android.mk index 0f528b63..d5762a12 100644 --- a/libwvdrmengine/Android.mk +++ b/libwvdrmengine/Android.mk @@ -59,7 +59,8 @@ LOCAL_C_INCLUDES := \ LOCAL_STATIC_LIBRARIES := \ libcdm \ - libl3crypto \ + libwvwrapper \ + libwvlevel3 \ libprotobuf-cpp-2.3.0-lite \ libwvdrmcryptoplugin \ libwvdrmdrmplugin \ @@ -87,6 +88,7 @@ include $(BUILD_SHARED_LIBRARY) include vendor/widevine/libwvdrmengine/cdm/Android.mk include vendor/widevine/libwvdrmengine/level3/Android.mk +include vendor/widevine/libwvdrmengine/oemcrypto/Android.mk include vendor/widevine/libwvdrmengine/mediacrypto/Android.mk include vendor/widevine/libwvdrmengine/mediadrm/Android.mk diff --git a/libwvdrmengine/cdm/core/src/client_files.proto b/libwvdrmengine/cdm/core/src/client_files.proto deleted file mode 100644 index 33ddb04c..00000000 --- a/libwvdrmengine/cdm/core/src/client_files.proto +++ /dev/null @@ -1,27 +0,0 @@ -// ---------------------------------------------------------------------------- -// client_files.proto -// ---------------------------------------------------------------------------- -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Description: -// Format of various files stored at the device. -// -syntax = "proto2"; - -package video_widevine_client.sdk; - -// need this if we are using libprotobuf-cpp-2.3.0-lite -option optimize_for = LITE_RUNTIME; - -message DeviceCertificateFileFormat { - optional int32 version = 1; - optional bytes certificate = 2; - optional bytes wrapped_private_key = 3; -} - -message LicenseFileFormat { - optional int32 version = 1; - optional bytes key_set_id = 2; - optional bytes license_request = 3; - optional bytes license = 4; -} diff --git a/libwvdrmengine/cdm/test/unit-test.mk b/libwvdrmengine/cdm/test/unit-test.mk index e465ca7c..909b8fb1 100644 --- a/libwvdrmengine/cdm/test/unit-test.mk +++ b/libwvdrmengine/cdm/test/unit-test.mk @@ -36,7 +36,8 @@ LOCAL_STATIC_LIBRARIES := \ libgmock \ libgtest \ libgtest_main \ - libl3crypto \ + libwvwrapper \ + libwvlevel3 \ libprotobuf-cpp-2.3.0-lite LOCAL_WHOLE_STATIC_LIBRARIES := libcdm_protos diff --git a/libwvdrmengine/level3/Android.mk b/libwvdrmengine/level3/Android.mk index 3f8a09ba..d52c9716 100644 --- a/libwvdrmengine/level3/Android.mk +++ b/libwvdrmengine/level3/Android.mk @@ -1,38 +1,4 @@ -LOCAL_PATH:= $(call my-dir) +ifneq ($(filter arm x86 mips,$(TARGET_ARCH)),) +include $(call all-subdir-makefiles) +endif -include $(CLEAR_VARS) - -# TODO(fredgc): remove mock code as real code starts working. -LOCAL_SRC_FILES := \ - $(TARGET_ARCH)/entry_points.cpp \ - ../oemcrypto/mock/src/oemcrypto_engine_mock.cpp \ - ../oemcrypto/mock/src/oemcrypto_key_mock.cpp \ - ../oemcrypto/mock/src/oemcrypto_keybox_mock.cpp \ - ../oemcrypto/mock/src/lock.cpp \ - ../oemcrypto/mock/src/log.cpp \ - ../oemcrypto/mock/src/string_conversions.cpp \ - ../oemcrypto/mock/src/wvcrc.cpp \ - -# TODO(fredgc): remove mock include when real code starts working. -LOCAL_C_INCLUDES += \ - vendor/widevine/libwvdrmengine/oemcrypto/mock/src \ - bionic \ - external/openssh \ - external/openssl/include \ - external/stlport/stlport \ - vendor/widevine/libwvdrmengine/oemcrypto/include \ - $(LOCAL_PATH)/include \ - $(LOCAL_PATH)/$(TARGET_ARCH) - -LOCAL_MODULE := libl3crypto - -LOCAL_SHARED_LIBRARIES := \ - libcrypto \ - libcutils \ - libdl \ - liblog \ - libstlport \ - libutils \ - libz \ - -include $(BUILD_STATIC_LIBRARY) diff --git a/libwvdrmengine/level3/arm/Android.mk b/libwvdrmengine/level3/arm/Android.mk new file mode 100644 index 00000000..74264a75 --- /dev/null +++ b/libwvdrmengine/level3/arm/Android.mk @@ -0,0 +1,12 @@ +ifeq ($(TARGET_ARCH),arm) +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE := libwvlevel3 +LOCAL_MODULE_CLASS := STATIC_LIBRARIES +LOCAL_MODULE_SUFFIX := .a +LOCAL_SRC_FILES := $(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX) +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_OWNER := widevine +include $(BUILD_PREBUILT) +endif # if arm. diff --git a/libwvdrmengine/level3/arm/entry_points.cpp b/libwvdrmengine/level3/arm/entry_points.cpp deleted file mode 100644 index 6f04a87c..00000000 --- a/libwvdrmengine/level3/arm/entry_points.cpp +++ /dev/null @@ -1,1308 +0,0 @@ -/******************************************************************************* - * - * Copyright 2013 Google Inc. All Rights Reserved. - * - * Wrapper for Level 1 OEMCrypto or Level 3 Fallback APIs - * - ******************************************************************************/ - -#include "OEMCryptoCENC.h" - -#include -#include -#include -#include -#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" - -namespace wvoec_mock { - -// TODO(fredgc): These are in the level 3 directory, but they are entry points for -// both level 3 and level 1. That is confusing. Fix it. -typedef OEMCryptoResult (*L1_Initialize_t)(void); -typedef OEMCryptoResult (*L1_Terminate_t)(void); -typedef OEMCryptoResult (*L1_OpenSession_t)(OEMCrypto_SESSION *session); -typedef OEMCryptoResult (*L1_CloseSession_t)(OEMCrypto_SESSION session); -typedef OEMCryptoResult (*L1_GenerateDerivedKeys_t)(OEMCrypto_SESSION session, - const uint8_t *mac_key_context, - uint32_t mac_key_context_length, - const uint8_t *enc_key_context, - uint32_t enc_key_context_length); -typedef OEMCryptoResult (*L1_GenerateNonce_t)(OEMCrypto_SESSION session, - uint32_t* nonce); -typedef OEMCryptoResult (*L1_GenerateSignature_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length); -typedef OEMCryptoResult (*L1_LoadKeys_t)(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, - size_t num_keys, - const OEMCrypto_KeyObject* key_array); -typedef OEMCryptoResult (*L1_RefreshKeys_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - size_t num_keys, - const OEMCrypto_KeyRefreshObject* key_array); -typedef OEMCryptoResult (*L1_SelectKey_t)(const OEMCrypto_SESSION session, - const uint8_t* key_id, - size_t key_id_length); -typedef OEMCryptoResult (*L1_DecryptCTR_t)(OEMCrypto_SESSION session, - const uint8_t *data_addr, - size_t data_length, - bool is_encrypted, - const uint8_t *iv, - size_t offset, - 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); -typedef OEMCryptoResult (*L1_GetDeviceID_t)(uint8_t* deviceID, - size_t *idLength); -typedef OEMCryptoResult (*L1_GetKeyData_t)(uint8_t* keyData, - size_t *keyDataLength); -typedef OEMCryptoResult (*L1_GetRandom_t)(uint8_t* randomData, - size_t dataLength); -typedef OEMCryptoResult (*L1_WrapKeybox_t)(const uint8_t *keybox, - size_t keyBoxLength, - uint8_t *wrappedKeybox, - size_t *wrappedKeyBoxLength, - const uint8_t *transportKey, - size_t transportKeyLength); -typedef OEMCryptoResult (*L1_RewrapDeviceRSAKey_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - const uint32_t *nonce, - const uint8_t* enc_rsa_key, - size_t enc_rsa_key_length, - const uint8_t* enc_rsa_key_iv, - uint8_t* wrapped_rsa_key, - size_t *wrapped_rsa_key_length); -typedef OEMCryptoResult (*L1_LoadDeviceRSAKey_t)(OEMCrypto_SESSION session, - const uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length); -typedef OEMCryptoResult (*L1_GenerateRSASignature_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t *signature_length); -typedef OEMCryptoResult (*L1_DeriveKeysFromSessionKey_t)(OEMCrypto_SESSION session, - const uint8_t* enc_session_key, - size_t enc_session_key_length, - const uint8_t *mac_key_context, - size_t mac_key_context_length, - const uint8_t *enc_key_context, - size_t enc_key_context_length); -typedef OEMCryptoResult (*L1_Generic_Encrypt_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer); -typedef OEMCryptoResult (*L1_Generic_Decrypt_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer); - -typedef OEMCryptoResult (*L1_Generic_Sign_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - uint8_t* signature, - size_t* signature_length); - -typedef OEMCryptoResult (*L1_Generic_Verify_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - const uint8_t* signature, - size_t signature_length); -typedef uint8_t (*L1_APIVersion_t)(); -typedef const char* (*L1_SecurityLevel_t)(); - -struct FunctionPointers { - void* library; - L1_Initialize_t OEMCrypto_Initialize; - L1_Terminate_t OEMCrypto_Terminate; - L1_OpenSession_t OEMCrypto_OpenSession; - L1_CloseSession_t OEMCrypto_CloseSession; - L1_GenerateDerivedKeys_t OEMCrypto_GenerateDerivedKeys; - L1_GenerateNonce_t OEMCrypto_GenerateNonce; - L1_GenerateSignature_t OEMCrypto_GenerateSignature; - L1_LoadKeys_t OEMCrypto_LoadKeys; - L1_RefreshKeys_t OEMCrypto_RefreshKeys; - L1_SelectKey_t OEMCrypto_SelectKey; - L1_DecryptCTR_t OEMCrypto_DecryptCTR; - L1_InstallKeybox_t OEMCrypto_InstallKeybox; - L1_IsKeyboxValid_t OEMCrypto_IsKeyboxValid; - L1_GetDeviceID_t OEMCrypto_GetDeviceID; - L1_GetKeyData_t OEMCrypto_GetKeyData; - L1_GetRandom_t OEMCrypto_GetRandom; - L1_WrapKeybox_t OEMCrypto_WrapKeybox; - L1_RewrapDeviceRSAKey_t OEMCrypto_RewrapDeviceRSAKey; - L1_LoadDeviceRSAKey_t OEMCrypto_LoadDeviceRSAKey; - L1_GenerateRSASignature_t OEMCrypto_GenerateRSASignature; - L1_DeriveKeysFromSessionKey_t OEMCrypto_DeriveKeysFromSessionKey; - L1_APIVersion_t OEMCrypto_APIVersion; - L1_SecurityLevel_t OEMCrypto_SecurityLevel; - L1_Generic_Encrypt_t OEMCrypto_Generic_Encrypt; - L1_Generic_Decrypt_t OEMCrypto_Generic_Decrypt; - L1_Generic_Sign_t OEMCrypto_Generic_Sign; - L1_Generic_Verify_t OEMCrypto_Generic_Verify; -}; -static struct FunctionPointers level1; - -#define QUOTE_DEFINE(A) #A -#define QUOTE(A) QUOTE_DEFINE(A) -#define LOOKUP(Type, Name) \ - level1.Name = (Type)dlsym(level1.library, QUOTE(Name)); \ - if (!level1.Name) { \ - dll_valid = false; \ - } - -typedef struct { - uint8_t signature[wvcdm::MAC_KEY_SIZE]; - uint8_t context[wvcdm::MAC_KEY_SIZE]; - uint8_t iv[wvcdm::KEY_IV_SIZE]; - uint8_t enc_rsa_key[]; -} WrappedRSAKey; - -static CryptoEngine* crypto_engine = NULL; - -extern "C" -OEMCryptoResult OEMCrypto_Initialize(void) { - crypto_engine = new CryptoEngine; - if (!crypto_engine || !crypto_engine->Initialized()) { - LOGE("[OEMCrypto_Initialize(): failed]"); - return OEMCrypto_ERROR_INIT_FAILED; - } - LOGD("OEMCrypto_Initialize Level 3 success. Now I will try to load Level 1"); - - level1.library = dlopen("liboemcrypto.so", RTLD_NOW); - if (level1.library == NULL) { - LOGW("Could not load liboemcrypto.so. Falling Back to L3."); - return OEMCrypto_SUCCESS; - } - bool dll_valid = true; - LOOKUP(L1_Initialize_t, OEMCrypto_Initialize); - LOOKUP(L1_Terminate_t, OEMCrypto_Terminate); - LOOKUP(L1_OpenSession_t, OEMCrypto_OpenSession); - LOOKUP(L1_CloseSession_t, OEMCrypto_CloseSession); - LOOKUP(L1_GenerateDerivedKeys_t, OEMCrypto_GenerateDerivedKeys); - LOOKUP(L1_GenerateNonce_t, OEMCrypto_GenerateNonce); - LOOKUP(L1_GenerateSignature_t, OEMCrypto_GenerateSignature); - LOOKUP(L1_LoadKeys_t, OEMCrypto_LoadKeys); - LOOKUP(L1_RefreshKeys_t, OEMCrypto_RefreshKeys); - LOOKUP(L1_SelectKey_t, OEMCrypto_SelectKey); - LOOKUP(L1_DecryptCTR_t, OEMCrypto_DecryptCTR); - LOOKUP(L1_InstallKeybox_t, OEMCrypto_InstallKeybox); - LOOKUP(L1_IsKeyboxValid_t, OEMCrypto_IsKeyboxValid); - LOOKUP(L1_GetDeviceID_t, OEMCrypto_GetDeviceID); - LOOKUP(L1_GetKeyData_t, OEMCrypto_GetKeyData); - LOOKUP(L1_GetRandom_t, OEMCrypto_GetRandom); - LOOKUP(L1_WrapKeybox_t, OEMCrypto_WrapKeybox); - - // TODO(fredgc): Move the validity check from here to below after we have - // an L1 library that matches current version. - if (!dll_valid) { - dlclose(level1.library); - level1.library = NULL; - LOGW("Could not load functions from liboemcrypto.so. Falling Back to L3."); - return OEMCrypto_SUCCESS; - } - - LOOKUP(L1_RewrapDeviceRSAKey_t, OEMCrypto_RewrapDeviceRSAKey); - LOOKUP(L1_LoadDeviceRSAKey_t, OEMCrypto_LoadDeviceRSAKey); - LOOKUP(L1_GenerateRSASignature_t, OEMCrypto_GenerateRSASignature); - LOOKUP(L1_DeriveKeysFromSessionKey_t, OEMCrypto_DeriveKeysFromSessionKey); - LOOKUP(L1_APIVersion_t, OEMCrypto_APIVersion); - LOOKUP(L1_SecurityLevel_t, OEMCrypto_SecurityLevel); - LOOKUP(L1_Generic_Decrypt_t, OEMCrypto_Generic_Decrypt); - LOOKUP(L1_Generic_Encrypt_t, OEMCrypto_Generic_Encrypt); - LOOKUP(L1_Generic_Sign_t, OEMCrypto_Generic_Sign); - LOOKUP(L1_Generic_Verify_t, OEMCrypto_Generic_Verify); - - // TODO(fredgc): Move the validity check from above to here after we have - // a current L1 library. - - OEMCryptoResult st = level1.OEMCrypto_Initialize(); - if (st != OEMCrypto_SUCCESS) { - LOGW("Could not initialize liboemcrypto.so. Falling Back to L3."); - dlclose(level1.library); - level1.library = NULL; - return OEMCrypto_SUCCESS; - } - if (level1.OEMCrypto_APIVersion ) { - uint32_t level1_version = level1.OEMCrypto_APIVersion(); - if( level1_version > oec_latest_version ) { // Check for foward jump. - LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.", - level1_version, oec_latest_version); - dlclose(level1.library); - level1.library = NULL; - return OEMCrypto_SUCCESS; - } - } - LOGD("OEMCrypto_Initialize Level 1 success. I will use level 1."); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Terminate(void) { - if (level1.library) { - OEMCryptoResult st = level1.OEMCrypto_Terminate(); - dlclose(level1.library); - level1.library = NULL; - return st; - } - if (!crypto_engine) { - LOGE("[OEMCrypto_Terminate(): failed]"); - return OEMCrypto_ERROR_TERMINATE_FAILED; - } - - if (crypto_engine->Initialized()) { - crypto_engine->Terminate(); - } - - delete crypto_engine; - crypto_engine = NULL; - LOGD("[OEMCrypto_Terminate(): success]"); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) { - if (level1.library) { - return level1.OEMCrypto_OpenSession(session); - } - SessionId sid = crypto_engine->CreateSession(); - *session = (OEMCrypto_SESSION)sid; - LOGD("[OEMCrypto_OpenSession(): SID=%08x]", sid); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session) { - if (level1.library) { - return level1.OEMCrypto_CloseSession(session); - } - if (!crypto_engine->DestroySession((SessionId)session)) { - LOGD("[OEMCrypto_CloseSession(SID=%08X): failed]", session); - return OEMCrypto_ERROR_CLOSE_SESSION_FAILED; - } else { - LOGD("[OEMCrypto_CloseSession(SID=%08X): success]", session); - return OEMCrypto_SUCCESS; - } -} - -extern "C" -OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session, - uint32_t* nonce) { - if (level1.library) { - return level1.OEMCrypto_GenerateNonce(session, nonce); - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateNonce(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - uint32_t nonce_value; - uint8_t* nonce_string = reinterpret_cast(&nonce_value); - - // Generate 4 bytes of random data - if (!RAND_bytes(nonce_string, 4)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - session_ctx->AddNonce(nonce_value); - *nonce = nonce_value; - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GenerateDerivedKeys(OEMCrypto_SESSION session, - const uint8_t* mac_key_context, - uint32_t mac_key_context_length, - const uint8_t* enc_key_context, - uint32_t enc_key_context_length) { - if (level1.library) { - return level1.OEMCrypto_GenerateDerivedKeys(session, mac_key_context, - mac_key_context_length, - enc_key_context, - enc_key_context_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - const std::vector mac_ctx_str(mac_key_context, - mac_key_context + mac_key_context_length); - const std::vector enc_ctx_str(enc_key_context, - enc_key_context + enc_key_context_length); - - // Generate mac and encryption keys for current session context - if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), - mac_ctx_str, enc_ctx_str)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GenerateSignature(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length) { - if (level1.library) { - return level1.OEMCrypto_GenerateSignature( session, message, message_length, - signature, signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateSignature(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - if (*signature_length < SHA256_DIGEST_LENGTH) { - *signature_length = SHA256_DIGEST_LENGTH; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0) { - LOGE("[OEMCrypto_GenerateSignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateSignature(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (session_ctx->GenerateSignature(message, - message_length, - signature, - signature_length)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE;; -} - -bool RangeCheck(const uint8_t* message, - uint32_t message_length, - const uint8_t* field, - uint32_t field_length, - bool allow_null) { - if (field == NULL) return allow_null; - if (field < message) return false; - if (field + field_length > message + message_length) return false; - return true; -} - -extern "C" -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_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_keys, - num_keys, key_array); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_LoadKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_LoadKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0 || - key_array == NULL || num_keys == 0) { - LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Range check - 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.]"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - for (unsigned int i = 0; i < num_keys; i++) { - if (!RangeCheck(message, message_length, key_array[i].key_id, - key_array[i].key_id_length, false) || - !RangeCheck(message, message_length, key_array[i].key_data, - key_array[i].key_data_length, false) || - !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, false) || - !RangeCheck(message, message_length, key_array[i].key_control_iv, - wvcdm::KEY_IV_SIZE, false)) { - LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE -range check %d]", i); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - } - - // Validate message signature - if (!session_ctx->ValidateMessage(message, message_length, signature, signature_length)) { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - session_ctx->StartTimer(); - - // Decrypt and install keys in key object - // Each key will have a key control block. They will all have the same nonce. - bool status = true; - std::vector key_id; - std::vector enc_key_data; - std::vector key_data_iv; - std::vector key_control; - std::vector key_control_iv; - for (unsigned int i = 0; i < num_keys; i++) { - key_id.assign(key_array[i].key_id, - key_array[i].key_id + key_array[i].key_id_length); - enc_key_data.assign(key_array[i].key_data, - key_array[i].key_data + key_array[i].key_data_length); - key_data_iv.assign(key_array[i].key_data_iv, - key_array[i].key_data_iv + wvcdm::KEY_IV_SIZE); - if (key_array[i].key_control == NULL) { - status = false; - break; - } - 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 (!session_ctx->InstallKey(key_id, enc_key_data, key_data_iv, key_control, - key_control_iv)) { - status = false; - break; - } - } - - session_ctx->FlushNonces(); - if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - - // enc_mac_key can be NULL if license renewal is not supported - if (enc_mac_keys == NULL) return OEMCrypto_SUCCESS; - - // 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->UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - size_t num_keys, - const OEMCrypto_KeyRefreshObject* key_array) { - if (level1.library) { - return level1.OEMCrypto_RefreshKeys(session, message, message_length, signature, - signature_length, num_keys, key_array); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_RefreshKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_RefreshKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0 || - num_keys == 0) { - LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Range check - for (unsigned int i = 0; i < num_keys; i++) { - 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, false) || - !RangeCheck(message, message_length, key_array[i].key_control_iv, - wvcdm::KEY_IV_SIZE, true)) { - LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - } - - // Validate message signature - if (!session_ctx->ValidateMessage(message, message_length, - signature, signature_length)) { - LOGE("[OEMCrypto_RefreshKeys(): signature was invalid]"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - // Decrypt and refresh keys in key refresh object - bool status = true; - std::vector key_id; - std::vector key_control; - std::vector key_control_iv; - for (unsigned int i = 0; i < num_keys; i++) { - 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); - key_control.assign(key_array[i].key_control, - key_array[i].key_control + wvcdm::KEY_CONTROL_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_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; - } - } - - session_ctx->FlushNonces(); - if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - - session_ctx->StartTimer(); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, - const uint8_t* key_id, - size_t key_id_length) { - if (level1.library) { - return level1.OEMCrypto_SelectKey(session, key_id, key_id_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_SelectKey(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_SelectKey(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - 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; - } - - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, - const uint8_t* data_addr, - size_t data_length, - bool is_encrypted, - const uint8_t* iv, - 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, block_offset, - out_buffer, subsample_flags); - } - wvoec_mock::BufferType buffer_type = kBufferTypeDirect; - uint8_t* destination = NULL; - size_t max_length = 0; - switch (out_buffer->type) { - case OEMCrypto_BufferType_Clear: - buffer_type = kBufferTypeClear; - destination = out_buffer->buffer.clear.address; - max_length = out_buffer->buffer.clear.max_length; - break; - case OEMCrypto_BufferType_Secure: - buffer_type = kBufferTypeSecure; - destination = ((uint8_t*)out_buffer->buffer.secure.handle - + out_buffer->buffer.secure.offset); - max_length = out_buffer->buffer.secure.max_length; - break; - default: - case OEMCrypto_BufferType_Direct: - buffer_type = kBufferTypeDirect; - destination = NULL; - break; - } - - if (buffer_type != kBufferTypeDirect && max_length < data_length) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_SHORT_BUFFER]"); - 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()) { - LOGE("[OEMCrypto_DecryptCTR(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (data_addr == NULL || data_length == 0 || - iv == NULL || out_buffer == NULL) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - if (!crypto_engine->DecryptCTR(session_ctx, iv, (int)block_offset, - data_addr, data_length, is_encrypted, - destination, buffer_type)) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_DECRYPT_FAILED]"); - return OEMCrypto_ERROR_DECRYPT_FAILED; - } - - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox, - size_t keyBoxLength) { - if (level1.library) { - return level1.OEMCrypto_InstallKeybox(keybox, keyBoxLength); - } - if (crypto_engine->keybox().InstallKeybox(keybox, keyBoxLength)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_WRITE_KEYBOX; -} - -extern "C" -OEMCryptoResult OEMCrypto_IsKeyboxValid(void) { - if (level1.library) { - return level1.OEMCrypto_IsKeyboxValid(); - } - switch(crypto_engine->ValidateKeybox()) { - case NO_ERROR: return OEMCrypto_SUCCESS; - case BAD_CRC: return OEMCrypto_ERROR_BAD_CRC; - case BAD_MAGIC: return OEMCrypto_ERROR_BAD_MAGIC; - default: - case OTHER_ERROR: return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } -} - -extern "C" -OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, - size_t* idLength) { - if (level1.library) { - return level1.OEMCrypto_GetDeviceID(deviceID, idLength); - } - 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_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_vec[0], dev_id_len); - *idLength = dev_id_len; - LOGD("[OEMCrypto_GetDeviceId(): success]"); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData, - size_t* keyDataLength) { - if (level1.library) { - return level1.OEMCrypto_GetKeyData(keyData, keyDataLength); - } - size_t length = crypto_engine->keybox().key_data_length(); - if (*keyDataLength < length) { - *keyDataLength = length; - LOGE("[OEMCrypto_GetKeyData(): ERROR_SHORT_BUFFER]"); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - memset(keyData, 0, *keyDataLength); - memcpy(keyData, crypto_engine->keybox().key_data(), length); - *keyDataLength = length; - LOGD("[OEMCrypto_GetKeyData(): success]"); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, size_t dataLength) { - if (level1.library) { - return level1.OEMCrypto_GetRandom(randomData, dataLength); - } - if (!randomData) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (RAND_bytes(randomData, dataLength)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE; -} - -extern "C" -OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox, - size_t keyBoxLength, - uint8_t* wrappedKeybox, - size_t* wrappedKeyBoxLength, - const uint8_t* transportKey, - size_t transportKeyLength) { - if (level1.library) { - return level1.OEMCrypto_WrapKeybox(keybox, keyBoxLength, wrappedKeybox, - wrappedKeyBoxLength, transportKey, - transportKeyLength); - } - if (!keybox || !wrappedKeybox || !wrappedKeyBoxLength - || (keyBoxLength != *wrappedKeyBoxLength)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // This implementation ignores the transport key. For test keys, we - // don't need to encrypt the keybox. - memcpy(wrappedKeybox, keybox, keyBoxLength); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - const uint32_t* nonce, - const uint8_t* enc_rsa_key, - size_t enc_rsa_key_length, - const uint8_t* enc_rsa_key_iv, - uint8_t* wrapped_rsa_key, - size_t* wrapped_rsa_key_length) { - if (level1.library) { - if (!level1.OEMCrypto_RewrapDeviceRSAKey ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_RewrapDeviceRSAKey( session, message, message_length, - signature, signature_length, nonce, - enc_rsa_key, enc_rsa_key_length, - enc_rsa_key_iv, wrapped_rsa_key, - wrapped_rsa_key_length); - } - if (wrapped_rsa_key_length == NULL) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - // For the reference implementation, the wrapped key and the encrypted - // key are the same size -- just encrypted with different keys. - // We add 32 bytes for a context, 32 for iv, and 32 bytes for a signature. - // Important: This layout must match OEMCrypto_LoadDeviceRSAKey below. - size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey); - - if (wrapped_rsa_key == NULL || *wrapped_rsa_key_length < buffer_size) { - LOGW("[OEMCrypto_RewrapDeviceRSAKey(): Wrapped Keybox Short Buffer]"); - *wrapped_rsa_key_length = buffer_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *wrapped_rsa_key_length = buffer_size; // Tell caller how much space we used. - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): 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]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (message == NULL || message_length == 0 || signature == NULL - || signature_length == 0 || nonce == NULL || enc_rsa_key == NULL) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Range check - if (!RangeCheck(message, message_length, reinterpret_cast(nonce), - sizeof(uint32_t), true) || - !RangeCheck(message, message_length, enc_rsa_key, enc_rsa_key_length, - true) || - !RangeCheck(message, message_length, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE, - true)) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): - range check.]"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - - // Validate nonce - if (!session_ctx->CheckNonce(*nonce)) { - return OEMCrypto_ERROR_INVALID_NONCE; - } - session_ctx->FlushNonces(); - - // 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( 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; - } - } - const std::vector context(wrapped->context, - wrapped->context + sizeof(wrapped->context)); - // Generate mac and encryption keys for encrypting the signature. - 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( 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; - - // 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 result; -} - -extern "C" -OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, - const uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length) { - if (level1.library) { - if (!level1.OEMCrypto_LoadDeviceRSAKey ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_LoadDeviceRSAKey( session, wrapped_rsa_key, - 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 (NO_ERROR != crypto_engine->ValidateKeybox()) { - 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_LoadDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - const std::vector context(wrapped->context, - wrapped->context + sizeof(wrapped->context)); - // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), - context, context)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // 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; - } - 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" -OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length) { - if (level1.library) { - if (!level1.OEMCrypto_GenerateRSASignature ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_GenerateRSASignature(session, message, message_length, - signature, signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateRSASignature(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - if (signature_length == 0) { - LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateRSASignature(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - size_t required_size = session_ctx->RSASignatureSize(); - if (*signature_length < required_size) { - *signature_length = required_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0) { - LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - if (session_ctx->GenerateRSASignature(message, - message_length, - signature, - signature_length)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE;; -} - -extern "C" -OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(OEMCrypto_SESSION session, - const uint8_t* enc_session_key, - size_t enc_session_key_length, - const uint8_t* mac_key_context, - size_t mac_key_context_length, - const uint8_t* enc_key_context, - size_t enc_key_context_length) { - if (level1.library) { - if (!level1.OEMCrypto_DeriveKeysFromSessionKey ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_DeriveKeysFromSessionKey(session, enc_session_key, - enc_session_key_length, - mac_key_context, - mac_key_context_length, - enc_key_context, - enc_key_context_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - const std::vector ssn_key_vec(enc_session_key, - enc_session_key + enc_session_key_length); - const std::vector mac_ctx_vec(mac_key_context, - mac_key_context + mac_key_context_length); - 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_vec, mac_ctx_vec, enc_ctx_vec)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -uint32_t OEMCrypto_APIVersion() { - if (level1.library) { - if (!level1.OEMCrypto_APIVersion ) { - return 5; - } - return level1.OEMCrypto_APIVersion(); - } - return oec_latest_version; -} - -extern "C" -const char* OEMCrypto_SecurityLevel() { - if (level1.library) { - if (!level1.OEMCrypto_SecurityLevel ) { - return "Unknown"; - } - return level1.OEMCrypto_SecurityLevel(); - } - return "L3"; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Encrypt(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - - if (level1.library) { - if (!level1.OEMCrypto_Generic_Encrypt ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Encrypt(session, in_buffer, buffer_length, - iv, algorithm, out_buffer); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Enrypt(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Enrypt(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (in_buffer == NULL || buffer_length == 0 || - iv == NULL || out_buffer == NULL) { - LOGE("[OEMCrypto_Generic_Enrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!session_ctx->Generic_Encrypt(in_buffer, buffer_length, iv, algorithm, - out_buffer)) { - LOGE("[OEMCrypto_Generic_Enrypt(): OEMCrypto_ERROR_UNKNOWN_FAILURE]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Decrypt(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - if (level1.library) { - if (!level1.OEMCrypto_Generic_Decrypt ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Decrypt(session, in_buffer, buffer_length, - iv, algorithm, out_buffer); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Decrypt(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Decrypt(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (!session_ctx->Generic_Decrypt(in_buffer, buffer_length, iv, algorithm, - out_buffer)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (in_buffer == NULL || buffer_length == 0 || - iv == NULL || out_buffer == NULL) { - LOGE("[OEMCrypto_Generic_Decrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - uint8_t* signature, - size_t* signature_length) { - if (level1.library) { - if (!level1.OEMCrypto_Generic_Sign ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Sign(session, in_buffer, buffer_length, - algorithm, signature, - signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Sign(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Sign(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (*signature_length < SHA256_DIGEST_LENGTH) { - *signature_length = SHA256_DIGEST_LENGTH; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - if (in_buffer == NULL || buffer_length == 0 || signature == NULL) { - LOGE("[OEMCrypto_Generic_Sign(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!session_ctx->Generic_Sign(in_buffer, buffer_length, algorithm, - signature, signature_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Verify(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - const uint8_t* signature, - size_t signature_length) { - if (level1.library) { - if (!level1.OEMCrypto_Generic_Verify ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Verify(session, in_buffer, buffer_length, - algorithm, signature, - signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Verify(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Verify(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (signature_length != SHA256_DIGEST_LENGTH) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (in_buffer == NULL || buffer_length == 0 || signature == NULL) { - LOGE("[OEMCrypto_Generic_Verify(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!session_ctx->Generic_Verify(in_buffer, buffer_length, algorithm, - signature, signature_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -}; // namespace wvoec_mock diff --git a/libwvdrmengine/level3/arm/libwvlevel3.a b/libwvdrmengine/level3/arm/libwvlevel3.a new file mode 100644 index 00000000..18353b7e Binary files /dev/null and b/libwvdrmengine/level3/arm/libwvlevel3.a differ diff --git a/libwvdrmengine/level3/mips/Android.mk b/libwvdrmengine/level3/mips/Android.mk new file mode 100644 index 00000000..b1311058 --- /dev/null +++ b/libwvdrmengine/level3/mips/Android.mk @@ -0,0 +1,12 @@ +ifeq ($(TARGET_ARCH),mips) +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE := libwvlevel3 +LOCAL_MODULE_CLASS := STATIC_LIBRARIES +LOCAL_MODULE_SUFFIX := .a +LOCAL_SRC_FILES := $(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX) +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_OWNER := widevine +include $(BUILD_PREBUILT) +endif # if mips. diff --git a/libwvdrmengine/level3/mips/entry_points.cpp b/libwvdrmengine/level3/mips/entry_points.cpp deleted file mode 100644 index 6f04a87c..00000000 --- a/libwvdrmengine/level3/mips/entry_points.cpp +++ /dev/null @@ -1,1308 +0,0 @@ -/******************************************************************************* - * - * Copyright 2013 Google Inc. All Rights Reserved. - * - * Wrapper for Level 1 OEMCrypto or Level 3 Fallback APIs - * - ******************************************************************************/ - -#include "OEMCryptoCENC.h" - -#include -#include -#include -#include -#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" - -namespace wvoec_mock { - -// TODO(fredgc): These are in the level 3 directory, but they are entry points for -// both level 3 and level 1. That is confusing. Fix it. -typedef OEMCryptoResult (*L1_Initialize_t)(void); -typedef OEMCryptoResult (*L1_Terminate_t)(void); -typedef OEMCryptoResult (*L1_OpenSession_t)(OEMCrypto_SESSION *session); -typedef OEMCryptoResult (*L1_CloseSession_t)(OEMCrypto_SESSION session); -typedef OEMCryptoResult (*L1_GenerateDerivedKeys_t)(OEMCrypto_SESSION session, - const uint8_t *mac_key_context, - uint32_t mac_key_context_length, - const uint8_t *enc_key_context, - uint32_t enc_key_context_length); -typedef OEMCryptoResult (*L1_GenerateNonce_t)(OEMCrypto_SESSION session, - uint32_t* nonce); -typedef OEMCryptoResult (*L1_GenerateSignature_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length); -typedef OEMCryptoResult (*L1_LoadKeys_t)(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, - size_t num_keys, - const OEMCrypto_KeyObject* key_array); -typedef OEMCryptoResult (*L1_RefreshKeys_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - size_t num_keys, - const OEMCrypto_KeyRefreshObject* key_array); -typedef OEMCryptoResult (*L1_SelectKey_t)(const OEMCrypto_SESSION session, - const uint8_t* key_id, - size_t key_id_length); -typedef OEMCryptoResult (*L1_DecryptCTR_t)(OEMCrypto_SESSION session, - const uint8_t *data_addr, - size_t data_length, - bool is_encrypted, - const uint8_t *iv, - size_t offset, - 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); -typedef OEMCryptoResult (*L1_GetDeviceID_t)(uint8_t* deviceID, - size_t *idLength); -typedef OEMCryptoResult (*L1_GetKeyData_t)(uint8_t* keyData, - size_t *keyDataLength); -typedef OEMCryptoResult (*L1_GetRandom_t)(uint8_t* randomData, - size_t dataLength); -typedef OEMCryptoResult (*L1_WrapKeybox_t)(const uint8_t *keybox, - size_t keyBoxLength, - uint8_t *wrappedKeybox, - size_t *wrappedKeyBoxLength, - const uint8_t *transportKey, - size_t transportKeyLength); -typedef OEMCryptoResult (*L1_RewrapDeviceRSAKey_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - const uint32_t *nonce, - const uint8_t* enc_rsa_key, - size_t enc_rsa_key_length, - const uint8_t* enc_rsa_key_iv, - uint8_t* wrapped_rsa_key, - size_t *wrapped_rsa_key_length); -typedef OEMCryptoResult (*L1_LoadDeviceRSAKey_t)(OEMCrypto_SESSION session, - const uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length); -typedef OEMCryptoResult (*L1_GenerateRSASignature_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t *signature_length); -typedef OEMCryptoResult (*L1_DeriveKeysFromSessionKey_t)(OEMCrypto_SESSION session, - const uint8_t* enc_session_key, - size_t enc_session_key_length, - const uint8_t *mac_key_context, - size_t mac_key_context_length, - const uint8_t *enc_key_context, - size_t enc_key_context_length); -typedef OEMCryptoResult (*L1_Generic_Encrypt_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer); -typedef OEMCryptoResult (*L1_Generic_Decrypt_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer); - -typedef OEMCryptoResult (*L1_Generic_Sign_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - uint8_t* signature, - size_t* signature_length); - -typedef OEMCryptoResult (*L1_Generic_Verify_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - const uint8_t* signature, - size_t signature_length); -typedef uint8_t (*L1_APIVersion_t)(); -typedef const char* (*L1_SecurityLevel_t)(); - -struct FunctionPointers { - void* library; - L1_Initialize_t OEMCrypto_Initialize; - L1_Terminate_t OEMCrypto_Terminate; - L1_OpenSession_t OEMCrypto_OpenSession; - L1_CloseSession_t OEMCrypto_CloseSession; - L1_GenerateDerivedKeys_t OEMCrypto_GenerateDerivedKeys; - L1_GenerateNonce_t OEMCrypto_GenerateNonce; - L1_GenerateSignature_t OEMCrypto_GenerateSignature; - L1_LoadKeys_t OEMCrypto_LoadKeys; - L1_RefreshKeys_t OEMCrypto_RefreshKeys; - L1_SelectKey_t OEMCrypto_SelectKey; - L1_DecryptCTR_t OEMCrypto_DecryptCTR; - L1_InstallKeybox_t OEMCrypto_InstallKeybox; - L1_IsKeyboxValid_t OEMCrypto_IsKeyboxValid; - L1_GetDeviceID_t OEMCrypto_GetDeviceID; - L1_GetKeyData_t OEMCrypto_GetKeyData; - L1_GetRandom_t OEMCrypto_GetRandom; - L1_WrapKeybox_t OEMCrypto_WrapKeybox; - L1_RewrapDeviceRSAKey_t OEMCrypto_RewrapDeviceRSAKey; - L1_LoadDeviceRSAKey_t OEMCrypto_LoadDeviceRSAKey; - L1_GenerateRSASignature_t OEMCrypto_GenerateRSASignature; - L1_DeriveKeysFromSessionKey_t OEMCrypto_DeriveKeysFromSessionKey; - L1_APIVersion_t OEMCrypto_APIVersion; - L1_SecurityLevel_t OEMCrypto_SecurityLevel; - L1_Generic_Encrypt_t OEMCrypto_Generic_Encrypt; - L1_Generic_Decrypt_t OEMCrypto_Generic_Decrypt; - L1_Generic_Sign_t OEMCrypto_Generic_Sign; - L1_Generic_Verify_t OEMCrypto_Generic_Verify; -}; -static struct FunctionPointers level1; - -#define QUOTE_DEFINE(A) #A -#define QUOTE(A) QUOTE_DEFINE(A) -#define LOOKUP(Type, Name) \ - level1.Name = (Type)dlsym(level1.library, QUOTE(Name)); \ - if (!level1.Name) { \ - dll_valid = false; \ - } - -typedef struct { - uint8_t signature[wvcdm::MAC_KEY_SIZE]; - uint8_t context[wvcdm::MAC_KEY_SIZE]; - uint8_t iv[wvcdm::KEY_IV_SIZE]; - uint8_t enc_rsa_key[]; -} WrappedRSAKey; - -static CryptoEngine* crypto_engine = NULL; - -extern "C" -OEMCryptoResult OEMCrypto_Initialize(void) { - crypto_engine = new CryptoEngine; - if (!crypto_engine || !crypto_engine->Initialized()) { - LOGE("[OEMCrypto_Initialize(): failed]"); - return OEMCrypto_ERROR_INIT_FAILED; - } - LOGD("OEMCrypto_Initialize Level 3 success. Now I will try to load Level 1"); - - level1.library = dlopen("liboemcrypto.so", RTLD_NOW); - if (level1.library == NULL) { - LOGW("Could not load liboemcrypto.so. Falling Back to L3."); - return OEMCrypto_SUCCESS; - } - bool dll_valid = true; - LOOKUP(L1_Initialize_t, OEMCrypto_Initialize); - LOOKUP(L1_Terminate_t, OEMCrypto_Terminate); - LOOKUP(L1_OpenSession_t, OEMCrypto_OpenSession); - LOOKUP(L1_CloseSession_t, OEMCrypto_CloseSession); - LOOKUP(L1_GenerateDerivedKeys_t, OEMCrypto_GenerateDerivedKeys); - LOOKUP(L1_GenerateNonce_t, OEMCrypto_GenerateNonce); - LOOKUP(L1_GenerateSignature_t, OEMCrypto_GenerateSignature); - LOOKUP(L1_LoadKeys_t, OEMCrypto_LoadKeys); - LOOKUP(L1_RefreshKeys_t, OEMCrypto_RefreshKeys); - LOOKUP(L1_SelectKey_t, OEMCrypto_SelectKey); - LOOKUP(L1_DecryptCTR_t, OEMCrypto_DecryptCTR); - LOOKUP(L1_InstallKeybox_t, OEMCrypto_InstallKeybox); - LOOKUP(L1_IsKeyboxValid_t, OEMCrypto_IsKeyboxValid); - LOOKUP(L1_GetDeviceID_t, OEMCrypto_GetDeviceID); - LOOKUP(L1_GetKeyData_t, OEMCrypto_GetKeyData); - LOOKUP(L1_GetRandom_t, OEMCrypto_GetRandom); - LOOKUP(L1_WrapKeybox_t, OEMCrypto_WrapKeybox); - - // TODO(fredgc): Move the validity check from here to below after we have - // an L1 library that matches current version. - if (!dll_valid) { - dlclose(level1.library); - level1.library = NULL; - LOGW("Could not load functions from liboemcrypto.so. Falling Back to L3."); - return OEMCrypto_SUCCESS; - } - - LOOKUP(L1_RewrapDeviceRSAKey_t, OEMCrypto_RewrapDeviceRSAKey); - LOOKUP(L1_LoadDeviceRSAKey_t, OEMCrypto_LoadDeviceRSAKey); - LOOKUP(L1_GenerateRSASignature_t, OEMCrypto_GenerateRSASignature); - LOOKUP(L1_DeriveKeysFromSessionKey_t, OEMCrypto_DeriveKeysFromSessionKey); - LOOKUP(L1_APIVersion_t, OEMCrypto_APIVersion); - LOOKUP(L1_SecurityLevel_t, OEMCrypto_SecurityLevel); - LOOKUP(L1_Generic_Decrypt_t, OEMCrypto_Generic_Decrypt); - LOOKUP(L1_Generic_Encrypt_t, OEMCrypto_Generic_Encrypt); - LOOKUP(L1_Generic_Sign_t, OEMCrypto_Generic_Sign); - LOOKUP(L1_Generic_Verify_t, OEMCrypto_Generic_Verify); - - // TODO(fredgc): Move the validity check from above to here after we have - // a current L1 library. - - OEMCryptoResult st = level1.OEMCrypto_Initialize(); - if (st != OEMCrypto_SUCCESS) { - LOGW("Could not initialize liboemcrypto.so. Falling Back to L3."); - dlclose(level1.library); - level1.library = NULL; - return OEMCrypto_SUCCESS; - } - if (level1.OEMCrypto_APIVersion ) { - uint32_t level1_version = level1.OEMCrypto_APIVersion(); - if( level1_version > oec_latest_version ) { // Check for foward jump. - LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.", - level1_version, oec_latest_version); - dlclose(level1.library); - level1.library = NULL; - return OEMCrypto_SUCCESS; - } - } - LOGD("OEMCrypto_Initialize Level 1 success. I will use level 1."); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Terminate(void) { - if (level1.library) { - OEMCryptoResult st = level1.OEMCrypto_Terminate(); - dlclose(level1.library); - level1.library = NULL; - return st; - } - if (!crypto_engine) { - LOGE("[OEMCrypto_Terminate(): failed]"); - return OEMCrypto_ERROR_TERMINATE_FAILED; - } - - if (crypto_engine->Initialized()) { - crypto_engine->Terminate(); - } - - delete crypto_engine; - crypto_engine = NULL; - LOGD("[OEMCrypto_Terminate(): success]"); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) { - if (level1.library) { - return level1.OEMCrypto_OpenSession(session); - } - SessionId sid = crypto_engine->CreateSession(); - *session = (OEMCrypto_SESSION)sid; - LOGD("[OEMCrypto_OpenSession(): SID=%08x]", sid); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session) { - if (level1.library) { - return level1.OEMCrypto_CloseSession(session); - } - if (!crypto_engine->DestroySession((SessionId)session)) { - LOGD("[OEMCrypto_CloseSession(SID=%08X): failed]", session); - return OEMCrypto_ERROR_CLOSE_SESSION_FAILED; - } else { - LOGD("[OEMCrypto_CloseSession(SID=%08X): success]", session); - return OEMCrypto_SUCCESS; - } -} - -extern "C" -OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session, - uint32_t* nonce) { - if (level1.library) { - return level1.OEMCrypto_GenerateNonce(session, nonce); - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateNonce(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - uint32_t nonce_value; - uint8_t* nonce_string = reinterpret_cast(&nonce_value); - - // Generate 4 bytes of random data - if (!RAND_bytes(nonce_string, 4)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - session_ctx->AddNonce(nonce_value); - *nonce = nonce_value; - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GenerateDerivedKeys(OEMCrypto_SESSION session, - const uint8_t* mac_key_context, - uint32_t mac_key_context_length, - const uint8_t* enc_key_context, - uint32_t enc_key_context_length) { - if (level1.library) { - return level1.OEMCrypto_GenerateDerivedKeys(session, mac_key_context, - mac_key_context_length, - enc_key_context, - enc_key_context_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - const std::vector mac_ctx_str(mac_key_context, - mac_key_context + mac_key_context_length); - const std::vector enc_ctx_str(enc_key_context, - enc_key_context + enc_key_context_length); - - // Generate mac and encryption keys for current session context - if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), - mac_ctx_str, enc_ctx_str)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GenerateSignature(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length) { - if (level1.library) { - return level1.OEMCrypto_GenerateSignature( session, message, message_length, - signature, signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateSignature(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - if (*signature_length < SHA256_DIGEST_LENGTH) { - *signature_length = SHA256_DIGEST_LENGTH; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0) { - LOGE("[OEMCrypto_GenerateSignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateSignature(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (session_ctx->GenerateSignature(message, - message_length, - signature, - signature_length)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE;; -} - -bool RangeCheck(const uint8_t* message, - uint32_t message_length, - const uint8_t* field, - uint32_t field_length, - bool allow_null) { - if (field == NULL) return allow_null; - if (field < message) return false; - if (field + field_length > message + message_length) return false; - return true; -} - -extern "C" -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_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_keys, - num_keys, key_array); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_LoadKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_LoadKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0 || - key_array == NULL || num_keys == 0) { - LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Range check - 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.]"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - for (unsigned int i = 0; i < num_keys; i++) { - if (!RangeCheck(message, message_length, key_array[i].key_id, - key_array[i].key_id_length, false) || - !RangeCheck(message, message_length, key_array[i].key_data, - key_array[i].key_data_length, false) || - !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, false) || - !RangeCheck(message, message_length, key_array[i].key_control_iv, - wvcdm::KEY_IV_SIZE, false)) { - LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE -range check %d]", i); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - } - - // Validate message signature - if (!session_ctx->ValidateMessage(message, message_length, signature, signature_length)) { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - session_ctx->StartTimer(); - - // Decrypt and install keys in key object - // Each key will have a key control block. They will all have the same nonce. - bool status = true; - std::vector key_id; - std::vector enc_key_data; - std::vector key_data_iv; - std::vector key_control; - std::vector key_control_iv; - for (unsigned int i = 0; i < num_keys; i++) { - key_id.assign(key_array[i].key_id, - key_array[i].key_id + key_array[i].key_id_length); - enc_key_data.assign(key_array[i].key_data, - key_array[i].key_data + key_array[i].key_data_length); - key_data_iv.assign(key_array[i].key_data_iv, - key_array[i].key_data_iv + wvcdm::KEY_IV_SIZE); - if (key_array[i].key_control == NULL) { - status = false; - break; - } - 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 (!session_ctx->InstallKey(key_id, enc_key_data, key_data_iv, key_control, - key_control_iv)) { - status = false; - break; - } - } - - session_ctx->FlushNonces(); - if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - - // enc_mac_key can be NULL if license renewal is not supported - if (enc_mac_keys == NULL) return OEMCrypto_SUCCESS; - - // 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->UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - size_t num_keys, - const OEMCrypto_KeyRefreshObject* key_array) { - if (level1.library) { - return level1.OEMCrypto_RefreshKeys(session, message, message_length, signature, - signature_length, num_keys, key_array); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_RefreshKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_RefreshKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0 || - num_keys == 0) { - LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Range check - for (unsigned int i = 0; i < num_keys; i++) { - 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, false) || - !RangeCheck(message, message_length, key_array[i].key_control_iv, - wvcdm::KEY_IV_SIZE, true)) { - LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - } - - // Validate message signature - if (!session_ctx->ValidateMessage(message, message_length, - signature, signature_length)) { - LOGE("[OEMCrypto_RefreshKeys(): signature was invalid]"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - // Decrypt and refresh keys in key refresh object - bool status = true; - std::vector key_id; - std::vector key_control; - std::vector key_control_iv; - for (unsigned int i = 0; i < num_keys; i++) { - 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); - key_control.assign(key_array[i].key_control, - key_array[i].key_control + wvcdm::KEY_CONTROL_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_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; - } - } - - session_ctx->FlushNonces(); - if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - - session_ctx->StartTimer(); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, - const uint8_t* key_id, - size_t key_id_length) { - if (level1.library) { - return level1.OEMCrypto_SelectKey(session, key_id, key_id_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_SelectKey(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_SelectKey(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - 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; - } - - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, - const uint8_t* data_addr, - size_t data_length, - bool is_encrypted, - const uint8_t* iv, - 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, block_offset, - out_buffer, subsample_flags); - } - wvoec_mock::BufferType buffer_type = kBufferTypeDirect; - uint8_t* destination = NULL; - size_t max_length = 0; - switch (out_buffer->type) { - case OEMCrypto_BufferType_Clear: - buffer_type = kBufferTypeClear; - destination = out_buffer->buffer.clear.address; - max_length = out_buffer->buffer.clear.max_length; - break; - case OEMCrypto_BufferType_Secure: - buffer_type = kBufferTypeSecure; - destination = ((uint8_t*)out_buffer->buffer.secure.handle - + out_buffer->buffer.secure.offset); - max_length = out_buffer->buffer.secure.max_length; - break; - default: - case OEMCrypto_BufferType_Direct: - buffer_type = kBufferTypeDirect; - destination = NULL; - break; - } - - if (buffer_type != kBufferTypeDirect && max_length < data_length) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_SHORT_BUFFER]"); - 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()) { - LOGE("[OEMCrypto_DecryptCTR(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (data_addr == NULL || data_length == 0 || - iv == NULL || out_buffer == NULL) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - if (!crypto_engine->DecryptCTR(session_ctx, iv, (int)block_offset, - data_addr, data_length, is_encrypted, - destination, buffer_type)) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_DECRYPT_FAILED]"); - return OEMCrypto_ERROR_DECRYPT_FAILED; - } - - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox, - size_t keyBoxLength) { - if (level1.library) { - return level1.OEMCrypto_InstallKeybox(keybox, keyBoxLength); - } - if (crypto_engine->keybox().InstallKeybox(keybox, keyBoxLength)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_WRITE_KEYBOX; -} - -extern "C" -OEMCryptoResult OEMCrypto_IsKeyboxValid(void) { - if (level1.library) { - return level1.OEMCrypto_IsKeyboxValid(); - } - switch(crypto_engine->ValidateKeybox()) { - case NO_ERROR: return OEMCrypto_SUCCESS; - case BAD_CRC: return OEMCrypto_ERROR_BAD_CRC; - case BAD_MAGIC: return OEMCrypto_ERROR_BAD_MAGIC; - default: - case OTHER_ERROR: return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } -} - -extern "C" -OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, - size_t* idLength) { - if (level1.library) { - return level1.OEMCrypto_GetDeviceID(deviceID, idLength); - } - 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_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_vec[0], dev_id_len); - *idLength = dev_id_len; - LOGD("[OEMCrypto_GetDeviceId(): success]"); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData, - size_t* keyDataLength) { - if (level1.library) { - return level1.OEMCrypto_GetKeyData(keyData, keyDataLength); - } - size_t length = crypto_engine->keybox().key_data_length(); - if (*keyDataLength < length) { - *keyDataLength = length; - LOGE("[OEMCrypto_GetKeyData(): ERROR_SHORT_BUFFER]"); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - memset(keyData, 0, *keyDataLength); - memcpy(keyData, crypto_engine->keybox().key_data(), length); - *keyDataLength = length; - LOGD("[OEMCrypto_GetKeyData(): success]"); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, size_t dataLength) { - if (level1.library) { - return level1.OEMCrypto_GetRandom(randomData, dataLength); - } - if (!randomData) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (RAND_bytes(randomData, dataLength)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE; -} - -extern "C" -OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox, - size_t keyBoxLength, - uint8_t* wrappedKeybox, - size_t* wrappedKeyBoxLength, - const uint8_t* transportKey, - size_t transportKeyLength) { - if (level1.library) { - return level1.OEMCrypto_WrapKeybox(keybox, keyBoxLength, wrappedKeybox, - wrappedKeyBoxLength, transportKey, - transportKeyLength); - } - if (!keybox || !wrappedKeybox || !wrappedKeyBoxLength - || (keyBoxLength != *wrappedKeyBoxLength)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // This implementation ignores the transport key. For test keys, we - // don't need to encrypt the keybox. - memcpy(wrappedKeybox, keybox, keyBoxLength); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - const uint32_t* nonce, - const uint8_t* enc_rsa_key, - size_t enc_rsa_key_length, - const uint8_t* enc_rsa_key_iv, - uint8_t* wrapped_rsa_key, - size_t* wrapped_rsa_key_length) { - if (level1.library) { - if (!level1.OEMCrypto_RewrapDeviceRSAKey ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_RewrapDeviceRSAKey( session, message, message_length, - signature, signature_length, nonce, - enc_rsa_key, enc_rsa_key_length, - enc_rsa_key_iv, wrapped_rsa_key, - wrapped_rsa_key_length); - } - if (wrapped_rsa_key_length == NULL) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - // For the reference implementation, the wrapped key and the encrypted - // key are the same size -- just encrypted with different keys. - // We add 32 bytes for a context, 32 for iv, and 32 bytes for a signature. - // Important: This layout must match OEMCrypto_LoadDeviceRSAKey below. - size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey); - - if (wrapped_rsa_key == NULL || *wrapped_rsa_key_length < buffer_size) { - LOGW("[OEMCrypto_RewrapDeviceRSAKey(): Wrapped Keybox Short Buffer]"); - *wrapped_rsa_key_length = buffer_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *wrapped_rsa_key_length = buffer_size; // Tell caller how much space we used. - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): 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]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (message == NULL || message_length == 0 || signature == NULL - || signature_length == 0 || nonce == NULL || enc_rsa_key == NULL) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Range check - if (!RangeCheck(message, message_length, reinterpret_cast(nonce), - sizeof(uint32_t), true) || - !RangeCheck(message, message_length, enc_rsa_key, enc_rsa_key_length, - true) || - !RangeCheck(message, message_length, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE, - true)) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): - range check.]"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - - // Validate nonce - if (!session_ctx->CheckNonce(*nonce)) { - return OEMCrypto_ERROR_INVALID_NONCE; - } - session_ctx->FlushNonces(); - - // 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( 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; - } - } - const std::vector context(wrapped->context, - wrapped->context + sizeof(wrapped->context)); - // Generate mac and encryption keys for encrypting the signature. - 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( 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; - - // 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 result; -} - -extern "C" -OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, - const uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length) { - if (level1.library) { - if (!level1.OEMCrypto_LoadDeviceRSAKey ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_LoadDeviceRSAKey( session, wrapped_rsa_key, - 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 (NO_ERROR != crypto_engine->ValidateKeybox()) { - 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_LoadDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - const std::vector context(wrapped->context, - wrapped->context + sizeof(wrapped->context)); - // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), - context, context)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // 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; - } - 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" -OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length) { - if (level1.library) { - if (!level1.OEMCrypto_GenerateRSASignature ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_GenerateRSASignature(session, message, message_length, - signature, signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateRSASignature(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - if (signature_length == 0) { - LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateRSASignature(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - size_t required_size = session_ctx->RSASignatureSize(); - if (*signature_length < required_size) { - *signature_length = required_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0) { - LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - if (session_ctx->GenerateRSASignature(message, - message_length, - signature, - signature_length)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE;; -} - -extern "C" -OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(OEMCrypto_SESSION session, - const uint8_t* enc_session_key, - size_t enc_session_key_length, - const uint8_t* mac_key_context, - size_t mac_key_context_length, - const uint8_t* enc_key_context, - size_t enc_key_context_length) { - if (level1.library) { - if (!level1.OEMCrypto_DeriveKeysFromSessionKey ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_DeriveKeysFromSessionKey(session, enc_session_key, - enc_session_key_length, - mac_key_context, - mac_key_context_length, - enc_key_context, - enc_key_context_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - const std::vector ssn_key_vec(enc_session_key, - enc_session_key + enc_session_key_length); - const std::vector mac_ctx_vec(mac_key_context, - mac_key_context + mac_key_context_length); - 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_vec, mac_ctx_vec, enc_ctx_vec)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -uint32_t OEMCrypto_APIVersion() { - if (level1.library) { - if (!level1.OEMCrypto_APIVersion ) { - return 5; - } - return level1.OEMCrypto_APIVersion(); - } - return oec_latest_version; -} - -extern "C" -const char* OEMCrypto_SecurityLevel() { - if (level1.library) { - if (!level1.OEMCrypto_SecurityLevel ) { - return "Unknown"; - } - return level1.OEMCrypto_SecurityLevel(); - } - return "L3"; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Encrypt(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - - if (level1.library) { - if (!level1.OEMCrypto_Generic_Encrypt ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Encrypt(session, in_buffer, buffer_length, - iv, algorithm, out_buffer); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Enrypt(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Enrypt(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (in_buffer == NULL || buffer_length == 0 || - iv == NULL || out_buffer == NULL) { - LOGE("[OEMCrypto_Generic_Enrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!session_ctx->Generic_Encrypt(in_buffer, buffer_length, iv, algorithm, - out_buffer)) { - LOGE("[OEMCrypto_Generic_Enrypt(): OEMCrypto_ERROR_UNKNOWN_FAILURE]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Decrypt(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - if (level1.library) { - if (!level1.OEMCrypto_Generic_Decrypt ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Decrypt(session, in_buffer, buffer_length, - iv, algorithm, out_buffer); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Decrypt(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Decrypt(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (!session_ctx->Generic_Decrypt(in_buffer, buffer_length, iv, algorithm, - out_buffer)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (in_buffer == NULL || buffer_length == 0 || - iv == NULL || out_buffer == NULL) { - LOGE("[OEMCrypto_Generic_Decrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - uint8_t* signature, - size_t* signature_length) { - if (level1.library) { - if (!level1.OEMCrypto_Generic_Sign ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Sign(session, in_buffer, buffer_length, - algorithm, signature, - signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Sign(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Sign(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (*signature_length < SHA256_DIGEST_LENGTH) { - *signature_length = SHA256_DIGEST_LENGTH; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - if (in_buffer == NULL || buffer_length == 0 || signature == NULL) { - LOGE("[OEMCrypto_Generic_Sign(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!session_ctx->Generic_Sign(in_buffer, buffer_length, algorithm, - signature, signature_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Verify(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - const uint8_t* signature, - size_t signature_length) { - if (level1.library) { - if (!level1.OEMCrypto_Generic_Verify ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Verify(session, in_buffer, buffer_length, - algorithm, signature, - signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Verify(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Verify(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (signature_length != SHA256_DIGEST_LENGTH) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (in_buffer == NULL || buffer_length == 0 || signature == NULL) { - LOGE("[OEMCrypto_Generic_Verify(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!session_ctx->Generic_Verify(in_buffer, buffer_length, algorithm, - signature, signature_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -}; // namespace wvoec_mock diff --git a/libwvdrmengine/level3/mips/libwvlevel3.a b/libwvdrmengine/level3/mips/libwvlevel3.a new file mode 100644 index 00000000..77330e06 Binary files /dev/null and b/libwvdrmengine/level3/mips/libwvlevel3.a differ diff --git a/libwvdrmengine/level3/x86/Android.mk b/libwvdrmengine/level3/x86/Android.mk new file mode 100644 index 00000000..0f2a7792 --- /dev/null +++ b/libwvdrmengine/level3/x86/Android.mk @@ -0,0 +1,12 @@ +ifeq ($(TARGET_ARCH),x86) +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE := libwvlevel3 +LOCAL_MODULE_CLASS := STATIC_LIBRARIES +LOCAL_MODULE_SUFFIX := .a +LOCAL_SRC_FILES := $(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX) +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_OWNER := widevine +include $(BUILD_PREBUILT) +endif # if x86. diff --git a/libwvdrmengine/level3/x86/entry_points.cpp b/libwvdrmengine/level3/x86/entry_points.cpp deleted file mode 100644 index 6f04a87c..00000000 --- a/libwvdrmengine/level3/x86/entry_points.cpp +++ /dev/null @@ -1,1308 +0,0 @@ -/******************************************************************************* - * - * Copyright 2013 Google Inc. All Rights Reserved. - * - * Wrapper for Level 1 OEMCrypto or Level 3 Fallback APIs - * - ******************************************************************************/ - -#include "OEMCryptoCENC.h" - -#include -#include -#include -#include -#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" - -namespace wvoec_mock { - -// TODO(fredgc): These are in the level 3 directory, but they are entry points for -// both level 3 and level 1. That is confusing. Fix it. -typedef OEMCryptoResult (*L1_Initialize_t)(void); -typedef OEMCryptoResult (*L1_Terminate_t)(void); -typedef OEMCryptoResult (*L1_OpenSession_t)(OEMCrypto_SESSION *session); -typedef OEMCryptoResult (*L1_CloseSession_t)(OEMCrypto_SESSION session); -typedef OEMCryptoResult (*L1_GenerateDerivedKeys_t)(OEMCrypto_SESSION session, - const uint8_t *mac_key_context, - uint32_t mac_key_context_length, - const uint8_t *enc_key_context, - uint32_t enc_key_context_length); -typedef OEMCryptoResult (*L1_GenerateNonce_t)(OEMCrypto_SESSION session, - uint32_t* nonce); -typedef OEMCryptoResult (*L1_GenerateSignature_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length); -typedef OEMCryptoResult (*L1_LoadKeys_t)(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, - size_t num_keys, - const OEMCrypto_KeyObject* key_array); -typedef OEMCryptoResult (*L1_RefreshKeys_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - size_t num_keys, - const OEMCrypto_KeyRefreshObject* key_array); -typedef OEMCryptoResult (*L1_SelectKey_t)(const OEMCrypto_SESSION session, - const uint8_t* key_id, - size_t key_id_length); -typedef OEMCryptoResult (*L1_DecryptCTR_t)(OEMCrypto_SESSION session, - const uint8_t *data_addr, - size_t data_length, - bool is_encrypted, - const uint8_t *iv, - size_t offset, - 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); -typedef OEMCryptoResult (*L1_GetDeviceID_t)(uint8_t* deviceID, - size_t *idLength); -typedef OEMCryptoResult (*L1_GetKeyData_t)(uint8_t* keyData, - size_t *keyDataLength); -typedef OEMCryptoResult (*L1_GetRandom_t)(uint8_t* randomData, - size_t dataLength); -typedef OEMCryptoResult (*L1_WrapKeybox_t)(const uint8_t *keybox, - size_t keyBoxLength, - uint8_t *wrappedKeybox, - size_t *wrappedKeyBoxLength, - const uint8_t *transportKey, - size_t transportKeyLength); -typedef OEMCryptoResult (*L1_RewrapDeviceRSAKey_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - const uint32_t *nonce, - const uint8_t* enc_rsa_key, - size_t enc_rsa_key_length, - const uint8_t* enc_rsa_key_iv, - uint8_t* wrapped_rsa_key, - size_t *wrapped_rsa_key_length); -typedef OEMCryptoResult (*L1_LoadDeviceRSAKey_t)(OEMCrypto_SESSION session, - const uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length); -typedef OEMCryptoResult (*L1_GenerateRSASignature_t)(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t *signature_length); -typedef OEMCryptoResult (*L1_DeriveKeysFromSessionKey_t)(OEMCrypto_SESSION session, - const uint8_t* enc_session_key, - size_t enc_session_key_length, - const uint8_t *mac_key_context, - size_t mac_key_context_length, - const uint8_t *enc_key_context, - size_t enc_key_context_length); -typedef OEMCryptoResult (*L1_Generic_Encrypt_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer); -typedef OEMCryptoResult (*L1_Generic_Decrypt_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer); - -typedef OEMCryptoResult (*L1_Generic_Sign_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - uint8_t* signature, - size_t* signature_length); - -typedef OEMCryptoResult (*L1_Generic_Verify_t)(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - const uint8_t* signature, - size_t signature_length); -typedef uint8_t (*L1_APIVersion_t)(); -typedef const char* (*L1_SecurityLevel_t)(); - -struct FunctionPointers { - void* library; - L1_Initialize_t OEMCrypto_Initialize; - L1_Terminate_t OEMCrypto_Terminate; - L1_OpenSession_t OEMCrypto_OpenSession; - L1_CloseSession_t OEMCrypto_CloseSession; - L1_GenerateDerivedKeys_t OEMCrypto_GenerateDerivedKeys; - L1_GenerateNonce_t OEMCrypto_GenerateNonce; - L1_GenerateSignature_t OEMCrypto_GenerateSignature; - L1_LoadKeys_t OEMCrypto_LoadKeys; - L1_RefreshKeys_t OEMCrypto_RefreshKeys; - L1_SelectKey_t OEMCrypto_SelectKey; - L1_DecryptCTR_t OEMCrypto_DecryptCTR; - L1_InstallKeybox_t OEMCrypto_InstallKeybox; - L1_IsKeyboxValid_t OEMCrypto_IsKeyboxValid; - L1_GetDeviceID_t OEMCrypto_GetDeviceID; - L1_GetKeyData_t OEMCrypto_GetKeyData; - L1_GetRandom_t OEMCrypto_GetRandom; - L1_WrapKeybox_t OEMCrypto_WrapKeybox; - L1_RewrapDeviceRSAKey_t OEMCrypto_RewrapDeviceRSAKey; - L1_LoadDeviceRSAKey_t OEMCrypto_LoadDeviceRSAKey; - L1_GenerateRSASignature_t OEMCrypto_GenerateRSASignature; - L1_DeriveKeysFromSessionKey_t OEMCrypto_DeriveKeysFromSessionKey; - L1_APIVersion_t OEMCrypto_APIVersion; - L1_SecurityLevel_t OEMCrypto_SecurityLevel; - L1_Generic_Encrypt_t OEMCrypto_Generic_Encrypt; - L1_Generic_Decrypt_t OEMCrypto_Generic_Decrypt; - L1_Generic_Sign_t OEMCrypto_Generic_Sign; - L1_Generic_Verify_t OEMCrypto_Generic_Verify; -}; -static struct FunctionPointers level1; - -#define QUOTE_DEFINE(A) #A -#define QUOTE(A) QUOTE_DEFINE(A) -#define LOOKUP(Type, Name) \ - level1.Name = (Type)dlsym(level1.library, QUOTE(Name)); \ - if (!level1.Name) { \ - dll_valid = false; \ - } - -typedef struct { - uint8_t signature[wvcdm::MAC_KEY_SIZE]; - uint8_t context[wvcdm::MAC_KEY_SIZE]; - uint8_t iv[wvcdm::KEY_IV_SIZE]; - uint8_t enc_rsa_key[]; -} WrappedRSAKey; - -static CryptoEngine* crypto_engine = NULL; - -extern "C" -OEMCryptoResult OEMCrypto_Initialize(void) { - crypto_engine = new CryptoEngine; - if (!crypto_engine || !crypto_engine->Initialized()) { - LOGE("[OEMCrypto_Initialize(): failed]"); - return OEMCrypto_ERROR_INIT_FAILED; - } - LOGD("OEMCrypto_Initialize Level 3 success. Now I will try to load Level 1"); - - level1.library = dlopen("liboemcrypto.so", RTLD_NOW); - if (level1.library == NULL) { - LOGW("Could not load liboemcrypto.so. Falling Back to L3."); - return OEMCrypto_SUCCESS; - } - bool dll_valid = true; - LOOKUP(L1_Initialize_t, OEMCrypto_Initialize); - LOOKUP(L1_Terminate_t, OEMCrypto_Terminate); - LOOKUP(L1_OpenSession_t, OEMCrypto_OpenSession); - LOOKUP(L1_CloseSession_t, OEMCrypto_CloseSession); - LOOKUP(L1_GenerateDerivedKeys_t, OEMCrypto_GenerateDerivedKeys); - LOOKUP(L1_GenerateNonce_t, OEMCrypto_GenerateNonce); - LOOKUP(L1_GenerateSignature_t, OEMCrypto_GenerateSignature); - LOOKUP(L1_LoadKeys_t, OEMCrypto_LoadKeys); - LOOKUP(L1_RefreshKeys_t, OEMCrypto_RefreshKeys); - LOOKUP(L1_SelectKey_t, OEMCrypto_SelectKey); - LOOKUP(L1_DecryptCTR_t, OEMCrypto_DecryptCTR); - LOOKUP(L1_InstallKeybox_t, OEMCrypto_InstallKeybox); - LOOKUP(L1_IsKeyboxValid_t, OEMCrypto_IsKeyboxValid); - LOOKUP(L1_GetDeviceID_t, OEMCrypto_GetDeviceID); - LOOKUP(L1_GetKeyData_t, OEMCrypto_GetKeyData); - LOOKUP(L1_GetRandom_t, OEMCrypto_GetRandom); - LOOKUP(L1_WrapKeybox_t, OEMCrypto_WrapKeybox); - - // TODO(fredgc): Move the validity check from here to below after we have - // an L1 library that matches current version. - if (!dll_valid) { - dlclose(level1.library); - level1.library = NULL; - LOGW("Could not load functions from liboemcrypto.so. Falling Back to L3."); - return OEMCrypto_SUCCESS; - } - - LOOKUP(L1_RewrapDeviceRSAKey_t, OEMCrypto_RewrapDeviceRSAKey); - LOOKUP(L1_LoadDeviceRSAKey_t, OEMCrypto_LoadDeviceRSAKey); - LOOKUP(L1_GenerateRSASignature_t, OEMCrypto_GenerateRSASignature); - LOOKUP(L1_DeriveKeysFromSessionKey_t, OEMCrypto_DeriveKeysFromSessionKey); - LOOKUP(L1_APIVersion_t, OEMCrypto_APIVersion); - LOOKUP(L1_SecurityLevel_t, OEMCrypto_SecurityLevel); - LOOKUP(L1_Generic_Decrypt_t, OEMCrypto_Generic_Decrypt); - LOOKUP(L1_Generic_Encrypt_t, OEMCrypto_Generic_Encrypt); - LOOKUP(L1_Generic_Sign_t, OEMCrypto_Generic_Sign); - LOOKUP(L1_Generic_Verify_t, OEMCrypto_Generic_Verify); - - // TODO(fredgc): Move the validity check from above to here after we have - // a current L1 library. - - OEMCryptoResult st = level1.OEMCrypto_Initialize(); - if (st != OEMCrypto_SUCCESS) { - LOGW("Could not initialize liboemcrypto.so. Falling Back to L3."); - dlclose(level1.library); - level1.library = NULL; - return OEMCrypto_SUCCESS; - } - if (level1.OEMCrypto_APIVersion ) { - uint32_t level1_version = level1.OEMCrypto_APIVersion(); - if( level1_version > oec_latest_version ) { // Check for foward jump. - LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.", - level1_version, oec_latest_version); - dlclose(level1.library); - level1.library = NULL; - return OEMCrypto_SUCCESS; - } - } - LOGD("OEMCrypto_Initialize Level 1 success. I will use level 1."); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Terminate(void) { - if (level1.library) { - OEMCryptoResult st = level1.OEMCrypto_Terminate(); - dlclose(level1.library); - level1.library = NULL; - return st; - } - if (!crypto_engine) { - LOGE("[OEMCrypto_Terminate(): failed]"); - return OEMCrypto_ERROR_TERMINATE_FAILED; - } - - if (crypto_engine->Initialized()) { - crypto_engine->Terminate(); - } - - delete crypto_engine; - crypto_engine = NULL; - LOGD("[OEMCrypto_Terminate(): success]"); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) { - if (level1.library) { - return level1.OEMCrypto_OpenSession(session); - } - SessionId sid = crypto_engine->CreateSession(); - *session = (OEMCrypto_SESSION)sid; - LOGD("[OEMCrypto_OpenSession(): SID=%08x]", sid); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session) { - if (level1.library) { - return level1.OEMCrypto_CloseSession(session); - } - if (!crypto_engine->DestroySession((SessionId)session)) { - LOGD("[OEMCrypto_CloseSession(SID=%08X): failed]", session); - return OEMCrypto_ERROR_CLOSE_SESSION_FAILED; - } else { - LOGD("[OEMCrypto_CloseSession(SID=%08X): success]", session); - return OEMCrypto_SUCCESS; - } -} - -extern "C" -OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session, - uint32_t* nonce) { - if (level1.library) { - return level1.OEMCrypto_GenerateNonce(session, nonce); - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateNonce(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - uint32_t nonce_value; - uint8_t* nonce_string = reinterpret_cast(&nonce_value); - - // Generate 4 bytes of random data - if (!RAND_bytes(nonce_string, 4)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - session_ctx->AddNonce(nonce_value); - *nonce = nonce_value; - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GenerateDerivedKeys(OEMCrypto_SESSION session, - const uint8_t* mac_key_context, - uint32_t mac_key_context_length, - const uint8_t* enc_key_context, - uint32_t enc_key_context_length) { - if (level1.library) { - return level1.OEMCrypto_GenerateDerivedKeys(session, mac_key_context, - mac_key_context_length, - enc_key_context, - enc_key_context_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - const std::vector mac_ctx_str(mac_key_context, - mac_key_context + mac_key_context_length); - const std::vector enc_ctx_str(enc_key_context, - enc_key_context + enc_key_context_length); - - // Generate mac and encryption keys for current session context - if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), - mac_ctx_str, enc_ctx_str)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GenerateSignature(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length) { - if (level1.library) { - return level1.OEMCrypto_GenerateSignature( session, message, message_length, - signature, signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateSignature(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - if (*signature_length < SHA256_DIGEST_LENGTH) { - *signature_length = SHA256_DIGEST_LENGTH; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0) { - LOGE("[OEMCrypto_GenerateSignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateSignature(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (session_ctx->GenerateSignature(message, - message_length, - signature, - signature_length)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE;; -} - -bool RangeCheck(const uint8_t* message, - uint32_t message_length, - const uint8_t* field, - uint32_t field_length, - bool allow_null) { - if (field == NULL) return allow_null; - if (field < message) return false; - if (field + field_length > message + message_length) return false; - return true; -} - -extern "C" -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_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_keys, - num_keys, key_array); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_LoadKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_LoadKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0 || - key_array == NULL || num_keys == 0) { - LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Range check - 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.]"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - for (unsigned int i = 0; i < num_keys; i++) { - if (!RangeCheck(message, message_length, key_array[i].key_id, - key_array[i].key_id_length, false) || - !RangeCheck(message, message_length, key_array[i].key_data, - key_array[i].key_data_length, false) || - !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, false) || - !RangeCheck(message, message_length, key_array[i].key_control_iv, - wvcdm::KEY_IV_SIZE, false)) { - LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE -range check %d]", i); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - } - - // Validate message signature - if (!session_ctx->ValidateMessage(message, message_length, signature, signature_length)) { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - session_ctx->StartTimer(); - - // Decrypt and install keys in key object - // Each key will have a key control block. They will all have the same nonce. - bool status = true; - std::vector key_id; - std::vector enc_key_data; - std::vector key_data_iv; - std::vector key_control; - std::vector key_control_iv; - for (unsigned int i = 0; i < num_keys; i++) { - key_id.assign(key_array[i].key_id, - key_array[i].key_id + key_array[i].key_id_length); - enc_key_data.assign(key_array[i].key_data, - key_array[i].key_data + key_array[i].key_data_length); - key_data_iv.assign(key_array[i].key_data_iv, - key_array[i].key_data_iv + wvcdm::KEY_IV_SIZE); - if (key_array[i].key_control == NULL) { - status = false; - break; - } - 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 (!session_ctx->InstallKey(key_id, enc_key_data, key_data_iv, key_control, - key_control_iv)) { - status = false; - break; - } - } - - session_ctx->FlushNonces(); - if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - - // enc_mac_key can be NULL if license renewal is not supported - if (enc_mac_keys == NULL) return OEMCrypto_SUCCESS; - - // 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->UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - size_t num_keys, - const OEMCrypto_KeyRefreshObject* key_array) { - if (level1.library) { - return level1.OEMCrypto_RefreshKeys(session, message, message_length, signature, - signature_length, num_keys, key_array); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_RefreshKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_RefreshKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0 || - num_keys == 0) { - LOGE("[OEMCrypto_RefreshKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Range check - for (unsigned int i = 0; i < num_keys; i++) { - 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, false) || - !RangeCheck(message, message_length, key_array[i].key_control_iv, - wvcdm::KEY_IV_SIZE, true)) { - LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - } - - // Validate message signature - if (!session_ctx->ValidateMessage(message, message_length, - signature, signature_length)) { - LOGE("[OEMCrypto_RefreshKeys(): signature was invalid]"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - // Decrypt and refresh keys in key refresh object - bool status = true; - std::vector key_id; - std::vector key_control; - std::vector key_control_iv; - for (unsigned int i = 0; i < num_keys; i++) { - 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); - key_control.assign(key_array[i].key_control, - key_array[i].key_control + wvcdm::KEY_CONTROL_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_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; - } - } - - session_ctx->FlushNonces(); - if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - - session_ctx->StartTimer(); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, - const uint8_t* key_id, - size_t key_id_length) { - if (level1.library) { - return level1.OEMCrypto_SelectKey(session, key_id, key_id_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_SelectKey(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_SelectKey(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - 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; - } - - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, - const uint8_t* data_addr, - size_t data_length, - bool is_encrypted, - const uint8_t* iv, - 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, block_offset, - out_buffer, subsample_flags); - } - wvoec_mock::BufferType buffer_type = kBufferTypeDirect; - uint8_t* destination = NULL; - size_t max_length = 0; - switch (out_buffer->type) { - case OEMCrypto_BufferType_Clear: - buffer_type = kBufferTypeClear; - destination = out_buffer->buffer.clear.address; - max_length = out_buffer->buffer.clear.max_length; - break; - case OEMCrypto_BufferType_Secure: - buffer_type = kBufferTypeSecure; - destination = ((uint8_t*)out_buffer->buffer.secure.handle - + out_buffer->buffer.secure.offset); - max_length = out_buffer->buffer.secure.max_length; - break; - default: - case OEMCrypto_BufferType_Direct: - buffer_type = kBufferTypeDirect; - destination = NULL; - break; - } - - if (buffer_type != kBufferTypeDirect && max_length < data_length) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_SHORT_BUFFER]"); - 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()) { - LOGE("[OEMCrypto_DecryptCTR(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (data_addr == NULL || data_length == 0 || - iv == NULL || out_buffer == NULL) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - if (!crypto_engine->DecryptCTR(session_ctx, iv, (int)block_offset, - data_addr, data_length, is_encrypted, - destination, buffer_type)) { - LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_DECRYPT_FAILED]"); - return OEMCrypto_ERROR_DECRYPT_FAILED; - } - - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox, - size_t keyBoxLength) { - if (level1.library) { - return level1.OEMCrypto_InstallKeybox(keybox, keyBoxLength); - } - if (crypto_engine->keybox().InstallKeybox(keybox, keyBoxLength)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_WRITE_KEYBOX; -} - -extern "C" -OEMCryptoResult OEMCrypto_IsKeyboxValid(void) { - if (level1.library) { - return level1.OEMCrypto_IsKeyboxValid(); - } - switch(crypto_engine->ValidateKeybox()) { - case NO_ERROR: return OEMCrypto_SUCCESS; - case BAD_CRC: return OEMCrypto_ERROR_BAD_CRC; - case BAD_MAGIC: return OEMCrypto_ERROR_BAD_MAGIC; - default: - case OTHER_ERROR: return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } -} - -extern "C" -OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, - size_t* idLength) { - if (level1.library) { - return level1.OEMCrypto_GetDeviceID(deviceID, idLength); - } - 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_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_vec[0], dev_id_len); - *idLength = dev_id_len; - LOGD("[OEMCrypto_GetDeviceId(): success]"); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData, - size_t* keyDataLength) { - if (level1.library) { - return level1.OEMCrypto_GetKeyData(keyData, keyDataLength); - } - size_t length = crypto_engine->keybox().key_data_length(); - if (*keyDataLength < length) { - *keyDataLength = length; - LOGE("[OEMCrypto_GetKeyData(): ERROR_SHORT_BUFFER]"); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - memset(keyData, 0, *keyDataLength); - memcpy(keyData, crypto_engine->keybox().key_data(), length); - *keyDataLength = length; - LOGD("[OEMCrypto_GetKeyData(): success]"); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, size_t dataLength) { - if (level1.library) { - return level1.OEMCrypto_GetRandom(randomData, dataLength); - } - if (!randomData) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (RAND_bytes(randomData, dataLength)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE; -} - -extern "C" -OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox, - size_t keyBoxLength, - uint8_t* wrappedKeybox, - size_t* wrappedKeyBoxLength, - const uint8_t* transportKey, - size_t transportKeyLength) { - if (level1.library) { - return level1.OEMCrypto_WrapKeybox(keybox, keyBoxLength, wrappedKeybox, - wrappedKeyBoxLength, transportKey, - transportKeyLength); - } - if (!keybox || !wrappedKeybox || !wrappedKeyBoxLength - || (keyBoxLength != *wrappedKeyBoxLength)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // This implementation ignores the transport key. For test keys, we - // don't need to encrypt the keybox. - memcpy(wrappedKeybox, keybox, keyBoxLength); - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length, - const uint32_t* nonce, - const uint8_t* enc_rsa_key, - size_t enc_rsa_key_length, - const uint8_t* enc_rsa_key_iv, - uint8_t* wrapped_rsa_key, - size_t* wrapped_rsa_key_length) { - if (level1.library) { - if (!level1.OEMCrypto_RewrapDeviceRSAKey ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_RewrapDeviceRSAKey( session, message, message_length, - signature, signature_length, nonce, - enc_rsa_key, enc_rsa_key_length, - enc_rsa_key_iv, wrapped_rsa_key, - wrapped_rsa_key_length); - } - if (wrapped_rsa_key_length == NULL) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - // For the reference implementation, the wrapped key and the encrypted - // key are the same size -- just encrypted with different keys. - // We add 32 bytes for a context, 32 for iv, and 32 bytes for a signature. - // Important: This layout must match OEMCrypto_LoadDeviceRSAKey below. - size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey); - - if (wrapped_rsa_key == NULL || *wrapped_rsa_key_length < buffer_size) { - LOGW("[OEMCrypto_RewrapDeviceRSAKey(): Wrapped Keybox Short Buffer]"); - *wrapped_rsa_key_length = buffer_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *wrapped_rsa_key_length = buffer_size; // Tell caller how much space we used. - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): 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]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (message == NULL || message_length == 0 || signature == NULL - || signature_length == 0 || nonce == NULL || enc_rsa_key == NULL) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Range check - if (!RangeCheck(message, message_length, reinterpret_cast(nonce), - sizeof(uint32_t), true) || - !RangeCheck(message, message_length, enc_rsa_key, enc_rsa_key_length, - true) || - !RangeCheck(message, message_length, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE, - true)) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): - range check.]"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - - // Validate nonce - if (!session_ctx->CheckNonce(*nonce)) { - return OEMCrypto_ERROR_INVALID_NONCE; - } - session_ctx->FlushNonces(); - - // 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( 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; - } - } - const std::vector context(wrapped->context, - wrapped->context + sizeof(wrapped->context)); - // Generate mac and encryption keys for encrypting the signature. - 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( 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; - - // 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 result; -} - -extern "C" -OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, - const uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length) { - if (level1.library) { - if (!level1.OEMCrypto_LoadDeviceRSAKey ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_LoadDeviceRSAKey( session, wrapped_rsa_key, - 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 (NO_ERROR != crypto_engine->ValidateKeybox()) { - 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_LoadDeviceRSAKey(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - const std::vector context(wrapped->context, - wrapped->context + sizeof(wrapped->context)); - // Generate mac and encryption keys for encrypting the signature. - if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key().value(), - context, context)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // 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; - } - 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" -OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length) { - if (level1.library) { - if (!level1.OEMCrypto_GenerateRSASignature ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_GenerateRSASignature(session, message, message_length, - signature, signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateRSASignature(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - if (signature_length == 0) { - LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateRSASignature(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - size_t required_size = session_ctx->RSASignatureSize(); - if (*signature_length < required_size) { - *signature_length = required_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - - if (message == NULL || message_length == 0 || - signature == NULL || signature_length == 0) { - LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - if (session_ctx->GenerateRSASignature(message, - message_length, - signature, - signature_length)) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE;; -} - -extern "C" -OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(OEMCrypto_SESSION session, - const uint8_t* enc_session_key, - size_t enc_session_key_length, - const uint8_t* mac_key_context, - size_t mac_key_context_length, - const uint8_t* enc_key_context, - size_t enc_key_context_length) { - if (level1.library) { - if (!level1.OEMCrypto_DeriveKeysFromSessionKey ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_DeriveKeysFromSessionKey(session, enc_session_key, - enc_session_key_length, - mac_key_context, - mac_key_context_length, - enc_key_context, - enc_key_context_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - const std::vector ssn_key_vec(enc_session_key, - enc_session_key + enc_session_key_length); - const std::vector mac_ctx_vec(mac_key_context, - mac_key_context + mac_key_context_length); - 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_vec, mac_ctx_vec, enc_ctx_vec)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -uint32_t OEMCrypto_APIVersion() { - if (level1.library) { - if (!level1.OEMCrypto_APIVersion ) { - return 5; - } - return level1.OEMCrypto_APIVersion(); - } - return oec_latest_version; -} - -extern "C" -const char* OEMCrypto_SecurityLevel() { - if (level1.library) { - if (!level1.OEMCrypto_SecurityLevel ) { - return "Unknown"; - } - return level1.OEMCrypto_SecurityLevel(); - } - return "L3"; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Encrypt(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - - if (level1.library) { - if (!level1.OEMCrypto_Generic_Encrypt ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Encrypt(session, in_buffer, buffer_length, - iv, algorithm, out_buffer); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Enrypt(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Enrypt(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (in_buffer == NULL || buffer_length == 0 || - iv == NULL || out_buffer == NULL) { - LOGE("[OEMCrypto_Generic_Enrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!session_ctx->Generic_Encrypt(in_buffer, buffer_length, iv, algorithm, - out_buffer)) { - LOGE("[OEMCrypto_Generic_Enrypt(): OEMCrypto_ERROR_UNKNOWN_FAILURE]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Decrypt(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - if (level1.library) { - if (!level1.OEMCrypto_Generic_Decrypt ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Decrypt(session, in_buffer, buffer_length, - iv, algorithm, out_buffer); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Decrypt(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Decrypt(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (!session_ctx->Generic_Decrypt(in_buffer, buffer_length, iv, algorithm, - out_buffer)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (in_buffer == NULL || buffer_length == 0 || - iv == NULL || out_buffer == NULL) { - LOGE("[OEMCrypto_Generic_Decrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - uint8_t* signature, - size_t* signature_length) { - if (level1.library) { - if (!level1.OEMCrypto_Generic_Sign ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Sign(session, in_buffer, buffer_length, - algorithm, signature, - signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Sign(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Sign(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (*signature_length < SHA256_DIGEST_LENGTH) { - *signature_length = SHA256_DIGEST_LENGTH; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - if (in_buffer == NULL || buffer_length == 0 || signature == NULL) { - LOGE("[OEMCrypto_Generic_Sign(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!session_ctx->Generic_Sign(in_buffer, buffer_length, algorithm, - signature, signature_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -extern "C" -OEMCryptoResult OEMCrypto_Generic_Verify(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - const uint8_t* signature, - size_t signature_length) { - if (level1.library) { - if (!level1.OEMCrypto_Generic_Verify ) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return level1.OEMCrypto_Generic_Verify(session, in_buffer, buffer_length, - algorithm, signature, - signature_length); - } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Verify(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (!session_ctx || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Verify(): ERROR_NO_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (signature_length != SHA256_DIGEST_LENGTH) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (in_buffer == NULL || buffer_length == 0 || signature == NULL) { - LOGE("[OEMCrypto_Generic_Verify(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!session_ctx->Generic_Verify(in_buffer, buffer_length, algorithm, - signature, signature_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -}; // namespace wvoec_mock diff --git a/libwvdrmengine/level3/x86/libwvlevel3.a b/libwvdrmengine/level3/x86/libwvlevel3.a new file mode 100644 index 00000000..3ef2a30a Binary files /dev/null and b/libwvdrmengine/level3/x86/libwvlevel3.a differ diff --git a/libwvdrmengine/mediacrypto/test/Android.mk b/libwvdrmengine/mediacrypto/test/Android.mk index 67f52799..edca99f8 100644 --- a/libwvdrmengine/mediacrypto/test/Android.mk +++ b/libwvdrmengine/mediacrypto/test/Android.mk @@ -20,7 +20,8 @@ LOCAL_STATIC_LIBRARIES := \ libgmock \ libgmock_main \ libgtest \ - libl3crypto \ + libwvwrapper \ + libwvlevel3 \ libprotobuf-cpp-2.3.0-lite \ libwvdrmcryptoplugin \ diff --git a/libwvdrmengine/mediadrm/test/Android.mk b/libwvdrmengine/mediadrm/test/Android.mk index 59a74b5c..07b3dda5 100644 --- a/libwvdrmengine/mediadrm/test/Android.mk +++ b/libwvdrmengine/mediadrm/test/Android.mk @@ -21,7 +21,8 @@ LOCAL_STATIC_LIBRARIES := \ libgmock \ libgmock_main \ libgtest \ - libl3crypto \ + libwvwrapper \ + libwvlevel3 \ libprotobuf-cpp-2.3.0-lite \ libwvdrmdrmplugin \ diff --git a/libwvdrmengine/oemcrypto/Android.mk b/libwvdrmengine/oemcrypto/Android.mk new file mode 100644 index 00000000..0c4f26e3 --- /dev/null +++ b/libwvdrmengine/oemcrypto/Android.mk @@ -0,0 +1,34 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES := \ + vendor/widevine/libwvdrmengine/cdm/core/include \ + bionic \ + external/openssh \ + external/openssl/include \ + external/openssl/include/openssl \ + external/stlport/stlport \ + vendor/widevine/libwvdrmengine/oemcrypto/include \ + +LOCAL_SHARED_LIBRARIES := \ + libcrypto \ + libcutils \ + libdl \ + liblog \ + libstlport \ + libutils \ + libz \ + +LOCAL_STATIC_LIBRARIES := \ + libwvlevel3 \ + +LOCAL_MODULE := libwvwrapper + +# TODO(fredgc): remove mock reference when library is complete. +REL_MOCK_SOURCE := ../oemcrypto/mock/src + +LOCAL_SRC_FILES := \ + src/wrapper.cpp \ + +include $(BUILD_STATIC_LIBRARY) diff --git a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h index db08880d..f964987c 100644 --- a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h +++ b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h @@ -1024,8 +1024,6 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_INVALID_SESSION * OEMCrypto_ERROR_SHORT_BUFFER if the signature buffer is too small. - * OEMCrypto_ERROR_CLOSE_SESSION_FAILED illegal/unrecognized handle or the - * security engine is not properly initialized. * * Version: * This method changed in API version 6. diff --git a/libwvdrmengine/oemcrypto/include/level3.h b/libwvdrmengine/oemcrypto/include/level3.h new file mode 100644 index 00000000..0e2b4f43 --- /dev/null +++ b/libwvdrmengine/oemcrypto/include/level3.h @@ -0,0 +1,160 @@ +/********************************************************************* + * OEMCryptoCENC.h + * + * (c) Copyright 2013 Google, Inc. + * + * Reference APIs needed to support Widevine's crypto algorithms. + *********************************************************************/ + +#ifndef LEVEL3_OEMCRYPTO_H_ +#define LEVEL3_OEMCRYPTO_H_ + +#include +#include + +#include "OEMCryptoCENC.h" + +namespace wvoec_level3 { + +#define Level3_Initialize _lcc01 +#define Level3_Terminate _lcc02 +#define Level3_InstallKeybox _lcc03 +#define Level3_GetKeyData _lcc04 +#define Level3_IsKeyboxValid _lcc05 +#define Level3_GetRandom _lcc06 +#define Level3_GetDeviceID _lcc07 +#define Level3_WrapKeybox _lcc08 +#define Level3_OpenSession _lcc09 +#define Level3_CloseSession _lcc10 +#define Level3_DecryptCTR _lcc11 +#define Level3_GenerateDerivedKeys _lcc12 +#define Level3_GenerateSignature _lcc13 +#define Level3_GenerateNonce _lcc14 +#define Level3_LoadKeys _lcc15 +#define Level3_RefreshKeys _lcc16 +#define Level3_SelectKey _lcc17 +#define Level3_RewrapDeviceRSAKey _lcc18 +#define Level3_LoadDeviceRSAKey _lcc19 +#define Level3_GenerateRSASignature _lcc20 +#define Level3_DeriveKeysFromSessionKey _lcc21 +#define Level3_APIVersion _lcc22 +#define Level3_SecurityLevel _lcc23 +#define Level3_Generic_Encrypt _lcc24 +#define Level3_Generic_Decrypt _lcc25 +#define Level3_Generic_Sign _lcc26 +#define Level3_Generic_Verify _lcc27 + +extern "C" { + +OEMCryptoResult Level3_Initialize(void); +OEMCryptoResult Level3_Terminate(void); +OEMCryptoResult Level3_OpenSession(OEMCrypto_SESSION *session); +OEMCryptoResult Level3_CloseSession(OEMCrypto_SESSION session); +OEMCryptoResult Level3_GenerateDerivedKeys(OEMCrypto_SESSION session, + const uint8_t *mac_key_context, + uint32_t mac_key_context_length, + const uint8_t *enc_key_context, + uint32_t enc_key_context_length); +OEMCryptoResult Level3_GenerateNonce(OEMCrypto_SESSION session, + uint32_t* nonce); +OEMCryptoResult Level3_GenerateSignature(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + uint8_t* signature, + size_t* signature_length); +OEMCryptoResult Level3_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, + size_t num_keys, + const OEMCrypto_KeyObject* key_array); +OEMCryptoResult Level3_RefreshKeys(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + const uint8_t* signature, + size_t signature_length, + size_t num_keys, + const OEMCrypto_KeyRefreshObject* key_array); +OEMCryptoResult Level3_SelectKey(const OEMCrypto_SESSION session, + const uint8_t* key_id, + size_t key_id_length); +OEMCryptoResult Level3_DecryptCTR(OEMCrypto_SESSION session, + const uint8_t *data_addr, + size_t data_length, + bool is_encrypted, + const uint8_t *iv, + size_t block_offset, + const OEMCrypto_DestBufferDesc* out_buffer, + uint8_t subsample_flags); +OEMCryptoResult Level3_InstallKeybox(const uint8_t *keybox, + size_t keyBoxLength); +OEMCryptoResult Level3_IsKeyboxValid(void); +OEMCryptoResult Level3_GetDeviceID(uint8_t* deviceID, + size_t *idLength); +OEMCryptoResult Level3_GetKeyData(uint8_t* keyData, + size_t *keyDataLength); +OEMCryptoResult Level3_GetRandom(uint8_t* randomData, + size_t dataLength); +OEMCryptoResult Level3_WrapKeybox(const uint8_t *keybox, + size_t keyBoxLength, + uint8_t *wrappedKeybox, + size_t *wrappedKeyBoxLength, + const uint8_t *transportKey, + size_t transportKeyLength); +OEMCryptoResult Level3_RewrapDeviceRSAKey(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + const uint8_t* signature, + size_t signature_length, + const uint32_t *nonce, + const uint8_t* enc_rsa_key, + size_t enc_rsa_key_length, + const uint8_t* enc_rsa_key_iv, + uint8_t* wrapped_rsa_key, + size_t *wrapped_rsa_key_length); +OEMCryptoResult Level3_LoadDeviceRSAKey(OEMCrypto_SESSION session, + const uint8_t* wrapped_rsa_key, + size_t wrapped_rsa_key_length); +OEMCryptoResult Level3_GenerateRSASignature(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + uint8_t* signature, + size_t *signature_length); +OEMCryptoResult Level3_DeriveKeysFromSessionKey(OEMCrypto_SESSION session, + const uint8_t* enc_session_key, + size_t enc_session_key_length, + const uint8_t *mac_key_context, + size_t mac_key_context_length, + const uint8_t *enc_key_context, + size_t enc_key_context_length); +OEMCryptoResult Level3_Generic_Encrypt(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + const uint8_t* iv, + OEMCrypto_Algorithm algorithm, + uint8_t* out_buffer); +OEMCryptoResult Level3_Generic_Decrypt(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + const uint8_t* iv, + OEMCrypto_Algorithm algorithm, + uint8_t* out_buffer); +OEMCryptoResult Level3_Generic_Sign(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + OEMCrypto_Algorithm algorithm, + uint8_t* signature, + size_t* signature_length); +OEMCryptoResult Level3_Generic_Verify(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + OEMCrypto_Algorithm algorithm, + const uint8_t* signature, + size_t signature_length); +}; + +} +#endif // LEVEL3_OEMCRYPTO_H_ diff --git a/libwvdrmengine/oemcrypto/src/wrapper.cpp b/libwvdrmengine/oemcrypto/src/wrapper.cpp new file mode 100644 index 00000000..49fac8a2 --- /dev/null +++ b/libwvdrmengine/oemcrypto/src/wrapper.cpp @@ -0,0 +1,626 @@ +/******************************************************************************* + * + * Copyright 2013 Google Inc. All Rights Reserved. + * + * mock implementation of OEMCrypto APIs + * + ******************************************************************************/ + +#include "OEMCryptoCENC.h" + +#include +#include +#include +#include +#include + +#include "level3.h" +#include "log.h" + +using namespace wvoec_level3; + +namespace { +typedef OEMCryptoResult (*L1_Initialize_t)(void); +typedef OEMCryptoResult (*L1_Terminate_t)(void); +typedef OEMCryptoResult (*L1_OpenSession_t)(OEMCrypto_SESSION *session); +typedef OEMCryptoResult (*L1_CloseSession_t)(OEMCrypto_SESSION session); +typedef OEMCryptoResult (*L1_GenerateDerivedKeys_t)(OEMCrypto_SESSION session, + const uint8_t *mac_key_context, + uint32_t mac_key_context_length, + const uint8_t *enc_key_context, + uint32_t enc_key_context_length); +typedef OEMCryptoResult (*L1_GenerateNonce_t)(OEMCrypto_SESSION session, + uint32_t* nonce); +typedef OEMCryptoResult (*L1_GenerateSignature_t)(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + uint8_t* signature, + size_t* signature_length); +typedef OEMCryptoResult (*L1_LoadKeys_t)(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, + size_t num_keys, + const OEMCrypto_KeyObject* key_array); +typedef OEMCryptoResult (*L1_RefreshKeys_t)(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + const uint8_t* signature, + size_t signature_length, + size_t num_keys, + const OEMCrypto_KeyRefreshObject* key_array); +typedef OEMCryptoResult (*L1_SelectKey_t)(const OEMCrypto_SESSION session, + const uint8_t* key_id, + size_t key_id_length); +typedef OEMCryptoResult (*L1_DecryptCTR_t)(OEMCrypto_SESSION session, + const uint8_t *data_addr, + size_t data_length, + bool is_encrypted, + const uint8_t *iv, + size_t offset, + 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); +typedef OEMCryptoResult (*L1_GetDeviceID_t)(uint8_t* deviceID, + size_t *idLength); +typedef OEMCryptoResult (*L1_GetKeyData_t)(uint8_t* keyData, + size_t *keyDataLength); +typedef OEMCryptoResult (*L1_GetRandom_t)(uint8_t* randomData, + size_t dataLength); +typedef OEMCryptoResult (*L1_WrapKeybox_t)(const uint8_t *keybox, + size_t keyBoxLength, + uint8_t *wrappedKeybox, + size_t *wrappedKeyBoxLength, + const uint8_t *transportKey, + size_t transportKeyLength); +typedef OEMCryptoResult (*L1_RewrapDeviceRSAKey_t)(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + const uint8_t* signature, + size_t signature_length, + const uint32_t *nonce, + const uint8_t* enc_rsa_key, + size_t enc_rsa_key_length, + const uint8_t* enc_rsa_key_iv, + uint8_t* wrapped_rsa_key, + size_t *wrapped_rsa_key_length); +typedef OEMCryptoResult (*L1_LoadDeviceRSAKey_t)(OEMCrypto_SESSION session, + const uint8_t* wrapped_rsa_key, + size_t wrapped_rsa_key_length); +typedef OEMCryptoResult (*L1_GenerateRSASignature_t)(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + uint8_t* signature, + size_t *signature_length); +typedef OEMCryptoResult (*L1_DeriveKeysFromSessionKey_t)(OEMCrypto_SESSION session, + const uint8_t* enc_session_key, + size_t enc_session_key_length, + const uint8_t *mac_key_context, + size_t mac_key_context_length, + const uint8_t *enc_key_context, + size_t enc_key_context_length); +typedef OEMCryptoResult (*L1_Generic_Encrypt_t)(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + const uint8_t* iv, + OEMCrypto_Algorithm algorithm, + uint8_t* out_buffer); +typedef OEMCryptoResult (*L1_Generic_Decrypt_t)(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + const uint8_t* iv, + OEMCrypto_Algorithm algorithm, + uint8_t* out_buffer); + +typedef OEMCryptoResult (*L1_Generic_Sign_t)(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + OEMCrypto_Algorithm algorithm, + uint8_t* signature, + size_t* signature_length); + +typedef OEMCryptoResult (*L1_Generic_Verify_t)(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + OEMCrypto_Algorithm algorithm, + const uint8_t* signature, + size_t signature_length); +typedef uint8_t (*L1_APIVersion_t)(); +typedef const char* (*L1_SecurityLevel_t)(); + +struct FunctionPointers { + void* library; + L1_Initialize_t OEMCrypto_Initialize; + L1_Terminate_t OEMCrypto_Terminate; + L1_OpenSession_t OEMCrypto_OpenSession; + L1_CloseSession_t OEMCrypto_CloseSession; + L1_GenerateDerivedKeys_t OEMCrypto_GenerateDerivedKeys; + L1_GenerateNonce_t OEMCrypto_GenerateNonce; + L1_GenerateSignature_t OEMCrypto_GenerateSignature; + L1_LoadKeys_t OEMCrypto_LoadKeys; + L1_RefreshKeys_t OEMCrypto_RefreshKeys; + L1_SelectKey_t OEMCrypto_SelectKey; + L1_DecryptCTR_t OEMCrypto_DecryptCTR; + L1_InstallKeybox_t OEMCrypto_InstallKeybox; + L1_IsKeyboxValid_t OEMCrypto_IsKeyboxValid; + L1_GetDeviceID_t OEMCrypto_GetDeviceID; + L1_GetKeyData_t OEMCrypto_GetKeyData; + L1_GetRandom_t OEMCrypto_GetRandom; + L1_WrapKeybox_t OEMCrypto_WrapKeybox; + L1_RewrapDeviceRSAKey_t OEMCrypto_RewrapDeviceRSAKey; + L1_LoadDeviceRSAKey_t OEMCrypto_LoadDeviceRSAKey; + L1_GenerateRSASignature_t OEMCrypto_GenerateRSASignature; + L1_DeriveKeysFromSessionKey_t OEMCrypto_DeriveKeysFromSessionKey; + L1_APIVersion_t OEMCrypto_APIVersion; + L1_SecurityLevel_t OEMCrypto_SecurityLevel; + L1_Generic_Encrypt_t OEMCrypto_Generic_Encrypt; + L1_Generic_Decrypt_t OEMCrypto_Generic_Decrypt; + L1_Generic_Sign_t OEMCrypto_Generic_Sign; + L1_Generic_Verify_t OEMCrypto_Generic_Verify; +}; +static struct FunctionPointers level1; + +#define QUOTE_DEFINE(A) #A +#define QUOTE(A) QUOTE_DEFINE(A) +#define LOOKUP(Type, Name) \ + level1.Name = (Type)dlsym(level1.library, QUOTE(Name)); \ + if (!level1.Name) { \ + dll_valid = false; \ + } + +extern "C" +OEMCryptoResult OEMCrypto_Initialize(void) { + // LOGD("First, I will try to load Level 1"); + level1.library = dlopen("liboemcrypto.so", RTLD_NOW); + if (level1.library == NULL) { + LOGW("Could not load liboemcrypto.so. Falling Back to L3. %s", dlerror()); + return Level3_Initialize(); + } + bool dll_valid = true; + LOOKUP(L1_Initialize_t, OEMCrypto_Initialize); + LOOKUP(L1_Terminate_t, OEMCrypto_Terminate); + LOOKUP(L1_OpenSession_t, OEMCrypto_OpenSession); + LOOKUP(L1_CloseSession_t, OEMCrypto_CloseSession); + LOOKUP(L1_GenerateDerivedKeys_t, OEMCrypto_GenerateDerivedKeys); + LOOKUP(L1_GenerateNonce_t, OEMCrypto_GenerateNonce); + LOOKUP(L1_GenerateSignature_t, OEMCrypto_GenerateSignature); + LOOKUP(L1_LoadKeys_t, OEMCrypto_LoadKeys); + LOOKUP(L1_RefreshKeys_t, OEMCrypto_RefreshKeys); + LOOKUP(L1_SelectKey_t, OEMCrypto_SelectKey); + LOOKUP(L1_DecryptCTR_t, OEMCrypto_DecryptCTR); + LOOKUP(L1_InstallKeybox_t, OEMCrypto_InstallKeybox); + LOOKUP(L1_IsKeyboxValid_t, OEMCrypto_IsKeyboxValid); + LOOKUP(L1_GetDeviceID_t, OEMCrypto_GetDeviceID); + LOOKUP(L1_GetKeyData_t, OEMCrypto_GetKeyData); + LOOKUP(L1_GetRandom_t, OEMCrypto_GetRandom); + LOOKUP(L1_WrapKeybox_t, OEMCrypto_WrapKeybox); + + // TODO(fredgc): Move the validity check from here to below after we have + // an L1 library that matches current version. + if (!dll_valid) { + dlclose(level1.library); + level1.library = NULL; + LOGW("Could not load functions from liboemcrypto.so. Falling Back to L3."); + return Level3_Initialize(); + } + LOOKUP(L1_RewrapDeviceRSAKey_t, OEMCrypto_RewrapDeviceRSAKey); + LOOKUP(L1_LoadDeviceRSAKey_t, OEMCrypto_LoadDeviceRSAKey); + LOOKUP(L1_GenerateRSASignature_t, OEMCrypto_GenerateRSASignature); + LOOKUP(L1_DeriveKeysFromSessionKey_t, OEMCrypto_DeriveKeysFromSessionKey); + LOOKUP(L1_APIVersion_t, OEMCrypto_APIVersion); + LOOKUP(L1_SecurityLevel_t, OEMCrypto_SecurityLevel); + LOOKUP(L1_Generic_Decrypt_t, OEMCrypto_Generic_Decrypt); + LOOKUP(L1_Generic_Encrypt_t, OEMCrypto_Generic_Encrypt); + LOOKUP(L1_Generic_Sign_t, OEMCrypto_Generic_Sign); + LOOKUP(L1_Generic_Verify_t, OEMCrypto_Generic_Verify); + + // TODO(fredgc): Move the validity check from above to here after we have + // a current L1 library. + + OEMCryptoResult st = level1.OEMCrypto_Initialize(); + if (st != OEMCrypto_SUCCESS) { + LOGW("Could not initialize liboemcrypto.so. Falling Back to L3."); + dlclose(level1.library); + level1.library = NULL; + return Level3_Initialize(); + } + if (level1.OEMCrypto_APIVersion) { + uint32_t level1_version = level1.OEMCrypto_APIVersion(); + if (level1_version > oec_latest_version) { // Check for foward jump. + LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.", + level1_version, oec_latest_version); + dlclose(level1.library); + level1.library = NULL; + return Level3_Initialize(); + } + } + LOGD("OEMCrypto_Initialize Level 1 success. I will use level 1."); + return OEMCrypto_SUCCESS; +} + +extern "C" +OEMCryptoResult OEMCrypto_Terminate(void) { + if (level1.library) { + OEMCryptoResult st = level1.OEMCrypto_Terminate(); + dlclose(level1.library); + level1.library = NULL; + return st; + } + return Level3_Terminate(); +} + +extern "C" +OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) { + if (level1.library) { + return level1.OEMCrypto_OpenSession(session); + } + return Level3_OpenSession(session); +} + +extern "C" +OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session) { + if (level1.library) { + return level1.OEMCrypto_CloseSession(session); + } + return Level3_CloseSession(session); +} + +extern "C" +OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session, + uint32_t* nonce) { + if (level1.library) { + return level1.OEMCrypto_GenerateNonce(session, nonce); + } + return Level3_GenerateNonce(session, nonce); +} + +extern "C" +OEMCryptoResult OEMCrypto_GenerateDerivedKeys(OEMCrypto_SESSION session, + const uint8_t* mac_key_context, + uint32_t mac_key_context_length, + const uint8_t* enc_key_context, + uint32_t enc_key_context_length) { + if (level1.library) { + return level1.OEMCrypto_GenerateDerivedKeys(session, mac_key_context, + mac_key_context_length, + enc_key_context, + enc_key_context_length); + } + return Level3_GenerateDerivedKeys(session, mac_key_context, + mac_key_context_length, + enc_key_context, + enc_key_context_length); +} + +extern "C" +OEMCryptoResult OEMCrypto_GenerateSignature(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + uint8_t* signature, + size_t* signature_length) { + if (level1.library) { + return level1.OEMCrypto_GenerateSignature(session, message, message_length, + signature, signature_length); + } + return Level3_GenerateSignature(session, message, message_length, + signature, signature_length); +} + + +extern "C" +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, + 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, + num_keys, key_array); + } + return Level3_LoadKeys(session, message, message_length, signature, + signature_length, enc_mac_key_iv, enc_mac_key, + num_keys, key_array); +} + +extern "C" +OEMCryptoResult OEMCrypto_RefreshKeys(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + const uint8_t* signature, + size_t signature_length, + size_t num_keys, + const OEMCrypto_KeyRefreshObject* key_array) { + if (level1.library) { + return level1.OEMCrypto_RefreshKeys(session, message, message_length, signature, + signature_length, num_keys, key_array); + } + return Level3_RefreshKeys(session, message, message_length, signature, + signature_length, num_keys, key_array); +} + +extern "C" +OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session, + const uint8_t* key_id, + size_t key_id_length) { + if (level1.library) { + return level1.OEMCrypto_SelectKey(session, key_id, key_id_length); + } + return Level3_SelectKey(session, key_id, key_id_length); +} + +extern "C" +OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session, + const uint8_t* data_addr, + size_t data_length, + bool is_encrypted, + const uint8_t* iv, + size_t 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, + subsample_flags); + } + return Level3_DecryptCTR(session, data_addr, data_length, + is_encrypted, iv, offset, out_buffer, subsample_flags); +} + +extern "C" +OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox, + size_t keyBoxLength) { + if (level1.library) { + return level1.OEMCrypto_InstallKeybox(keybox, keyBoxLength); + } + return Level3_InstallKeybox(keybox, keyBoxLength); +} + +extern "C" +OEMCryptoResult OEMCrypto_IsKeyboxValid(void) { + if (level1.library) { + return level1.OEMCrypto_IsKeyboxValid(); + } + return Level3_IsKeyboxValid(); +} + +extern "C" +OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, + size_t* idLength) { + if (level1.library) { + return level1.OEMCrypto_GetDeviceID(deviceID, idLength); + } + return Level3_GetDeviceID(deviceID, idLength); +} + +extern "C" +OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData, + size_t* keyDataLength) { + if (level1.library) { + return level1.OEMCrypto_GetKeyData(keyData, keyDataLength); + } + return Level3_GetKeyData(keyData, keyDataLength); +} + +extern "C" +OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, size_t dataLength) { + if (level1.library) { + return level1.OEMCrypto_GetRandom(randomData, dataLength); + } + return Level3_GetRandom(randomData, dataLength); +} + +extern "C" +OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox, + size_t keyBoxLength, + uint8_t* wrappedKeybox, + size_t* wrappedKeyBoxLength, + const uint8_t* transportKey, + size_t transportKeyLength) { + if (level1.library) { + return level1.OEMCrypto_WrapKeybox(keybox, keyBoxLength, wrappedKeybox, + wrappedKeyBoxLength, transportKey, + transportKeyLength); + } + return Level3_WrapKeybox(keybox, keyBoxLength, wrappedKeybox, + wrappedKeyBoxLength, transportKey, + transportKeyLength); +} + +extern "C" +OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + const uint8_t* signature, + size_t signature_length, + const uint32_t* nonce, + const uint8_t* enc_rsa_key, + size_t enc_rsa_key_length, + const uint8_t* enc_rsa_key_iv, + uint8_t* wrapped_rsa_key, + size_t* wrapped_rsa_key_length) { + if (level1.library) { + if (!level1.OEMCrypto_RewrapDeviceRSAKey) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + return level1.OEMCrypto_RewrapDeviceRSAKey(session, message, message_length, + signature, signature_length, nonce, + enc_rsa_key, enc_rsa_key_length, + enc_rsa_key_iv, wrapped_rsa_key, + wrapped_rsa_key_length); + } + return Level3_RewrapDeviceRSAKey(session, message, message_length, + signature, signature_length, nonce, + enc_rsa_key, enc_rsa_key_length, + enc_rsa_key_iv, wrapped_rsa_key, + wrapped_rsa_key_length); +} + +extern "C" +OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, + const uint8_t* wrapped_rsa_key, + size_t wrapped_rsa_key_length) { + if (level1.library) { + if (!level1.OEMCrypto_LoadDeviceRSAKey) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + return level1.OEMCrypto_LoadDeviceRSAKey(session, wrapped_rsa_key, + wrapped_rsa_key_length); + } + return Level3_LoadDeviceRSAKey(session, wrapped_rsa_key, + wrapped_rsa_key_length); +} + +extern "C" +OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session, + const uint8_t* message, + size_t message_length, + uint8_t* signature, + size_t* signature_length) { + if (level1.library) { + if (!level1.OEMCrypto_GenerateRSASignature) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + return level1.OEMCrypto_GenerateRSASignature(session, message, message_length, + signature, signature_length); + } + return Level3_GenerateRSASignature(session, message, message_length, + signature, signature_length); +} + +extern "C" +OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(OEMCrypto_SESSION session, + const uint8_t* enc_session_key, + size_t enc_session_key_length, + const uint8_t* mac_key_context, + size_t mac_key_context_length, + const uint8_t* enc_key_context, + size_t enc_key_context_length) { + if (level1.library) { + if (!level1.OEMCrypto_DeriveKeysFromSessionKey) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + return level1.OEMCrypto_DeriveKeysFromSessionKey(session, enc_session_key, + enc_session_key_length, + mac_key_context, + mac_key_context_length, + enc_key_context, + enc_key_context_length); + } + return Level3_DeriveKeysFromSessionKey(session, enc_session_key, + enc_session_key_length, + mac_key_context, + mac_key_context_length, + enc_key_context, + enc_key_context_length); +} + +extern "C" +uint32_t OEMCrypto_APIVersion() { + if (level1.library) { + if (!level1.OEMCrypto_APIVersion) { + return 5; + } + return level1.OEMCrypto_APIVersion(); + } + return oec_latest_version; +} + +extern "C" +const char* OEMCrypto_SecurityLevel() { + if (level1.library) { + if (!level1.OEMCrypto_SecurityLevel) { + return "Unknown"; + } + return level1.OEMCrypto_SecurityLevel(); + } + return "L3"; +} + +extern "C" +OEMCryptoResult OEMCrypto_Generic_Encrypt(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + const uint8_t* iv, + OEMCrypto_Algorithm algorithm, + uint8_t* out_buffer) { + + if (level1.library) { + if (!level1.OEMCrypto_Generic_Encrypt) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + return level1.OEMCrypto_Generic_Encrypt(session, in_buffer, buffer_length, + iv, algorithm, out_buffer); + } + return Level3_Generic_Encrypt(session, in_buffer, buffer_length, + iv, algorithm, out_buffer); +} + +extern "C" +OEMCryptoResult OEMCrypto_Generic_Decrypt(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + const uint8_t* iv, + OEMCrypto_Algorithm algorithm, + uint8_t* out_buffer) { + if (level1.library) { + if (!level1.OEMCrypto_Generic_Decrypt) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + return level1.OEMCrypto_Generic_Decrypt(session, in_buffer, buffer_length, + iv, algorithm, out_buffer); + } + return Level3_Generic_Decrypt(session, in_buffer, buffer_length, + iv, algorithm, out_buffer); +} + +extern "C" +OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + OEMCrypto_Algorithm algorithm, + uint8_t* signature, + size_t* signature_length) { + if (level1.library) { + if (!level1.OEMCrypto_Generic_Sign) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + return level1.OEMCrypto_Generic_Sign(session, in_buffer, buffer_length, + algorithm, signature, + signature_length); + } + return Level3_Generic_Sign(session, in_buffer, buffer_length, + algorithm, signature, + signature_length); +} + +extern "C" +OEMCryptoResult OEMCrypto_Generic_Verify(OEMCrypto_SESSION session, + const uint8_t* in_buffer, + size_t buffer_length, + OEMCrypto_Algorithm algorithm, + const uint8_t* signature, + size_t signature_length) { + if (level1.library) { + if (!level1.OEMCrypto_Generic_Verify) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + return level1.OEMCrypto_Generic_Verify(session, in_buffer, buffer_length, + algorithm, signature, + signature_length); + } + return Level3_Generic_Verify(session, in_buffer, buffer_length, + algorithm, signature, + signature_length); +} + +}; // namespace wvoec_mock diff --git a/libwvdrmengine/oemcrypto/test/Android.mk b/libwvdrmengine/oemcrypto/test/Android.mk index 9ddd4cf7..bd378587 100644 --- a/libwvdrmengine/oemcrypto/test/Android.mk +++ b/libwvdrmengine/oemcrypto/test/Android.mk @@ -4,8 +4,8 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - oemcrypto_test.cpp \ - oemcrypto_keybox_test.cpp + oemcrypto_test.cpp \ + oemcrypto_keybox_test.cpp LOCAL_MODULE_TAGS := tests @@ -13,26 +13,28 @@ LOCAL_MODULE_TAGS := tests LOCAL_CFLAGS += -DCAN_INSTALL_KEYBOX LOCAL_C_INCLUDES += \ - bionic \ - external/gtest/include \ - external/openssl/include \ - external/stlport/stlport \ - $(LOCAL_PATH)/../include \ - $(LOCAL_PATH)/../mock/src \ + bionic \ + external/gtest/include \ + external/openssl/include \ + external/stlport/stlport \ + $(LOCAL_PATH)/../include \ + $(LOCAL_PATH)/../mock/src \ +# TODO(fredgc): fix order dependencies on libwvlevel3 and libwvwrapper. LOCAL_STATIC_LIBRARIES := \ - libgtest \ - libgtest_main \ - libl3crypto \ + libgtest \ + libgtest_main \ + libwvwrapper \ + libwvlevel3 \ LOCAL_SHARED_LIBRARIES := \ - libcrypto \ - libcutils \ - libdl \ - liblog \ - libstlport \ - libutils \ - libz \ + libcrypto \ + libcutils \ + libdl \ + liblog \ + libstlport \ + libutils \ + libz \ LOCAL_MODULE:=oemcrypto_test diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_keybox_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_keybox_test.cpp index e0db67bd..06d345d3 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_keybox_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_keybox_test.cpp @@ -92,11 +92,11 @@ class OEMCryptoKeyboxTest : public ::testing::Test { protected: virtual void SetUp() { - ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize()) - << "OEMCrypto_Initialize failed."; } - void install_keybox(wvoec_mock::WidevineKeybox& keybox) { + void install_keybox(wvoec_mock::WidevineKeybox& keybox, bool good) { + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize()) + << "OEMCrypto_Initialize failed."; OEMCryptoResult sts; uint8_t wrapped[sizeof(wvoec_mock::WidevineKeybox)]; size_t length = sizeof(wvoec_mock::WidevineKeybox); @@ -107,18 +107,23 @@ class OEMCryptoKeyboxTest : public ::testing::Test { NULL, 0); ASSERT_EQ(OEMCrypto_SUCCESS, sts); sts = OEMCrypto_InstallKeybox(wrapped, sizeof(keybox)); - ASSERT_EQ(OEMCrypto_SUCCESS, sts); + if( good ) { + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + } else { + // Can return error now, or return error on IsKeyboxValid. + } } virtual void TearDown() { - ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Terminate()) - << "OEMCrypto_Terminate failed."; + OEMCrypto_Terminate(); } public: }; TEST_F(OEMCryptoKeyboxTest, DefaultKeybox) { + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize()) + << "OEMCrypto_Initialize failed."; OEMCryptoResult sts; sts = OEMCrypto_IsKeyboxValid(); ASSERT_EQ(OEMCrypto_SUCCESS, sts); @@ -127,12 +132,12 @@ TEST_F(OEMCryptoKeyboxTest, DefaultKeybox) { TEST_F(OEMCryptoKeyboxTest, GoodKeybox) { wvoec_mock::WidevineKeybox keybox = kValidKeybox02; OEMCryptoResult sts; - install_keybox(keybox); + install_keybox(keybox, true); sts = OEMCrypto_IsKeyboxValid(); ASSERT_EQ(OEMCrypto_SUCCESS, sts); keybox = kValidKeybox03; - install_keybox(keybox); + install_keybox(keybox, true); sts = OEMCrypto_IsKeyboxValid(); ASSERT_EQ(OEMCrypto_SUCCESS, sts); } @@ -141,7 +146,7 @@ TEST_F(OEMCryptoKeyboxTest, BadCRCKeybox) { wvoec_mock::WidevineKeybox keybox = kValidKeybox02; keybox.crc_[1] = 42; OEMCryptoResult sts; - install_keybox(keybox); + install_keybox(keybox, false); sts = OEMCrypto_IsKeyboxValid(); ASSERT_EQ(OEMCrypto_ERROR_BAD_CRC, sts); } @@ -150,7 +155,7 @@ TEST_F(OEMCryptoKeyboxTest, BadMagicKeybox) { wvoec_mock::WidevineKeybox keybox = kValidKeybox02; keybox.magic_[1] = 42; OEMCryptoResult sts; - install_keybox(keybox); + install_keybox(keybox, false); sts = OEMCrypto_IsKeyboxValid(); ASSERT_EQ(OEMCrypto_ERROR_BAD_MAGIC, sts); } @@ -160,7 +165,7 @@ TEST_F(OEMCryptoKeyboxTest, BadDataKeybox) { wvoec_mock::WidevineKeybox keybox = kValidKeybox02; keybox.data_[1] = 42; OEMCryptoResult sts; - install_keybox(keybox); + install_keybox(keybox, false); sts = OEMCrypto_IsKeyboxValid(); ASSERT_EQ(OEMCrypto_ERROR_BAD_CRC, sts); } diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index f2e99e87..b43ea2ab 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -1682,9 +1682,16 @@ TEST_F(OEMCryptoClientTest, GenerateDerivedKeys) { testTearDown(); } +// Define CAN_INSTALL_KEYBOX if you are compiling with the reference +// implementation of OEMCrypto, or if your version of OEMCrypto supports +// OEMCrypto_InstallKeybox and OEwith a clear keybox. +// The Below tests are based on a specific keybox which is installed for testing. +#if defined(CAN_INSTALL_KEYBOX) + TEST_F(OEMCryptoClientTest, GenerateSignature) { - Session& s = createSession("ONE"); testSetUp(); + InstallKeybox(kDefaultKeybox); + Session& s = createSession("ONE"); s.open(); s.GenerateDerivedKeys(); @@ -1715,19 +1722,12 @@ TEST_F(OEMCryptoClientTest, GenerateSignature) { ASSERT_EQ(0, memcmp(&expected_signature[0], signature, expected_signature.size())); - s.close(); ASSERT_TRUE(s.successStatus()); ASSERT_FALSE(s.isOpen()); testTearDown(); } -// Define CAN_INSTALL_KEYBOX if you are compiling with the reference -// implementation of OEMCrypto, or if your version of OEMCrypto supports -// OEMCrypto_InstallKeybox and OEwith a clear keybox. -// The Below tests are based on a specific keybox which is installed for testing. -#if defined(CAN_INSTALL_KEYBOX) - TEST_F(OEMCryptoClientTest, LoadKeyNoNonce) { testSetUp(); InstallKeybox(kDefaultKeybox);