diff --git a/CMakeLists.txt b/CMakeLists.txt index a34605b7ed..8a7635d03a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,24 @@ if (BUILD_OPENSSL AND OE_TRUSTZONE) message(FATAL_ERROR "BUILD_OPENSSL is not supported on ARM yet.") endif () +set(DEFAULT_TEST_ENCLAVE_CRYPTO_LIB + "mbedtls" + CACHE STRING "Default crypto library used by the enclaves.") +string(TOLOWER "${DEFAULT_TEST_ENCLAVE_CRYPTO_LIB}" + DEFAULT_TEST_ENCLAVE_CRYPTO_LIB_LOWER) +if ((NOT DEFAULT_TEST_ENCLAVE_CRYPTO_LIB_LOWER STREQUAL "mbedtls") + AND (NOT DEFAULT_TEST_ENCLAVE_CRYPTO_LIB_LOWER STREQUAL "openssl")) + message( + FATAL_ERROR "Unsupported crypto library: ${DEFAULT_ENCLAVE_CRYPTO_LIB}") +endif () +if ((DEFAULT_TEST_ENCLAVE_CRYPTO_LIB_LOWER STREQUAL "openssl") + AND (NOT BUILD_OPENSSL)) + message( + FATAL_ERROR + "Cannot set OpenSSL as the default crypto library when BUILD_OPENSSL is OFF" + ) +endif () + if (WIN32) # NOTE: On Windows we have found that we must use Git Bash, not the # Bash from the Windows Subsystem for Linux. Hence this is diff --git a/cmake/add_enclave.cmake b/cmake/add_enclave.cmake index 112db39940..7a45521031 100644 --- a/cmake/add_enclave.cmake +++ b/cmake/add_enclave.cmake @@ -10,6 +10,7 @@ # [] # [CXX] # [ADD_LVI_MITIGATION] +# [] # # [] # []) @@ -54,7 +55,8 @@ macro (add_enclave) KEY SIGNING_ENGINE ENGINE_LOAD_PATH - ENGINE_KEY_ID) + ENGINE_KEY_ID + CRYPTO_LIB) set(multiValueArgs SOURCES) cmake_parse_arguments(ENCLAVE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -75,6 +77,8 @@ macro (add_enclave) ${ENCLAVE_ENGINE_LOAD_PATH} ENGINE_KEY_ID ${ENCLAVE_ENGINE_KEY_ID} + CRYPTO_LIB + ${ENCLAVE_CRYPTO_LIB} ADD_LVI_MITIGATION ${ENCLAVE_ADD_LVI_MITIGATION} SOURCES @@ -89,6 +93,8 @@ macro (add_enclave) ${ENCLAVE_UUID} KEY ${ENCLAVE_KEY} + CRYPTO_LIB + ${ENCLAVE_CRYPTO_LIB} SOURCES ${ENCLAVE_SOURCES}) endif () @@ -156,6 +162,7 @@ function (add_enclave_sgx) SIGNING_ENGINE ENGINE_LOAD_PATH ENGINE_KEY_ID + CRYPTO_LIB CXX ADD_LVI_MITIGATION) set(multiValueArgs SOURCES) @@ -182,6 +189,24 @@ function (add_enclave_sgx) endif () enclave_link_libraries(${ENCLAVE_TARGET} oeenclave) + + # If the CRYPTO_LIB argument to add_enclave() is not set, the following + # logic determines the default crypto library based on the value of the + # DEFAULT_TEST_ENCLAVE_CRYPTO_LIB global variable (e.g., either "MbedTLS" or "OpenSSL"). + # If the CRYPTO_LIB argument is set, it overrides the DEFAULT_TEST_ENCLAVE_CRYPTO_LIB. + if (NOT ENCLAVE_CRYPTO_LIB) + set(ENCLAVE_CRYPTO_LIB ${DEFAULT_TEST_ENCLAVE_CRYPTO_LIB}) + endif () + + string(TOLOWER "${ENCLAVE_CRYPTO_LIB}" ENCLAVE_CRYPTO_LIB_LOWER) + if (ENCLAVE_CRYPTO_LIB_LOWER STREQUAL "mbedtls") + enclave_link_libraries(${ENCLAVE_TARGET} oecryptombedtls) + elseif (ENCLAVE_CRYPTO_LIB_LOWER STREQUAL "openssl") + enclave_link_libraries(${ENCLAVE_TARGET} oecryptoopenssl) + else () + message(FATAL_ERROR "Unsupported crypto library ${ENCLAVE_CRYPTO_LIB}.") + endif () + if (ENCLAVE_CXX) enclave_link_libraries(${ENCLAVE_TARGET} oelibcxx) endif () @@ -269,7 +294,7 @@ function (add_enclave_sgx) endfunction () macro (add_enclave_optee) - set(oneValueArgs TARGET UUID KEY CXX) + set(oneValueArgs TARGET UUID KEY CRYPTO_LIB CXX) set(multiValueArgs SOURCES) cmake_parse_arguments(ENCLAVE "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -318,7 +343,27 @@ macro (add_enclave_optee) add_dependencies(${ENCLAVE_TARGET} ${ENCLAVE_TARGET}.ld) target_include_directories(${ENCLAVE_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/optee) + target_link_libraries(${ENCLAVE_TARGET} oeenclave) + + # If the CRYPTO_LIB argument to add_enclave() is not set, the following + # logic determines the default crypto library based on the value of the + # DEFAULT_TEST_ENCLAVE_CRYPTO_LIB global variable (e.g., either "MbedTLS" or "OpenSSL"). + # If the CRYPTO_LIB argument is set, it overrides the DEFAULT_TEST_ENCLAVE_CRYPTO_LIB. + # Note that the OpenSSL-based crypto library is currently not supported on OP-TEE. + if (NOT ENCLAVE_CRYPTO_LIB) + set(ENCLAVE_CRYPTO_LIB ${DEFAULT_TEST_ENCLAVE_CRYPTO_LIB}) + endif () + + string(TOLOWER "${ENCLAVE_CRYPTO_LIB}" ENCLAVE_CRYPTO_LIB_LOWER) + if (ENCLAVE_CRYPTO_LIB_LOWER STREQUAL "mbedtls") + enclave_link_libraries(${ENCLAVE_TARGET} oecryptombedtls) + elseif (ENCLAVE_CRYPTO_LIB_LOWER STREQUAL "openssl") + enclave_link_libraries(${ENCLAVE_TARGET} oecryptoopenssl) + else () + message(FATAL_ERROR "Unsupported crypto library ${ENCLAVE_CRYPTO_LIB}.") + endif () + if (ENCLAVE_CXX) target_link_libraries(${ENCLAVE_TARGET} oelibcxx) endif () diff --git a/host/crypto/openssl/asn1.c b/common/crypto/openssl/asn1.c similarity index 99% rename from host/crypto/openssl/asn1.c rename to common/crypto/openssl/asn1.c index 20d14b40e6..83812601ae 100644 --- a/host/crypto/openssl/asn1.c +++ b/common/crypto/openssl/asn1.c @@ -1,7 +1,7 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. -#include "../common/asn1.h" +#include "../../asn1.h" #include #include #include diff --git a/host/crypto/openssl/asn1.h b/common/crypto/openssl/asn1.h similarity index 85% rename from host/crypto/openssl/asn1.h rename to common/crypto/openssl/asn1.h index 182b86b4df..9b7cefda98 100644 --- a/host/crypto/openssl/asn1.h +++ b/common/crypto/openssl/asn1.h @@ -1,8 +1,8 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. -#ifndef _OE_HOST_CRYPTO_ASN1_OPENSSL_H -#define _OE_HOST_CRYPTO_ASN1_OPENSSL_H +#ifndef _OE_COMMON_CRYPTO_OPENSSL_ASN1_H +#define _OE_COMMON_CRYPTO_OPENSSL_ASN1_H #include #include @@ -25,4 +25,4 @@ oe_result_t oe_asn1_string_to_date(const char* str, oe_datetime_t* date); */ oe_result_t oe_asn1_time_to_date(const ASN1_TIME* time, oe_datetime_t* date); -#endif /* _OE_HOST_CRYPTO_ASN1_OPENSSL_H */ +#endif /* _OE_COMMON_CRYPTO_OPENSSL_ASN1_H */ diff --git a/host/crypto/openssl/cert.c b/common/crypto/openssl/cert.c similarity index 98% rename from host/crypto/openssl/cert.c rename to common/crypto/openssl/cert.c index 90e79160e4..991eb377bb 100644 --- a/host/crypto/openssl/cert.c +++ b/common/crypto/openssl/cert.c @@ -5,6 +5,9 @@ #include #include #include +#if !defined(OE_BUILD_ENCLAVE) +#include +#endif #include #include #include @@ -14,15 +17,12 @@ #include #include #include -#include -#include #include -#include "../../../common/oe_host_stdlib.h" -#include "../magic.h" +#include "../../oe_host_stdlib.h" #include "asn1.h" #include "crl.h" #include "ec.h" -#include "init.h" +#include "magic.h" #include "rsa.h" /* @@ -498,8 +498,10 @@ oe_result_t oe_cert_read_pem( if (strnlen((const char*)pem_data, pem_size) != pem_size - 1) OE_RAISE(OE_INVALID_PARAMETER); +#if !defined(OE_BUILD_ENCLAVE) /* Initialize OpenSSL (if not already initialized) */ - oe_initialize_openssl(); + oe_crypto_initialize(); +#endif /* Create a BIO object for reading the PEM data */ if (!(bio = BIO_new_mem_buf(pem_data, (int)pem_size))) @@ -543,8 +545,10 @@ oe_result_t oe_cert_read_der( if (!der_data || !der_size || der_size > OE_INT_MAX || !cert) OE_RAISE(OE_INVALID_PARAMETER); +#if !defined(OE_BUILD_ENCLAVE) /* Initialize OpenSSL (if not already initialized) */ - oe_initialize_openssl(); + oe_crypto_initialize(); +#endif p = (unsigned char*)der_data; @@ -651,8 +655,10 @@ oe_result_t oe_cert_chain_read_pem( tmp_pem_data[pem_size] = '\0'; } +#if !defined(OE_BUILD_ENCLAVE) /* Initialize OpenSSL (if not already initialized) */ - oe_initialize_openssl(); + oe_crypto_initialize(); +#endif /* Read the certificate chain into memory */ if (!(sk = _read_cert_chain((const char*)tmp_pem_data))) @@ -721,8 +727,10 @@ oe_result_t oe_cert_verify( OE_RAISE_MSG(OE_INVALID_PARAMETER, "Invalid chain parameter", NULL); } +#if !defined(OE_BUILD_ENCLAVE) /* Initialize OpenSSL (if not already initialized) */ - oe_initialize_openssl(); + oe_crypto_initialize(); +#endif /* Verify the certificate */ OE_CHECK(_verify_cert( diff --git a/common/crypto/openssl/cmac.c b/common/crypto/openssl/cmac.c new file mode 100644 index 0000000000..6bdcdc53ac --- /dev/null +++ b/common/crypto/openssl/cmac.c @@ -0,0 +1,46 @@ +// Copyright (c) Open Enclave SDK contributors. +// Licensed under the MIT License. + +#include +#include + +#include +#include +#include + +oe_result_t oe_aes_cmac_sign( + const uint8_t* key, + size_t key_size, + const uint8_t* message, + size_t message_length, + oe_aes_cmac_t* aes_cmac) +{ + oe_result_t result = OE_UNEXPECTED; + size_t key_size_bits = key_size * 8; + size_t final_size = sizeof(oe_aes_cmac_t); + CMAC_CTX* ctx = NULL; + + if (aes_cmac == NULL) + OE_RAISE(OE_INVALID_PARAMETER); + + if (key_size_bits != 128) + OE_RAISE(OE_UNSUPPORTED); + + oe_secure_zero_fill(aes_cmac->impl, sizeof(*aes_cmac)); + + ctx = CMAC_CTX_new(); + if (ctx == NULL) + OE_RAISE(OE_CRYPTO_ERROR); + + CMAC_Init(ctx, key, key_size, EVP_aes_128_cbc(), NULL); + CMAC_Update(ctx, message, message_length); + CMAC_Final(ctx, (unsigned char*)aes_cmac->impl, &final_size); + + result = OE_OK; + +done: + if (ctx) + CMAC_CTX_free(ctx); + + return result; +} diff --git a/host/crypto/openssl/crl.c b/common/crypto/openssl/crl.c similarity index 99% rename from host/crypto/openssl/crl.c rename to common/crypto/openssl/crl.c index 72947c816e..9f68979b2b 100644 --- a/host/crypto/openssl/crl.c +++ b/common/crypto/openssl/crl.c @@ -14,9 +14,9 @@ #include #include -#include "../magic.h" #include "asn1.h" #include "crl.h" +#include "magic.h" #if OPENSSL_VERSION_NUMBER < 0x10100000L /* Needed for compatibility with ssl1.1 */ diff --git a/host/crypto/openssl/crl.h b/common/crypto/openssl/crl.h similarity index 68% rename from host/crypto/openssl/crl.h rename to common/crypto/openssl/crl.h index 7823e260db..9e9a0bdafd 100644 --- a/host/crypto/openssl/crl.h +++ b/common/crypto/openssl/crl.h @@ -1,8 +1,8 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. -#ifndef _OE_HOST_CRYPTO_CRL_H -#define _OE_HOST_CRYPTO_CRL_H +#ifndef _OE_COMMON_CRYPTO_OPENSSL_CRL_H +#define _OE_COMMON_CRYPTO_OPENSSL_CRL_H #include #include @@ -15,4 +15,4 @@ typedef struct _crl bool crl_is_valid(const crl_t* impl); -#endif /* _OE_HOST_CRYPTO_CRL_H */ +#endif /* _OE_COMMON_CRYPTO_OPENSSL_CRL_H */ diff --git a/host/crypto/openssl/ec.c b/common/crypto/openssl/ec.c similarity index 93% rename from host/crypto/openssl/ec.c rename to common/crypto/openssl/ec.c index ef3bcae09b..74d0e716ff 100644 --- a/host/crypto/openssl/ec.c +++ b/common/crypto/openssl/ec.c @@ -1,15 +1,17 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. +#if !defined(OE_BUILD_ENCLAVE) +#include +#endif #include #include #include #include -#include "../magic.h" #include "ec.h" -#include "init.h" #include "key.h" +#include "magic.h" #if OPENSSL_VERSION_NUMBER < 0x10100000L /* Needed for compatibility with ssl1.1 */ @@ -73,8 +75,8 @@ static oe_result_t _public_key_equal( *equal = false; /* Reject bad parameters */ - if (!oe_public_key_is_valid(public_key1, OE_RSA_PUBLIC_KEY_MAGIC) || - !oe_public_key_is_valid(public_key2, OE_RSA_PUBLIC_KEY_MAGIC) || !equal) + if (!oe_public_key_is_valid(public_key1, OE_EC_PUBLIC_KEY_MAGIC) || + !oe_public_key_is_valid(public_key2, OE_EC_PUBLIC_KEY_MAGIC) || !equal) OE_RAISE(OE_INVALID_PARAMETER); { @@ -112,13 +114,13 @@ static oe_result_t _public_key_equal( void oe_ec_public_key_init(oe_ec_public_key_t* public_key, EVP_PKEY* pkey) { oe_public_key_init( - (oe_public_key_t*)public_key, pkey, OE_RSA_PUBLIC_KEY_MAGIC); + (oe_public_key_t*)public_key, pkey, OE_EC_PUBLIC_KEY_MAGIC); } void oe_ec_private_key_init(oe_ec_private_key_t* private_key, EVP_PKEY* pkey) { oe_private_key_init( - (oe_private_key_t*)private_key, pkey, OE_RSA_PRIVATE_KEY_MAGIC); + (oe_private_key_t*)private_key, pkey, OE_EC_PRIVATE_KEY_MAGIC); } oe_result_t oe_ec_private_key_read_pem( @@ -131,7 +133,7 @@ oe_result_t oe_ec_private_key_read_pem( pem_size, (oe_private_key_t*)private_key, EVP_PKEY_EC, - OE_RSA_PRIVATE_KEY_MAGIC); + OE_EC_PRIVATE_KEY_MAGIC); } oe_result_t oe_ec_private_key_write_pem( @@ -144,7 +146,7 @@ oe_result_t oe_ec_private_key_write_pem( pem_data, pem_size, _private_key_write_pem_callback, - OE_RSA_PRIVATE_KEY_MAGIC); + OE_EC_PRIVATE_KEY_MAGIC); } oe_result_t oe_ec_public_key_read_pem( @@ -157,7 +159,7 @@ oe_result_t oe_ec_public_key_read_pem( pem_size, (oe_public_key_t*)public_key, EVP_PKEY_EC, - OE_RSA_PUBLIC_KEY_MAGIC); + OE_EC_PUBLIC_KEY_MAGIC); } oe_result_t oe_ec_public_key_write_pem( @@ -169,19 +171,19 @@ oe_result_t oe_ec_public_key_write_pem( (const oe_public_key_t*)public_key, pem_data, pem_size, - OE_RSA_PUBLIC_KEY_MAGIC); + OE_EC_PUBLIC_KEY_MAGIC); } oe_result_t oe_ec_private_key_free(oe_ec_private_key_t* private_key) { return oe_private_key_free( - (oe_private_key_t*)private_key, OE_RSA_PRIVATE_KEY_MAGIC); + (oe_private_key_t*)private_key, OE_EC_PRIVATE_KEY_MAGIC); } oe_result_t oe_ec_public_key_free(oe_ec_public_key_t* public_key) { return oe_public_key_free( - (oe_public_key_t*)public_key, OE_RSA_PUBLIC_KEY_MAGIC); + (oe_public_key_t*)public_key, OE_EC_PUBLIC_KEY_MAGIC); } oe_result_t oe_ec_private_key_sign( @@ -199,7 +201,7 @@ oe_result_t oe_ec_private_key_sign( hash_size, signature, signature_size, - OE_RSA_PRIVATE_KEY_MAGIC); + OE_EC_PRIVATE_KEY_MAGIC); } oe_result_t oe_ec_public_key_verify( @@ -217,7 +219,7 @@ oe_result_t oe_ec_public_key_verify( hash_size, signature, signature_size, - OE_RSA_PUBLIC_KEY_MAGIC); + OE_EC_PUBLIC_KEY_MAGIC); } oe_result_t oe_ec_generate_key_pair_from_private( @@ -241,8 +243,10 @@ oe_result_t oe_ec_generate_key_pair_from_private( OE_RAISE(OE_INVALID_PARAMETER); } +#if !defined(OE_BUILD_ENCLAVE) /* Initialize OpenSSL. */ - oe_initialize_openssl(); + oe_crypto_initialize(); +#endif /* Initialize the EC key. */ key = EC_KEY_new_by_curve_name(_get_nid(curve)); @@ -347,8 +351,10 @@ oe_result_t oe_ec_public_key_from_coordinates( if (public_key) oe_secure_zero_fill(public_key, sizeof(oe_ec_public_key_t)); +#if !defined(OE_BUILD_ENCLAVE) /* Initialize OpenSSL */ - oe_initialize_openssl(); + oe_crypto_initialize(); +#endif /* Reject invalid parameters */ if (!public_key || !x_data || !x_size || x_size > OE_INT_MAX || !y_data || @@ -405,7 +411,7 @@ oe_result_t oe_ec_public_key_from_coordinates( /* Initialize the public key */ { - oe_public_key_init(impl, pkey, OE_RSA_PUBLIC_KEY_MAGIC); + oe_public_key_init(impl, pkey, OE_EC_PUBLIC_KEY_MAGIC); pkey = NULL; } } diff --git a/host/crypto/openssl/ec.h b/common/crypto/openssl/ec.h similarity index 74% rename from host/crypto/openssl/ec.h rename to common/crypto/openssl/ec.h index 989d452fb9..c377d7b229 100644 --- a/host/crypto/openssl/ec.h +++ b/common/crypto/openssl/ec.h @@ -1,8 +1,8 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. -#ifndef _OE_HOST_CRYPTO_EC_H -#define _OE_HOST_CRYPTO_EC_H +#ifndef _OE_COMMON_CRYPTO_OPENSSL_EC_H +#define _OE_COMMON_CRYPTO_OPENSSL_EC_H #include #include @@ -12,4 +12,4 @@ void oe_ec_public_key_init(oe_ec_public_key_t* public_key, EVP_PKEY* pkey); void oe_ec_private_key_init(oe_ec_private_key_t* private_key, EVP_PKEY* pkey); -#endif /* _OE_HOST_CRYPTO_EC_H */ +#endif /* _OE_COMMON_CRYPTO_OPENSSL_EC_H */ diff --git a/host/crypto/openssl/hmac.c b/common/crypto/openssl/hmac.c similarity index 100% rename from host/crypto/openssl/hmac.c rename to common/crypto/openssl/hmac.c diff --git a/host/crypto/openssl/key.c b/common/crypto/openssl/key.c similarity index 97% rename from host/crypto/openssl/key.c rename to common/crypto/openssl/key.c index 0ae6784f9b..c3642643e2 100644 --- a/host/crypto/openssl/key.c +++ b/common/crypto/openssl/key.c @@ -1,7 +1,9 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. -#include "key.h" +#if !defined(OE_BUILD_ENCLAVE) +#include +#endif #include #include #include @@ -10,7 +12,9 @@ #include #include #include -#include "init.h" + +#include "key.h" +#include "magic.h" bool oe_private_key_is_valid(const oe_private_key_t* impl, uint64_t magic) { @@ -155,8 +159,10 @@ oe_result_t oe_private_key_read_pem( if (strnlen((const char*)pem_data, pem_size) != pem_size - 1) OE_RAISE(OE_INVALID_PARAMETER); +#if !defined(OE_BUILD_ENCLAVE) /* Initialize OpenSSL */ - oe_initialize_openssl(); + oe_crypto_initialize(); +#endif /* Create a BIO object for reading the PEM data */ if (!(bio = BIO_new_mem_buf(pem_data, (int)pem_size))) @@ -212,8 +218,10 @@ oe_result_t oe_public_key_read_pem( if (strnlen((const char*)pem_data, pem_size) != pem_size - 1) OE_RAISE(OE_INVALID_PARAMETER); +#if !defined(OE_BUILD_ENCLAVE) /* Initialize OpenSSL */ - oe_initialize_openssl(); + oe_crypto_initialize(); +#endif /* Create a BIO object for reading the PEM data */ if (!(bio = BIO_new_mem_buf(pem_data, (int)pem_size))) @@ -449,8 +457,10 @@ oe_result_t oe_private_key_sign( if (!signature && *signature_size != 0) OE_RAISE(OE_INVALID_PARAMETER); +#if !defined(OE_BUILD_ENCLAVE) /* Initialize OpenSSL */ - oe_initialize_openssl(); + oe_crypto_initialize(); +#endif /* Create signing context */ if (!(ctx = EVP_PKEY_CTX_new(impl->pkey, NULL))) @@ -525,8 +535,10 @@ oe_result_t oe_public_key_verify( if (hash_type > hash_size) OE_RAISE(OE_INVALID_PARAMETER); +#if !defined(OE_BUILD_ENCLAVE) /* Initialize OpenSSL */ - oe_initialize_openssl(); + oe_crypto_initialize(); +#endif /* Create signing context */ if (!(ctx = EVP_PKEY_CTX_new(impl->pkey, NULL))) diff --git a/host/crypto/openssl/key.h b/common/crypto/openssl/key.h similarity index 94% rename from host/crypto/openssl/key.h rename to common/crypto/openssl/key.h index a0e72d02ce..a9e5825125 100644 --- a/host/crypto/openssl/key.h +++ b/common/crypto/openssl/key.h @@ -1,8 +1,8 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. -#ifndef _HOST_KEY_H -#define _HOST_KEY_H +#ifndef _OE_COMMON_CRYPTO_OPENSSL_KEY_H +#define _OE_COMMON_CRYPTO_OPENSSL_KEY_H #include #include @@ -96,4 +96,4 @@ oe_result_t oe_public_key_verify( size_t signature_size, uint64_t magic); -#endif /* _HOST_KEY_H */ +#endif /* _OE_COMMON_CRYPTO_OPENSSL_KEY_H */ diff --git a/common/crypto/openssl/magic.h b/common/crypto/openssl/magic.h new file mode 100644 index 0000000000..b95e9ae31d --- /dev/null +++ b/common/crypto/openssl/magic.h @@ -0,0 +1,27 @@ +// Copyright (c) Open Enclave SDK contributors. +// Licensed under the MIT License. + +#ifndef _OE_COMMON_CRYPTO_OPENSSL_MAGIC_H +#define _OE_COMMON_CRYPTO_OPENSSL_MAGIC_H + +#if !defined(OE_BUILD_ENCLAVE) +/* oe_crypto magic numbers for host OpenSSL implementation */ +#define OE_CERT_MAGIC 0xbc8e184285de4d2a +#define OE_CERT_CHAIN_MAGIC 0xa5ddf70fb28f4480 +#define OE_CRL_MAGIC 0xe8c993b1cca24906 +#define OE_EC_PRIVATE_KEY_MAGIC 0x19a751419ae04bbc +#define OE_EC_PUBLIC_KEY_MAGIC 0xb1d39580c1f14c02 +#define OE_RSA_PRIVATE_KEY_MAGIC 0x7bf635929a714b2c +#define OE_RSA_PUBLIC_KEY_MAGIC 0x8f8f72170025426d +#else +/* oe_crypto magic numbers for enclave OpenSSL implementation */ +#define OE_CERT_MAGIC 0xa7a55f4322919317 +#define OE_CERT_CHAIN_MAGIC 0xa87e5d8e25671870 +#define OE_CRL_MAGIC 0x8f062e782b5760b2 +#define OE_EC_PRIVATE_KEY_MAGIC 0x9ffae0517397b76c +#define OE_EC_PUBLIC_KEY_MAGIC 0xb8e1d57e9be31ed7 +#define OE_RSA_PRIVATE_KEY_MAGIC 0xba24987b29769828 +#define OE_RSA_PUBLIC_KEY_MAGIC 0x92f1fdf6c81b4aaa +#endif + +#endif /* _OE_COMMON_CRYPTO_OPENSSL_MAGIC_H */ diff --git a/common/crypto/openssl/rsa.c b/common/crypto/openssl/rsa.c new file mode 100644 index 0000000000..7ae94dc442 --- /dev/null +++ b/common/crypto/openssl/rsa.c @@ -0,0 +1,335 @@ +// Copyright (c) Open Enclave SDK contributors. +// Licensed under the MIT License. + +#include +#include +#include +#include + +#include "key.h" +#include "magic.h" +#include "rsa.h" + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +/* Needed for compatibility with ssl1.1 */ + +static void RSA_get0_key( + const RSA* r, + const BIGNUM** n, + const BIGNUM** e, + const BIGNUM** d) +{ + if (n != NULL) + *n = r->n; + if (e != NULL) + *e = r->e; + if (d != NULL) + *d = r->d; +} + +#endif + +OE_STATIC_ASSERT(sizeof(oe_public_key_t) <= sizeof(oe_rsa_public_key_t)); +OE_STATIC_ASSERT(sizeof(oe_private_key_t) <= sizeof(oe_rsa_private_key_t)); + +static oe_result_t _private_key_write_pem_callback(BIO* bio, EVP_PKEY* pkey) +{ + oe_result_t result = OE_UNEXPECTED; + RSA* rsa = NULL; + + if (!(rsa = EVP_PKEY_get1_RSA(pkey))) + OE_RAISE(OE_CRYPTO_ERROR); + + if (!PEM_write_bio_RSAPrivateKey(bio, rsa, NULL, NULL, 0, 0, NULL)) + OE_RAISE(OE_CRYPTO_ERROR); + + result = OE_OK; + +done: + + if (rsa) + RSA_free(rsa); + + return result; +} + +static oe_result_t _get_public_key_get_modulus_or_exponent( + const oe_public_key_t* public_key, + uint8_t* buffer, + size_t* buffer_size, + bool get_modulus) +{ + oe_result_t result = OE_UNEXPECTED; + size_t required_size; + const BIGNUM* bn; + RSA* rsa = NULL; + + /* Check for invalid parameters */ + if (!public_key || !buffer_size) + OE_RAISE(OE_INVALID_PARAMETER); + + /* If buffer is null, then buffer_size must be zero */ + if (!buffer && *buffer_size != 0) + OE_RAISE(OE_INVALID_PARAMETER); + + /* Get RSA key */ + if (!(rsa = EVP_PKEY_get1_RSA(public_key->pkey))) + OE_RAISE(OE_CRYPTO_ERROR); + + /* Select modulus or exponent */ + const BIGNUM* e; + const BIGNUM* n; + RSA_get0_key(rsa, &n, &e, NULL); + bn = get_modulus ? n : e; + + /* Determine the required size in bytes */ + { + int n = BN_num_bytes(bn); + + if (n <= 0) + OE_RAISE(OE_CRYPTO_ERROR); + + /* Add one leading byte for the leading zero byte */ + required_size = (size_t)n; + } + + /* If buffer is null or not big enough */ + if (!buffer || (*buffer_size < required_size)) + { + *buffer_size = required_size; + + if (buffer) + OE_RAISE(OE_BUFFER_TOO_SMALL); + /* If buffer is null, this call is intented to get the correct + * buffer_size so no need to trace OE_BUFFER_TOO_SMALL */ + else + OE_RAISE_NO_TRACE(OE_BUFFER_TOO_SMALL); + } + + /* Copy key bytes to the caller's buffer */ + if (!BN_bn2bin(bn, buffer)) + OE_RAISE(OE_CRYPTO_ERROR); + + *buffer_size = required_size; + + result = OE_OK; + +done: + + if (rsa) + RSA_free(rsa); + + return result; +} + +static oe_result_t _public_key_get_modulus( + const oe_public_key_t* public_key, + uint8_t* buffer, + size_t* buffer_size) +{ + return _get_public_key_get_modulus_or_exponent( + public_key, buffer, buffer_size, true); +} + +static oe_result_t _public_key_get_exponent( + const oe_public_key_t* public_key, + uint8_t* buffer, + size_t* buffer_size) +{ + return _get_public_key_get_modulus_or_exponent( + public_key, buffer, buffer_size, false); +} + +static oe_result_t _public_key_equal( + const oe_public_key_t* public_key1, + const oe_public_key_t* public_key2, + bool* equal) +{ + oe_result_t result = OE_UNEXPECTED; + RSA* rsa1 = NULL; + RSA* rsa2 = NULL; + + if (equal) + *equal = false; + + /* Reject bad parameters */ + if (!oe_public_key_is_valid(public_key1, OE_RSA_PUBLIC_KEY_MAGIC) || + !oe_public_key_is_valid(public_key2, OE_RSA_PUBLIC_KEY_MAGIC) || !equal) + OE_RAISE(OE_INVALID_PARAMETER); + + if (!(rsa1 = EVP_PKEY_get1_RSA(public_key1->pkey))) + OE_RAISE(OE_INVALID_PARAMETER); + + if (!(rsa2 = EVP_PKEY_get1_RSA(public_key2->pkey))) + OE_RAISE(OE_INVALID_PARAMETER); + + const BIGNUM* e1; + const BIGNUM* e2; + const BIGNUM* n1; + const BIGNUM* n2; + RSA_get0_key(rsa1, &n1, &e1, NULL); + RSA_get0_key(rsa2, &n2, &e2, NULL); + + /* Compare modulus and exponent */ + if (BN_cmp(n1, n2) == 0 && BN_cmp(e1, e2) == 0) + *equal = true; + + result = OE_OK; + +done: + + if (rsa1) + RSA_free(rsa1); + + if (rsa2) + RSA_free(rsa2); + + return result; +} + +void oe_rsa_public_key_init(oe_rsa_public_key_t* public_key, EVP_PKEY* pkey) +{ + oe_public_key_init( + (oe_public_key_t*)public_key, pkey, OE_RSA_PUBLIC_KEY_MAGIC); +} + +oe_result_t oe_rsa_private_key_from_engine( + oe_rsa_private_key_t* private_key, + const char* engine_id, + const char* engine_load_path, + const char* key_id) +{ + return oe_private_key_from_engine( + engine_id, + engine_load_path, + key_id, + (oe_private_key_t*)private_key, + EVP_PKEY_RSA, + OE_RSA_PRIVATE_KEY_MAGIC); +} + +oe_result_t oe_rsa_private_key_read_pem( + oe_rsa_private_key_t* private_key, + const uint8_t* pem_data, + size_t pem_size) +{ + return oe_private_key_read_pem( + pem_data, + pem_size, + (oe_private_key_t*)private_key, + EVP_PKEY_RSA, + OE_RSA_PRIVATE_KEY_MAGIC); +} + +oe_result_t oe_rsa_private_key_write_pem( + const oe_rsa_private_key_t* private_key, + uint8_t* pem_data, + size_t* pem_size) +{ + return oe_private_key_write_pem( + (const oe_private_key_t*)private_key, + pem_data, + pem_size, + _private_key_write_pem_callback, + OE_RSA_PRIVATE_KEY_MAGIC); +} + +oe_result_t oe_rsa_public_key_read_pem( + oe_rsa_public_key_t* public_key, + const uint8_t* pem_data, + size_t pem_size) +{ + return oe_public_key_read_pem( + pem_data, + pem_size, + (oe_public_key_t*)public_key, + EVP_PKEY_RSA, + OE_RSA_PUBLIC_KEY_MAGIC); +} + +oe_result_t oe_rsa_public_key_write_pem( + const oe_rsa_public_key_t* public_key, + uint8_t* pem_data, + size_t* pem_size) +{ + return oe_public_key_write_pem( + (const oe_public_key_t*)public_key, + pem_data, + pem_size, + OE_RSA_PUBLIC_KEY_MAGIC); +} + +oe_result_t oe_rsa_private_key_free(oe_rsa_private_key_t* private_key) +{ + return oe_private_key_free( + (oe_private_key_t*)private_key, OE_RSA_PRIVATE_KEY_MAGIC); +} + +oe_result_t oe_rsa_public_key_free(oe_rsa_public_key_t* public_key) +{ + return oe_public_key_free( + (oe_public_key_t*)public_key, OE_RSA_PUBLIC_KEY_MAGIC); +} + +oe_result_t oe_rsa_private_key_sign( + const oe_rsa_private_key_t* private_key, + oe_hash_type_t hash_type, + const void* hash_data, + size_t hash_size, + uint8_t* signature, + size_t* signature_size) +{ + return oe_private_key_sign( + (oe_private_key_t*)private_key, + hash_type, + hash_data, + hash_size, + signature, + signature_size, + OE_RSA_PRIVATE_KEY_MAGIC); +} + +oe_result_t oe_rsa_public_key_verify( + const oe_rsa_public_key_t* public_key, + oe_hash_type_t hash_type, + const void* hash_data, + size_t hash_size, + const uint8_t* signature, + size_t signature_size) +{ + return oe_public_key_verify( + (oe_public_key_t*)public_key, + hash_type, + hash_data, + hash_size, + signature, + signature_size, + OE_RSA_PUBLIC_KEY_MAGIC); +} + +oe_result_t oe_rsa_public_key_get_modulus( + const oe_rsa_public_key_t* public_key, + uint8_t* buffer, + size_t* buffer_size) +{ + return _public_key_get_modulus( + (oe_public_key_t*)public_key, buffer, buffer_size); +} + +oe_result_t oe_rsa_public_key_get_exponent( + const oe_rsa_public_key_t* public_key, + uint8_t* buffer, + size_t* buffer_size) +{ + return _public_key_get_exponent( + (oe_public_key_t*)public_key, buffer, buffer_size); +} + +oe_result_t oe_rsa_public_key_equal( + const oe_rsa_public_key_t* public_key1, + const oe_rsa_public_key_t* public_key2, + bool* equal) +{ + return _public_key_equal( + (oe_public_key_t*)public_key1, (oe_public_key_t*)public_key2, equal); +} diff --git a/host/crypto/openssl/rsa.h b/common/crypto/openssl/rsa.h similarity index 69% rename from host/crypto/openssl/rsa.h rename to common/crypto/openssl/rsa.h index f746235222..f336d08f4a 100644 --- a/host/crypto/openssl/rsa.h +++ b/common/crypto/openssl/rsa.h @@ -1,8 +1,8 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. -#ifndef _OE_HOST_CRYPTO_OPENSSL_RSA_H -#define _OE_HOST_CRYPTO_OPENSSL_RSA_H +#ifndef _OE_COMMON_CRYPTO_OPENSSL_RSA_H +#define _OE_COMMON_CRYPTO_OPENSSL_RSA_H #include #include @@ -10,4 +10,4 @@ /* Caller is responsible for validating parameters */ void oe_rsa_public_key_init(oe_rsa_public_key_t* public_key, EVP_PKEY* pkey); -#endif /* _OE_HOST_CRYPTO_OPENSSL_RSA_H */ +#endif /* _OE_COMMON_CRYPTO_OPENSSL_RSA_H */ diff --git a/host/crypto/openssl/sha.c b/common/crypto/openssl/sha.c similarity index 100% rename from host/crypto/openssl/sha.c rename to common/crypto/openssl/sha.c diff --git a/common/sgx/eeid.c b/common/sgx/eeid.c index 4fc732c27d..bd32fc6d98 100644 --- a/common/sgx/eeid.c +++ b/common/sgx/eeid.c @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include +#include #include #include @@ -19,14 +20,14 @@ #ifdef OE_BUILD_ENCLAVE #include -#include "../../enclave/crypto/key.h" -#include "../../enclave/crypto/rsa.h" +#include "../../enclave/crypto/mbedtls/key.h" +#include "../../enclave/crypto/mbedtls/rsa.h" #else #include #include #include -#include "../../host/crypto/openssl/key.h" -#include "../../host/crypto/openssl/rsa.h" +#include "../crypto/openssl/key.h" +#include "../crypto/openssl/rsa.h" #endif int is_eeid_base_image(const oe_sgx_enclave_properties_t* properties) diff --git a/enclave/CMakeLists.txt b/enclave/CMakeLists.txt index 0f18b9c6c1..19e7868836 100644 --- a/enclave/CMakeLists.txt +++ b/enclave/CMakeLists.txt @@ -60,7 +60,8 @@ enclave_enable_code_coverage(oeenclave) # functions implemented via EDL files. enclave_include_directories(oeenclave PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/core) -enclave_link_libraries(oeenclave PUBLIC oecryptombed) +enclave_link_libraries(oeenclave PUBLIC oelibc) + if (OE_TRUSTZONE) enclave_link_libraries(oeenclave PUBLIC oelibutee) endif () @@ -78,4 +79,11 @@ install_enclaves( if (WITH_EEID) enclave_compile_definitions(oeenclave PRIVATE OE_WITH_EXPERIMENTAL_EEID) + # oeenclave currently does not link against the oecrypto* library by default. + # Consequently, it does not inherit the include paths of the crypto (e.g., mbedtls) + # headers, which are needed by eeid.c. Therefore, we add the paths here. + enclave_include_directories( + oeenclave PRIVATE + $ + $) endif () diff --git a/enclave/core/sgx/calls.c b/enclave/core/sgx/calls.c index da3936b9c9..ead4077f78 100644 --- a/enclave/core/sgx/calls.c +++ b/enclave/core/sgx/calls.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -174,6 +175,9 @@ static oe_result_t _handle_init_enclave(uint64_t arg_in) * Depends on TD and sgx_create_report, so can't happen earlier */ OE_CHECK(oe_set_is_xsave_supported()); + /* Initialize the OE crypto library. */ + oe_crypto_initialize(); + /* Call global constructors. Now they can safely use simulated * instructions like CPUID. */ oe_call_init_functions(); diff --git a/enclave/crypto/CMakeLists.txt b/enclave/crypto/CMakeLists.txt index 818dccebd8..2430c64752 100644 --- a/enclave/crypto/CMakeLists.txt +++ b/enclave/crypto/CMakeLists.txt @@ -2,3 +2,6 @@ # Licensed under the MIT License. add_subdirectory(mbedtls) +if (BUILD_OPENSSL) + add_subdirectory(openssl) +endif () diff --git a/enclave/crypto/mbedtls/CMakeLists.txt b/enclave/crypto/mbedtls/CMakeLists.txt index 6a9930cc7d..04e2798734 100644 --- a/enclave/crypto/mbedtls/CMakeLists.txt +++ b/enclave/crypto/mbedtls/CMakeLists.txt @@ -4,16 +4,17 @@ add_enclave_library( oecryptombedtls STATIC - ../../../common/asn1.c - ../../../common/cert.c - ../../../common/kdf.c + ${PROJECT_SOURCE_DIR}/common/asn1.c + ${PROJECT_SOURCE_DIR}/common/cert.c + ${PROJECT_SOURCE_DIR}/common/kdf.c asn1.c cert.c + cmac.c crl.c ctr_drbg.c ec.c - cmac.c hmac.c + init.c key.c rsa.c sha.c) diff --git a/enclave/crypto/mbedtls/init.c b/enclave/crypto/mbedtls/init.c new file mode 100644 index 0000000000..df72baef61 --- /dev/null +++ b/enclave/crypto/mbedtls/init.c @@ -0,0 +1,13 @@ +// Copyright (c) Open Enclave SDK contributors. +// Licensed under the MIT License. + +#include + +/* + * oe_crypto_initialize will be invoked during the enclave initialization. + * Do nothing here given that Mbed TLS does not require initialization + * (while OpenSSL does). + */ +void oe_crypto_initialize(void) +{ +} diff --git a/enclave/crypto/openssl/CMakeLists.txt b/enclave/crypto/openssl/CMakeLists.txt new file mode 100644 index 0000000000..776ae655e6 --- /dev/null +++ b/enclave/crypto/openssl/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright (c) Open Enclave SDK contributors. +# Licensed under the MIT License. + +add_enclave_library( + oecryptoopenssl + STATIC + ${PROJECT_SOURCE_DIR}/3rdparty/mbedtls/mbedtls/library/oid.c + ${PROJECT_SOURCE_DIR}/common/asn1.c + ${PROJECT_SOURCE_DIR}/common/cert.c + ${PROJECT_SOURCE_DIR}/common/kdf.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/asn1.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/cert.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/cmac.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/crl.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/ec.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/hmac.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/key.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/rsa.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/sha.c + cert.c + init.c) + +maybe_build_using_clangw(oecryptoopenssl) + +enclave_enable_code_coverage(oecryptoopenssl) + +enclave_include_directories(oecryptoopenssl PUBLIC + $) + +enclave_include_directories( + oecryptoopenssl PRIVATE + $ + $) + +enclave_link_libraries(oecryptoopenssl PUBLIC openssl) + +set_enclave_property(TARGET oecryptoopenssl PROPERTY ARCHIVE_OUTPUT_DIRECTORY + ${OE_LIBDIR}/openenclave/enclave) + +install_enclaves( + TARGETS + oecryptoopenssl + EXPORT + openenclave-targets + ARCHIVE + DESTINATION + ${CMAKE_INSTALL_LIBDIR}/openenclave/enclave) diff --git a/enclave/crypto/openssl/cert.c b/enclave/crypto/openssl/cert.c new file mode 100644 index 0000000000..f7f8ea2dee --- /dev/null +++ b/enclave/crypto/openssl/cert.c @@ -0,0 +1,404 @@ +// Copyright (c) Open Enclave SDK contributors. +// Licensed under the MIT License. + +#include "cert.h" +#include +#include // For mbedtls_oid_get_numeric_string +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Value used by the _decode_oid_to_str() function. Although the OID + * standard does not limit the depth of an OID definition tree (i.e., the + * number of arcs), our implementation only supports a simple decoding + * with a limited depth (i.e., decoding into a fixed size string). + */ +#define OE_OID_MAX_LENGTH 200 + +/* + * Parse the name string into X509_NAME struct. The format of the string is + * "KEY1=VALUE1,KEY2=VALUE2,KEY3=VALUE3...". The implementation is based + * on the mbedtls_x509_string_to_names from Mbed TLS. + * Note that the string is expected to use commas as the separators instead + * of slashes as OpenSSL CLI does. Also, the implementation does not + * support multivalue-RDN names (with the "+" in the value). + */ +X509_NAME* X509_parse_name(const char* name_string) +{ + const char* s = name_string; + const char* c = s; + const char* end = s + strlen(s); + int in_tag = 1; + char key[OE_X509_MAX_NAME_SIZE]; + char data[OE_X509_MAX_NAME_SIZE]; + char* d = data; + X509_NAME* name = NULL; + int error = 1; + + name = X509_NAME_new(); + if (name == NULL) + goto done; + + while (c <= end) + { + if (in_tag && *c == '=') + { + size_t len = (size_t)(c - s) + 1; + if (len > OE_X509_MAX_NAME_SIZE) + goto done; + + if (oe_memcpy_s(key, OE_X509_MAX_NAME_SIZE, s, len) != OE_OK) + goto done; + key[len - 1] = '\0'; + s = c + 1; + in_tag = 0; + d = data; + } + + if (!in_tag && *c == '\\' && c != end) + { + c++; + /* Only support escaping commas */ + if (c == end || *c != ',') + goto done; + } + else if (!in_tag && (*c == ',' || c == end)) + { + /* + * The check of if(d - data == OE_X509_MAX_NAME_SIZE) + * below ensures that d should never go beyond the boundary of data. + * Place null that indicates the end of the string. + */ + *d = '\0'; + if (!X509_NAME_add_entry_by_txt( + name, key, MBSTRING_UTF8, (unsigned char*)data, -1, -1, 0)) + goto done; + + /* Skip the spaces after the comma */ + while (c < end && *(c + 1) == ' ') + c++; + s = c + 1; + in_tag = 1; + } + + if (!in_tag && s != c + 1) + { + *(d++) = *c; + if (d - data == OE_X509_MAX_NAME_SIZE) + goto done; + } + + c++; + } + + error = 0; + +done: + if (error && name) + { + X509_NAME_free(name); + name = NULL; + } + + return name; +} + +/* + * Reuse the mbedtls_oid_get_numeric_string in Mbed TLS to decode the OID from + * its BER format (byte-encoding) into a dot-notation string. + */ +static char* _decode_oid_to_str(char* oid, size_t oid_size) +{ + mbedtls_x509_buf buf; + char* oid_str = NULL; + char oid_buf[OE_OID_MAX_LENGTH]; + int rc; + + buf.tag = 0; + buf.len = oid_size; + buf.p = (unsigned char*)oid; + + rc = mbedtls_oid_get_numeric_string(oid_buf, OE_OID_MAX_LENGTH, &buf); + if (rc < 0) + goto done; + + /* Copy from buffer */ + size_t oid_len = strlen(oid_buf) + 1; + oid_str = (char*)oe_malloc(oid_len); + if (oid_str == NULL) + goto done; + + strncpy(oid_str, oid_buf, oid_len); + +done: + return oid_str; +} + +oe_result_t oe_gen_custom_x509_cert( + oe_cert_config_t* config, + unsigned char* cert_buf, + size_t cert_buf_size, + size_t* bytes_written) +{ + oe_result_t result = OE_CRYPTO_ERROR; + X509* x509cert = NULL; + X509V3_CTX ctx; + BIO* bio = NULL; + X509_NAME* name = NULL; + EVP_PKEY* subject_issuer_key_pair = NULL; + X509_EXTENSION* ext = NULL; + ASN1_OBJECT* obj = NULL; + ASN1_OCTET_STRING* data = NULL; + BASIC_CONSTRAINTS* bc = NULL; + unsigned char* buf = NULL; + unsigned char* p = NULL; + char* oid = NULL; + char date_str[16]; + int len = 0; + int ret = 0; + + x509cert = X509_new(); + subject_issuer_key_pair = EVP_PKEY_new(); + + /* Allocate buffer for certificate */ + if ((buf = oe_malloc(cert_buf_size)) == NULL) + OE_RAISE(OE_OUT_OF_MEMORY); + + /* Set certificate info */ + + /* Parse public key */ + bio = BIO_new_mem_buf( + (const void*)config->public_key_buf, (int)config->public_key_buf_size); + if (bio == NULL) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "bio = NULL"); + + if (!PEM_read_bio_PUBKEY(bio, &subject_issuer_key_pair, NULL, NULL)) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "subject_key read failed"); + + OE_TRACE_VERBOSE( + "custom_x509_cert: key type:%d", + EVP_PKEY_base_id(subject_issuer_key_pair)); + + BIO_free(bio); + bio = NULL; + + /* Parse private key */ + bio = BIO_new_mem_buf( + (const void*)config->private_key_buf, + (int)config->private_key_buf_size); + if (bio == NULL) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "bio = NULL"); + + if (!PEM_read_bio_PrivateKey(bio, &subject_issuer_key_pair, NULL, NULL)) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "issuer_key read failed"); + + BIO_free(bio); + bio = NULL; + + /* Set version to V3 */ + ret = X509_set_version(x509cert, 2); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "set version failed"); + + /* Set key */ + ret = X509_set_pubkey(x509cert, subject_issuer_key_pair); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "set pubkey failed"); + + /* Covert the subject string to X509_name struct */ + name = X509_parse_name((const char*)config->subject_name); + if (!name) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "parse subject name failed"); + + /* Set subject name */ + ret = X509_set_subject_name(x509cert, name); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "set subject name failed"); + + X509_NAME_free(name); + name = NULL; + + /* Covert the issuer string to X509_name struct */ + name = X509_parse_name((const char*)config->issuer_name); + if (!name) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "parse issuer name failed"); + + /* Set issuer name */ + ret = X509_set_issuer_name(x509cert, name); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "set issuer name failed"); + + X509_NAME_free(name); + name = NULL; + + /* Set serial number */ + ret = ASN1_INTEGER_set(X509_get_serialNumber(x509cert), 1); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "set serial number failed"); + + /* Convert the format YYYYMMDDHHMMSS to YYYYMMDDHHMMSSZ */ + strncpy(date_str, (const char*)config->date_not_valid_before, 14); + date_str[14] = 'Z'; + date_str[15] = '\0'; + + /* Set validity start date */ + ret = ASN1_TIME_set_string(X509_getm_notBefore(x509cert), date_str); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "set validity date not before failed"); + + /* Convert the format YYYYMMDDHHMMSS to YYYYMMDDHHMMSSZ */ + strncpy(date_str, (const char*)config->date_not_valid_after, 14); + date_str[14] = 'Z'; + date_str[15] = '\0'; + + /* Set validity end date */ + ret = ASN1_TIME_set_string(X509_getm_notAfter(x509cert), date_str); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "set validity date not after failed"); + + /* Initialize the ctx. Required by X509V3_EXT_conf_nid. */ + /* No configuration database */ + X509V3_set_ctx_nodb(&ctx); + /* Use the target as both issuer and subject for the self-signed + * certificate. */ + X509V3_set_ctx(&ctx, x509cert, x509cert, NULL, NULL, 0); + + /* Set the basic constraints extention */ + ext = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, "CA:FALSE"); + if (!ext) + OE_RAISE_MSG( + OE_CRYPTO_ERROR, "create basic constraint extension failed"); + + ret = X509_add_ext(x509cert, ext, -1); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "add basic constraint extension failed"); + + X509_EXTENSION_free(ext); + ext = NULL; + + /* Set the subject key identifier extension */ + ext = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, "hash"); + if (!ext) + OE_RAISE_MSG( + OE_CRYPTO_ERROR, "create subject key identifier extension failed"); + + ret = X509_add_ext(x509cert, ext, -1); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "add basic constraint extension failed"); + + X509_EXTENSION_free(ext); + ext = NULL; + + /* Set the authority key identifier extension */ + ext = X509V3_EXT_conf_nid( + NULL, &ctx, NID_authority_key_identifier, "keyid:always"); + if (!ext) + OE_RAISE_MSG( + OE_CRYPTO_ERROR, "create subject key identifier extension failed"); + + ret = X509_add_ext(x509cert, ext, -1); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "add basic constraint extension failed"); + X509_EXTENSION_free(ext); + ext = NULL; + + /* Set the custom extension */ + data = ASN1_OCTET_STRING_new(); + if (!data) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "ASN1_OCTET_STRING_new failed"); + + ret = ASN1_OCTET_STRING_set( + data, + (const unsigned char*)config->ext_data_buf, + (int)config->ext_data_buf_size); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "set octet string failed"); + + /* + * By default, the config->oid_ext stores the OID in the encoded form + * (BER-TLV) that can directly be consumed by Mbed TLS APIs. However, + * OpenSSL APIs require the OID in the decoded form. Therefore, we need to + * decode the OID first. + */ + oid = _decode_oid_to_str(config->ext_oid, config->ext_oid_size); + if (!oid) + OE_RAISE_MSG(OE_INVALID_PARAMETER, "decode oid failed"); + + obj = OBJ_txt2obj(oid, 1); + if (!obj) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "create custom extension obj failed"); + + if (!X509_EXTENSION_create_by_OBJ(&ext, obj, 0, data)) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "create custom extension failed"); + + ret = X509_add_ext(x509cert, ext, -1); + if (!ret) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "add custom extension failed"); + + /* Sign the certificate */ + if (!X509_sign(x509cert, subject_issuer_key_pair, EVP_sha256())) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "sign cert failed"); + + /* + * Write to DER + * The use of temporary variable is mandatory. + * If p is not NULL, the i2d_x509 function writes the DER encoded data to + * the buffer at *p and increments p to point after the data just written. + */ + p = buf; + len = i2d_X509(x509cert, &p); + if (len <= 0) + OE_RAISE_MSG(OE_CRYPTO_ERROR, "i2d_X509 failed"); + + *bytes_written = (size_t)len; + + /* Copy DER data to buffer */ + OE_CHECK(oe_memcpy_s( + (void*)cert_buf, cert_buf_size, (const void*)buf, *bytes_written)); + OE_TRACE_VERBOSE("bytes_written = 0x%x", (unsigned int)*bytes_written); + + result = OE_OK; + +done: + if (x509cert) + X509_free(x509cert); + if (ext) + X509_EXTENSION_free(ext); + if (name) + X509_NAME_free(name); + if (bio) + BIO_free(bio); + if (obj) + ASN1_OBJECT_free(obj); + if (data) + ASN1_OCTET_STRING_free(data); + if (bc) + BASIC_CONSTRAINTS_free(bc); + if (subject_issuer_key_pair) + EVP_PKEY_free(subject_issuer_key_pair); + if (buf) + { + oe_free(buf); + buf = NULL; + } + if (oid) + { + oe_free(oid); + oid = NULL; + } + p = NULL; + + return result; +} diff --git a/enclave/crypto/openssl/cert.h b/enclave/crypto/openssl/cert.h new file mode 100644 index 0000000000..671277e2c2 --- /dev/null +++ b/enclave/crypto/openssl/cert.h @@ -0,0 +1,15 @@ +// Copyright (c) Open Enclave SDK contributors. +// Licensed under the MIT License. + +#ifndef _OE_ENCLAVE_CRYPTO_OPENSSL_CERT_H +#define _OE_ENCLAVE_CRYPTO_OPENSSL_CERT_H + +#include + +/* The value is based on the implementation of Mbed TLS + * (MBEDTLS_X509_MAX_DN_NAME_SIZE). */ +#define OE_X509_MAX_NAME_SIZE 256 + +X509_NAME* X509_parse_name(const char* name_string); + +#endif /* _OE_ENCLAVE_CRYPTO_OPENSSL_CERT_H */ diff --git a/enclave/crypto/openssl/init.c b/enclave/crypto/openssl/init.c new file mode 100644 index 0000000000..1d48088649 --- /dev/null +++ b/enclave/crypto/openssl/init.c @@ -0,0 +1,66 @@ +// Copyright (c) Open Enclave SDK contributors. +// Licensed under the MIT License. + +#include +#include +#include +#include +static oe_once_t _openssl_initialize_once; +static ENGINE* eng; + +static void _finalize(void) +{ + if (eng) + { + ENGINE_finish(eng); + ENGINE_free(eng); + ENGINE_cleanup(); + eng = NULL; + } +} + +static void _initialize_rdrand_engine() +{ + int rc = 0; + + /* Initialize rdrand engine. */ + ENGINE_load_rdrand(); + eng = ENGINE_by_id("rdrand"); + if (eng == NULL) + goto done; + + rc = ENGINE_init(eng); + if (rc == 0) + goto done; + + rc = ENGINE_set_default(eng, ENGINE_METHOD_RAND); + if (rc == 0) + goto done; + + if (!atexit(_finalize)) + goto done; + + rc = 1; + +done: + if (rc == 0) + { + OE_TRACE_ERROR("OpenSSL initialization failed"); + _finalize(); + } + return; +} + +static void _initialize(void) +{ + /* + * OpenSSL in the enclave requires us to explicitly register the RDRAND + * engine. + */ + _initialize_rdrand_engine(); +} + +void oe_crypto_initialize(void) +{ + oe_once(&_openssl_initialize_once, _initialize); +} diff --git a/enclave/crypto/openssl/magic.h b/enclave/crypto/openssl/magic.h new file mode 100644 index 0000000000..e37673de05 --- /dev/null +++ b/enclave/crypto/openssl/magic.h @@ -0,0 +1,16 @@ +// Copyright (c) Open Enclave SDK contributors. +// Licensed under the MIT License. + +#ifndef _OE_ENCLAVE_CRYPTO_OPENSSL_MAGIC_H +#define _OE_ENCLAVE_CRYPTO_OPENSSL_MAGIC_H + +/* oe_crypto magic numbers for enclave OpenSSL implementation */ +#define OE_CERT_MAGIC 0xa7a55f4322919317 +#define OE_CERT_CHAIN_MAGIC 0xa87e5d8e25671870 +#define OE_CRL_MAGIC 0x8f062e782b5760b2 +#define OE_EC_PRIVATE_KEY_MAGIC 0x9ffae0517397b76c +#define OE_EC_PUBLIC_KEY_MAGIC 0xb8e1d57e9be31ed7 +#define OE_RSA_PRIVATE_KEY_MAGIC 0xba24987b29769828 +#define OE_RSA_PUBLIC_KEY_MAGIC 0x92f1fdf6c81b4aaa + +#endif /* _OE_ENCLAVE_CRYPTO_OPENSSL_MAGIC_H */ diff --git a/enclave/link.c b/enclave/link.c index 989e1b524e..dcd2c7e5c4 100644 --- a/enclave/link.c +++ b/enclave/link.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "core_t.h" @@ -28,6 +29,7 @@ const void* oe_link_enclave(void) // cause the first definitions of these functions to be picked up. oe_allocator_malloc, oe_debug_malloc_tracking_start, + oe_crypto_initialize, #if defined(OE_USE_DEBUG_MALLOC) oe_debug_malloc_check, #endif /* defined(OE_USE_DEBUG_MALLOC) */ diff --git a/enclave/sgx/attester.c b/enclave/sgx/attester.c index df91e6572e..99daa4ea4e 100644 --- a/enclave/sgx/attester.c +++ b/enclave/sgx/attester.c @@ -16,8 +16,6 @@ #include #include -#include - #include "../common/attest_plugin.h" #include "../common/sgx/endorsements.h" #include "../core/sgx/report.h" diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 7334fac2c8..66f19c332a 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -120,25 +120,27 @@ if (UNIX) list( APPEND PLATFORM_HOST_ONLY_SRC - ../common/cert.c - crypto/openssl/asn1.c - crypto/openssl/cert.c - crypto/openssl/crl.c - crypto/openssl/ec.c + ${PROJECT_SOURCE_DIR}/common/cert.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/asn1.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/cert.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/crl.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/ec.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/key.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/rsa.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/sha.c crypto/openssl/init.c - crypto/openssl/key.c crypto/openssl/rsa.c - crypto/openssl/sha.c linux/hostthread.c linux/time.c) - list(APPEND PLATFORM_SDK_ONLY_SRC ../common/asn1.c crypto/openssl/hmac.c + list(APPEND PLATFORM_SDK_ONLY_SRC ${PROJECT_SOURCE_DIR}/common/asn1.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/hmac.c crypto/openssl/random.c linux/syscall.c) elseif (WIN32) list( APPEND PLATFORM_HOST_ONLY_SRC - ../common/cert.c + ${PROJECT_SOURCE_DIR}/common/cert.c crypto/bcrypt/cert.c crypto/bcrypt/crl.c crypto/bcrypt/ec.c @@ -153,10 +155,10 @@ elseif (WIN32) list( APPEND PLATFORM_SDK_ONLY_SRC - ../3rdparty/mbedtls/mbedtls/library/bignum.c - ../3rdparty/mbedtls/mbedtls/library/platform_util.c #Used by bignum.c - ../common/asn1.c - ../common/cert.c + ${PROJECT_SOURCE_DIR}/3rdparty/mbedtls/mbedtls/library/bignum.c + ${PROJECT_SOURCE_DIR}/3rdparty/mbedtls/mbedtls/library/platform_util.c #Used by bignum.c + ${PROJECT_SOURCE_DIR}/common/asn1.c + ${PROJECT_SOURCE_DIR}/common/cert.c crypto/bcrypt/cert.c crypto/bcrypt/crl.c crypto/bcrypt/ec.c @@ -193,17 +195,17 @@ if (OE_SGX) list( APPEND PLATFORM_HOST_ONLY_SRC - ../common/sgx/endorsements.c - ../common/sgx/qeidentity.c - ../common/sgx/quote.c - ../common/sgx/report.c - ../common/sgx/report_helper.c - ../common/sgx/collateral.c - ../common/sgx/sgxcertextensions.c - ../common/sgx/sgxmeasure.c - ../common/sgx/tcbinfo.c - ../common/sgx/tlsverifier.c - ../common/sgx/verifier.c + ${PROJECT_SOURCE_DIR}/common/sgx/endorsements.c + ${PROJECT_SOURCE_DIR}/common/sgx/qeidentity.c + ${PROJECT_SOURCE_DIR}/common/sgx/quote.c + ${PROJECT_SOURCE_DIR}/common/sgx/report.c + ${PROJECT_SOURCE_DIR}/common/sgx/report_helper.c + ${PROJECT_SOURCE_DIR}/common/sgx/collateral.c + ${PROJECT_SOURCE_DIR}/common/sgx/sgxcertextensions.c + ${PROJECT_SOURCE_DIR}/common/sgx/sgxmeasure.c + ${PROJECT_SOURCE_DIR}/common/sgx/tcbinfo.c + ${PROJECT_SOURCE_DIR}/common/sgx/tlsverifier.c + ${PROJECT_SOURCE_DIR}/common/sgx/verifier.c sgx/hostverify_report.c sgx/report_common.c sgx/sgxquoteprovider.c @@ -211,14 +213,15 @@ if (OE_SGX) sgx/sgxquote.c) if (WITH_EEID) - list(APPEND PLATFORM_HOST_ONLY_SRC ../common/sgx/eeid_verifier.c - ../common/sgx/eeid.c) + list(APPEND PLATFORM_HOST_ONLY_SRC + ${PROJECT_SOURCE_DIR}/common/sgx/eeid_verifier.c + ${PROJECT_SOURCE_DIR}/common/sgx/eeid.c) endif () list( APPEND PLATFORM_SDK_ONLY_SRC - ../common/sgx/cpuid.c + ${PROJECT_SOURCE_DIR}/common/sgx/cpuid.c sgx/calls.c sgx/create.c sgx/elf.c @@ -244,11 +247,8 @@ if (OE_SGX) # OS specific as well. if (UNIX) - list( - APPEND - PLATFORM_HOST_ONLY_SRC - sgx/linux/sgxquoteproviderloader.c - sgx/linux/sgxquoteexloader.c) + list(APPEND PLATFORM_HOST_ONLY_SRC sgx/linux/sgxquoteproviderloader.c + sgx/linux/sgxquoteexloader.c) list( APPEND @@ -261,11 +261,8 @@ if (OE_SGX) sgx/linux/sgxquoteexloader.c sgx/linux/xstate.c) else () - list( - APPEND - PLATFORM_HOST_ONLY_SRC - sgx/windows/sgxquoteproviderloader.c - sgx/windows/sgxquoteexloader.c) + list(APPEND PLATFORM_HOST_ONLY_SRC sgx/windows/sgxquoteproviderloader.c + sgx/windows/sgxquoteexloader.c) list( APPEND @@ -310,11 +307,11 @@ endif () list( APPEND PLATFORM_HOST_ONLY_SRC - ../common/attest_plugin.c - ../common/custom_claims.c - ../common/datetime.c - ../common/safecrt.c - ../common/sha.c + ${PROJECT_SOURCE_DIR}/common/attest_plugin.c + ${PROJECT_SOURCE_DIR}/common/custom_claims.c + ${PROJECT_SOURCE_DIR}/common/datetime.c + ${PROJECT_SOURCE_DIR}/common/safecrt.c + ${PROJECT_SOURCE_DIR}/common/sha.c hexdump.c dupenv.c fopen.c @@ -326,8 +323,8 @@ list( list( APPEND PLATFORM_SDK_ONLY_SRC - ../common/kdf.c - ../common/argv.c + ${PROJECT_SOURCE_DIR}/common/kdf.c + ${PROJECT_SOURCE_DIR}/common/argv.c asym_keys.c ecall_ids.c calls.c diff --git a/host/crypto/bcrypt/cert.c b/host/crypto/bcrypt/cert.c index bd23070135..bef4fc12e8 100644 --- a/host/crypto/bcrypt/cert.c +++ b/host/crypto/bcrypt/cert.c @@ -10,11 +10,11 @@ #include #include -#include "../magic.h" #include "bcrypt.h" #include "crl.h" #include "ec.h" #include "key.h" +#include "magic.h" #include "pem.h" #include "rsa.h" #include "util.h" diff --git a/host/crypto/bcrypt/crl.c b/host/crypto/bcrypt/crl.c index 34fb0f5d9a..d6f63ffdda 100644 --- a/host/crypto/bcrypt/crl.c +++ b/host/crypto/bcrypt/crl.c @@ -6,9 +6,9 @@ #include #include -#include "../magic.h" #include "bcrypt.h" #include "crl.h" +#include "magic.h" #include "util.h" #define DER_DATA_SIZE 8192 diff --git a/host/crypto/bcrypt/ec.c b/host/crypto/bcrypt/ec.c index 7f143be67f..e50d5e38bf 100644 --- a/host/crypto/bcrypt/ec.c +++ b/host/crypto/bcrypt/ec.c @@ -7,10 +7,10 @@ #include #include -#include "../magic.h" #include "bcrypt.h" #include "ec.h" #include "key.h" +#include "magic.h" #include "pem.h" OE_STATIC_ASSERT(sizeof(oe_public_key_t) <= sizeof(oe_ec_public_key_t)); diff --git a/host/crypto/bcrypt/key.c b/host/crypto/bcrypt/key.c index 6c440d69b4..ebc5f91f0e 100644 --- a/host/crypto/bcrypt/key.c +++ b/host/crypto/bcrypt/key.c @@ -7,9 +7,9 @@ #include #include -#include "../magic.h" #include "bcrypt.h" #include "key.h" +#include "magic.h" #include "pem.h" /* can't use an engine with bcrypt */ diff --git a/host/crypto/bcrypt/magic.h b/host/crypto/bcrypt/magic.h new file mode 100644 index 0000000000..5ce934d506 --- /dev/null +++ b/host/crypto/bcrypt/magic.h @@ -0,0 +1,16 @@ +// Copyright (c) Open Enclave SDK contributors. +// Licensed under the MIT License. + +#ifndef _OE_HOST_CRYPTO_BCRYPT_MAGIC_H +#define _OE_HOST_CRYPTO_BCRYPT_MAGIC_H + +/* oe_crypto magic numbers for host BCrypt implementation */ +#define OE_CERT_MAGIC 0x95ca8154b3f3e679 +#define OE_CERT_CHAIN_MAGIC 0xbe0a60c6d7a39453 +#define OE_CRL_MAGIC 0xa21f47e346af4058 +#define OE_EC_PRIVATE_KEY_MAGIC 0x8f2472e2263e422f +#define OE_EC_PUBLIC_KEY_MAGIC 0xa1bfef275c3a8373 +#define OE_RSA_PRIVATE_KEY_MAGIC 0x902a3c00b88ed678 +#define OE_RSA_PUBLIC_KEY_MAGIC 0xab3740b49b10abdd + +#endif /* _OE_HOST_CRYPTO_BCRYPT_MAGIC_H */ diff --git a/host/crypto/bcrypt/rsa.c b/host/crypto/bcrypt/rsa.c index eb2bf14113..d9a466921d 100644 --- a/host/crypto/bcrypt/rsa.c +++ b/host/crypto/bcrypt/rsa.c @@ -7,10 +7,9 @@ #include #include -#include "../magic.h" -#include "../rsa.h" #include "bcrypt.h" #include "key.h" +#include "magic.h" #include "rsa.h" OE_STATIC_ASSERT(sizeof(oe_public_key_t) <= sizeof(oe_rsa_public_key_t)); diff --git a/host/crypto/openssl/init.c b/host/crypto/openssl/init.c index bd2dd08fad..9c4712338e 100644 --- a/host/crypto/openssl/init.c +++ b/host/crypto/openssl/init.c @@ -1,21 +1,25 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. -#include "init.h" +#include #include -#include +#include #include - static pthread_once_t _once = PTHREAD_ONCE_INIT; static void _initialize(void) { + /* + * The following code is used to support OpenSSL < 1.1.0 on the host. Will + * be removed once we drop the support of older version of OpenSSL (along + * with Ubuntu 16.04). + */ OpenSSL_add_all_algorithms(); ERR_load_BIO_strings(); ERR_load_crypto_strings(); } -void oe_initialize_openssl(void) +void oe_crypto_initialize(void) { pthread_once(&_once, _initialize); } diff --git a/host/crypto/openssl/init.h b/host/crypto/openssl/init.h deleted file mode 100644 index 09891d8641..0000000000 --- a/host/crypto/openssl/init.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Open Enclave SDK contributors. -// Licensed under the MIT License. - -#ifndef _OE_CRYPTO_HOST_INIT_H -#define _OE_CRYPTO_HOST_INIT_H - -/* Initializes OpenSSL. May be called multiple times */ -void oe_initialize_openssl(void); - -#endif /* _OE_CRYPTO_HOST_INIT_H */ diff --git a/host/crypto/magic.h b/host/crypto/openssl/magic.h similarity index 67% rename from host/crypto/magic.h rename to host/crypto/openssl/magic.h index 54a4b1ec46..210e1d64de 100644 --- a/host/crypto/magic.h +++ b/host/crypto/openssl/magic.h @@ -1,19 +1,16 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. -#ifndef _OE_HOST_CRYPTO_MAGIC_H -#define _OE_HOST_CRYPTO_MAGIC_H - -/* oe_crypto magic numbers for host types are shared - * between OpenSSL and BCrypt implementations */ +#ifndef _OE_HOST_CRYPTO_OPENSSL_MAGIC_H +#define _OE_HOST_CRYPTO_OPENSSL_MAGIC_H +/* oe_crypto magic numbers for host OpenSSL implementation */ #define OE_CERT_MAGIC 0xbc8e184285de4d2a #define OE_CERT_CHAIN_MAGIC 0xa5ddf70fb28f4480 #define OE_CRL_MAGIC 0xe8c993b1cca24906 - #define OE_EC_PRIVATE_KEY_MAGIC 0x19a751419ae04bbc #define OE_EC_PUBLIC_KEY_MAGIC 0xb1d39580c1f14c02 #define OE_RSA_PRIVATE_KEY_MAGIC 0x7bf635929a714b2c #define OE_RSA_PUBLIC_KEY_MAGIC 0x8f8f72170025426d -#endif /* _OE_HOST_CRYPTO_MAGIC_H */ +#endif /* _OE_HOST_CRYPTO_OPENSSL_MAGIC_H */ diff --git a/host/crypto/openssl/rsa.c b/host/crypto/openssl/rsa.c index 1ca00beaf4..96a6d3af63 100644 --- a/host/crypto/openssl/rsa.c +++ b/host/crypto/openssl/rsa.c @@ -1,17 +1,13 @@ // Copyright (c) Open Enclave SDK contributors. // Licensed under the MIT License. +#include "../../../common/crypto/openssl/rsa.h" #include -#include #include #include #include - -#include "../magic.h" -#include "../rsa.h" -#include "init.h" -#include "key.h" -#include "rsa.h" +#include +#include "../../../common/crypto/openssl/key.h" #if OPENSSL_VERSION_NUMBER < 0x10100000L /* Needed for compatibility with ssl1.1 */ @@ -60,311 +56,6 @@ static int RSA_set0_key(RSA* r, BIGNUM* n, BIGNUM* e, BIGNUM* d) #endif -OE_STATIC_ASSERT(sizeof(oe_public_key_t) <= sizeof(oe_rsa_public_key_t)); -OE_STATIC_ASSERT(sizeof(oe_private_key_t) <= sizeof(oe_rsa_private_key_t)); - -static oe_result_t _private_key_write_pem_callback(BIO* bio, EVP_PKEY* pkey) -{ - oe_result_t result = OE_UNEXPECTED; - RSA* rsa = NULL; - - if (!(rsa = EVP_PKEY_get1_RSA(pkey))) - OE_RAISE(OE_CRYPTO_ERROR); - - if (!PEM_write_bio_RSAPrivateKey(bio, rsa, NULL, NULL, 0, 0, NULL)) - OE_RAISE(OE_CRYPTO_ERROR); - - result = OE_OK; - -done: - - if (rsa) - RSA_free(rsa); - - return result; -} - -static oe_result_t _get_public_key_get_modulus_or_exponent( - const oe_public_key_t* public_key, - uint8_t* buffer, - size_t* buffer_size, - bool get_modulus) -{ - oe_result_t result = OE_UNEXPECTED; - size_t required_size; - const BIGNUM* bn; - RSA* rsa = NULL; - - /* Check for invalid parameters */ - if (!public_key || !buffer_size) - OE_RAISE(OE_INVALID_PARAMETER); - - /* If buffer is null, then buffer_size must be zero */ - if (!buffer && *buffer_size != 0) - OE_RAISE(OE_INVALID_PARAMETER); - - /* Get RSA key */ - if (!(rsa = EVP_PKEY_get1_RSA(public_key->pkey))) - OE_RAISE(OE_CRYPTO_ERROR); - - /* Select modulus or exponent */ - const BIGNUM* e; - const BIGNUM* n; - RSA_get0_key(rsa, &n, &e, NULL); - bn = get_modulus ? n : e; - - /* Determine the required size in bytes */ - { - int n = BN_num_bytes(bn); - - if (n <= 0) - OE_RAISE(OE_CRYPTO_ERROR); - - /* Add one leading byte for the leading zero byte */ - required_size = (size_t)n; - } - - /* If buffer is null or not big enough */ - if (!buffer || (*buffer_size < required_size)) - { - *buffer_size = required_size; - - if (buffer) - OE_RAISE(OE_BUFFER_TOO_SMALL); - /* If buffer is null, this call is intented to get the correct - * buffer_size so no need to trace OE_BUFFER_TOO_SMALL */ - else - OE_RAISE_NO_TRACE(OE_BUFFER_TOO_SMALL); - } - - /* Copy key bytes to the caller's buffer */ - if (!BN_bn2bin(bn, buffer)) - OE_RAISE(OE_CRYPTO_ERROR); - - *buffer_size = required_size; - - result = OE_OK; - -done: - - if (rsa) - RSA_free(rsa); - - return result; -} - -static oe_result_t _public_key_get_modulus( - const oe_public_key_t* public_key, - uint8_t* buffer, - size_t* buffer_size) -{ - return _get_public_key_get_modulus_or_exponent( - public_key, buffer, buffer_size, true); -} - -static oe_result_t _public_key_get_exponent( - const oe_public_key_t* public_key, - uint8_t* buffer, - size_t* buffer_size) -{ - return _get_public_key_get_modulus_or_exponent( - public_key, buffer, buffer_size, false); -} - -static oe_result_t _public_key_equal( - const oe_public_key_t* public_key1, - const oe_public_key_t* public_key2, - bool* equal) -{ - oe_result_t result = OE_UNEXPECTED; - RSA* rsa1 = NULL; - RSA* rsa2 = NULL; - - if (equal) - *equal = false; - - /* Reject bad parameters */ - if (!oe_public_key_is_valid(public_key1, OE_RSA_PUBLIC_KEY_MAGIC) || - !oe_public_key_is_valid(public_key2, OE_RSA_PUBLIC_KEY_MAGIC) || !equal) - OE_RAISE(OE_INVALID_PARAMETER); - - if (!(rsa1 = EVP_PKEY_get1_RSA(public_key1->pkey))) - OE_RAISE(OE_INVALID_PARAMETER); - - if (!(rsa2 = EVP_PKEY_get1_RSA(public_key2->pkey))) - OE_RAISE(OE_INVALID_PARAMETER); - - const BIGNUM* e1; - const BIGNUM* e2; - const BIGNUM* n1; - const BIGNUM* n2; - RSA_get0_key(rsa1, &n1, &e1, NULL); - RSA_get0_key(rsa2, &n2, &e2, NULL); - - /* Compare modulus and exponent */ - if (BN_cmp(n1, n2) == 0 && BN_cmp(e1, e2) == 0) - *equal = true; - - result = OE_OK; - -done: - - if (rsa1) - RSA_free(rsa1); - - if (rsa2) - RSA_free(rsa2); - - return result; -} - -void oe_rsa_public_key_init(oe_rsa_public_key_t* public_key, EVP_PKEY* pkey) -{ - oe_public_key_init( - (oe_public_key_t*)public_key, pkey, OE_RSA_PUBLIC_KEY_MAGIC); -} - -oe_result_t oe_rsa_private_key_from_engine( - oe_rsa_private_key_t* private_key, - const char* engine_id, - const char* engine_load_path, - const char* key_id) -{ - return oe_private_key_from_engine( - engine_id, - engine_load_path, - key_id, - (oe_private_key_t*)private_key, - EVP_PKEY_RSA, - OE_RSA_PRIVATE_KEY_MAGIC); -} - -oe_result_t oe_rsa_private_key_read_pem( - oe_rsa_private_key_t* private_key, - const uint8_t* pem_data, - size_t pem_size) -{ - return oe_private_key_read_pem( - pem_data, - pem_size, - (oe_private_key_t*)private_key, - EVP_PKEY_RSA, - OE_RSA_PRIVATE_KEY_MAGIC); -} - -oe_result_t oe_rsa_private_key_write_pem( - const oe_rsa_private_key_t* private_key, - uint8_t* pem_data, - size_t* pem_size) -{ - return oe_private_key_write_pem( - (const oe_private_key_t*)private_key, - pem_data, - pem_size, - _private_key_write_pem_callback, - OE_RSA_PRIVATE_KEY_MAGIC); -} - -oe_result_t oe_rsa_public_key_read_pem( - oe_rsa_public_key_t* public_key, - const uint8_t* pem_data, - size_t pem_size) -{ - return oe_public_key_read_pem( - pem_data, - pem_size, - (oe_public_key_t*)public_key, - EVP_PKEY_RSA, - OE_RSA_PUBLIC_KEY_MAGIC); -} - -oe_result_t oe_rsa_public_key_write_pem( - const oe_rsa_public_key_t* public_key, - uint8_t* pem_data, - size_t* pem_size) -{ - return oe_public_key_write_pem( - (const oe_public_key_t*)public_key, - pem_data, - pem_size, - OE_RSA_PUBLIC_KEY_MAGIC); -} - -oe_result_t oe_rsa_private_key_free(oe_rsa_private_key_t* private_key) -{ - return oe_private_key_free( - (oe_private_key_t*)private_key, OE_RSA_PRIVATE_KEY_MAGIC); -} - -oe_result_t oe_rsa_public_key_free(oe_rsa_public_key_t* public_key) -{ - return oe_public_key_free( - (oe_public_key_t*)public_key, OE_RSA_PUBLIC_KEY_MAGIC); -} - -oe_result_t oe_rsa_private_key_sign( - const oe_rsa_private_key_t* private_key, - oe_hash_type_t hash_type, - const void* hash_data, - size_t hash_size, - uint8_t* signature, - size_t* signature_size) -{ - return oe_private_key_sign( - (oe_private_key_t*)private_key, - hash_type, - hash_data, - hash_size, - signature, - signature_size, - OE_RSA_PRIVATE_KEY_MAGIC); -} - -oe_result_t oe_rsa_public_key_verify( - const oe_rsa_public_key_t* public_key, - oe_hash_type_t hash_type, - const void* hash_data, - size_t hash_size, - const uint8_t* signature, - size_t signature_size) -{ - return oe_public_key_verify( - (oe_public_key_t*)public_key, - hash_type, - hash_data, - hash_size, - signature, - signature_size, - OE_RSA_PUBLIC_KEY_MAGIC); -} - -oe_result_t oe_rsa_public_key_get_modulus( - const oe_rsa_public_key_t* public_key, - uint8_t* buffer, - size_t* buffer_size) -{ - return _public_key_get_modulus( - (oe_public_key_t*)public_key, buffer, buffer_size); -} - -oe_result_t oe_rsa_public_key_get_exponent( - const oe_rsa_public_key_t* public_key, - uint8_t* buffer, - size_t* buffer_size) -{ - return _public_key_get_exponent( - (oe_public_key_t*)public_key, buffer, buffer_size); -} - -oe_result_t oe_rsa_public_key_equal( - const oe_rsa_public_key_t* public_key1, - const oe_rsa_public_key_t* public_key2, - bool* equal) -{ - return _public_key_equal( - (oe_public_key_t*)public_key1, (oe_public_key_t*)public_key2, equal); -} - oe_result_t oe_rsa_get_public_key_from_private( const oe_rsa_private_key_t* private_key, oe_rsa_public_key_t* public_key) diff --git a/host/crypto/rsa.h b/host/crypto/rsa.h deleted file mode 100644 index c97caadc63..0000000000 --- a/host/crypto/rsa.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Open Enclave SDK contributors. -// Licensed under the MIT License. - -#ifndef _OE_HOST_CRYPTO_RSA_H -#define _OE_HOST_CRYPTO_RSA_H - -#include - -/* Caller is responsible for freeing public key. */ -oe_result_t oe_rsa_get_public_key_from_private( - const oe_rsa_private_key_t* private_key, - oe_rsa_public_key_t* public_key); - -#endif /* _OE_HOST_CRYPTO_RSA_H */ diff --git a/host/measure/CMakeLists.txt b/host/measure/CMakeLists.txt index 26685978e6..40d9b6f0ee 100644 --- a/host/measure/CMakeLists.txt +++ b/host/measure/CMakeLists.txt @@ -4,13 +4,14 @@ # Add a library oehostmr independent of libsgx_enclave_common/libsgx_dcap_ql if (UNIX) set(PLATFORM_HOST_MR_SRC - crypto/openssl/asn1.c - crypto/openssl/cert.c - crypto/openssl/ec.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/asn1.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/cert.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/ec.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/key.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/rsa.c + ${PROJECT_SOURCE_DIR}/common/crypto/openssl/sha.c crypto/openssl/init.c - crypto/openssl/key.c crypto/openssl/rsa.c - crypto/openssl/sha.c linux/hostthread.c linux/time.c) elseif (WIN32) @@ -21,10 +22,10 @@ elseif (WIN32) crypto/bcrypt/pem.c crypto/bcrypt/util.c windows/hostthread.c - ../3rdparty/mbedtls/mbedtls/library/bignum.c - ../3rdparty/mbedtls/mbedtls/library/platform_util.c #Used by bignum.c - ../common/asn1.c - ../common/cert.c + ${PROJECT_SOURCE_DIR}/3rdparty/mbedtls/mbedtls/library/bignum.c + ${PROJECT_SOURCE_DIR}/3rdparty/mbedtls/mbedtls/library/platform_util.c #Used by bignum.c + ${PROJECT_SOURCE_DIR}/common/asn1.c + ${PROJECT_SOURCE_DIR}/common/cert.c crypto/bcrypt/cert.c crypto/bcrypt/crl.c crypto/bcrypt/ec.c @@ -47,7 +48,7 @@ if (OE_SGX) APPEND PLATFORM_HOST_MR_SRC signkey.c - ../common/sgx/sgxmeasure.c + ${PROJECT_SOURCE_DIR}/common/sgx/sgxmeasure.c sgx/create.c sgx/elf.c sgx/load.c @@ -55,10 +56,10 @@ if (OE_SGX) sgx/sgxload.c sgx/sgxsign.c sgx/sgxtypes.c - ../common/sgx/report_helper.c) + ${PROJECT_SOURCE_DIR}/common/sgx/report_helper.c) if (WITH_EEID) - list(APPEND PLATFORM_HOST_MR_SRC ../common/sgx/eeid.c) + list(APPEND PLATFORM_HOST_MR_SRC ${PROJECT_SOURCE_DIR}/common/sgx/eeid.c) endif () # OS specific as well. @@ -86,8 +87,8 @@ endif () list( APPEND PLATFORM_HOST_MR_SRC - ../common/safecrt.c - ../common/sha.c + ${PROJECT_SOURCE_DIR}/common/safecrt.c + ${PROJECT_SOURCE_DIR}/common/sha.c hexdump.c dupenv.c fopen.c diff --git a/host/sgx/sgxsign.c b/host/sgx/sgxsign.c index c20ffed316..e59095c8a3 100644 --- a/host/sgx/sgxsign.c +++ b/host/sgx/sgxsign.c @@ -16,7 +16,6 @@ #include #include #include -#include "../crypto/rsa.h" #include "enclave.h" /* Use mbedtls/openssl for bignum math on Windows/Linux respectively. */ diff --git a/include/openenclave/internal/crypto/init.h b/include/openenclave/internal/crypto/init.h new file mode 100644 index 0000000000..4ce026f415 --- /dev/null +++ b/include/openenclave/internal/crypto/init.h @@ -0,0 +1,10 @@ +// Copyright (c) Open Enclave SDK contributors. +// Licensed under the MIT License. + +#ifndef _OE_INTERNAL_CRYPTO_INIT_H +#define _OE_INTERNAL_CRYPTO_INIT_H + +/* Initialize OE crypto. */ +void oe_crypto_initialize(void); + +#endif /* _OE_INTERNAL_CRYPTO_INIT_H */ diff --git a/include/openenclave/internal/rsa.h b/include/openenclave/internal/rsa.h index de94602af3..60502f3852 100644 --- a/include/openenclave/internal/rsa.h +++ b/include/openenclave/internal/rsa.h @@ -262,6 +262,11 @@ oe_result_t oe_rsa_public_key_equal( const oe_rsa_public_key_t* public_key2, bool* equal); +/* Caller is responsible for freeing public key. */ +oe_result_t oe_rsa_get_public_key_from_private( + const oe_rsa_private_key_t* private_key, + oe_rsa_public_key_t* public_key); + OE_EXTERNC_END #endif /* _OE_RSA_H */ diff --git a/samples/attestation/common/CMakeLists.txt b/samples/attestation/common/CMakeLists.txt index 3dba0a91cb..0cf966a00a 100644 --- a/samples/attestation/common/CMakeLists.txt +++ b/samples/attestation/common/CMakeLists.txt @@ -29,6 +29,6 @@ target_link_libraries( # Alternatively we could use a CMake OBJECT library, but that # requires a newish version of CMake. $<$:-Wl,--require-defined=__oe_ecalls_table> - openenclave::oeenclave openenclave::oelibcxx) + openenclave::oeenclave openenclave::oecryptombed openenclave::oelibcxx) target_include_directories(common PUBLIC ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}) diff --git a/samples/log_callback/enclave/CMakeLists.txt b/samples/log_callback/enclave/CMakeLists.txt index de5330089c..3a981a135b 100644 --- a/samples/log_callback/enclave/CMakeLists.txt +++ b/samples/log_callback/enclave/CMakeLists.txt @@ -25,8 +25,10 @@ if (LVI_MITIGATION MATCHES ControlFlow) # Helper to enable compiler options for LVI mitigation. apply_lvi_mitigation(enclave) # Link against LVI-mitigated libraries. - target_link_libraries(enclave openenclave::oeenclave-lvi-cfg - openenclave::oelibc-lvi-cfg) + target_link_libraries( + enclave openenclave::oeenclave-lvi-cfg openenclave::oecryptombed-lvi-cfg + openenclave::oelibc-lvi-cfg) else () - target_link_libraries(enclave openenclave::oeenclave openenclave::oelibc) + target_link_libraries(enclave openenclave::oeenclave + openenclave::oecryptombed openenclave::oelibc) endif ()