From 74b80b5e53aa98d747f02e5eb361e26ca08de876 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Sun, 9 Apr 2023 03:40:31 +0000 Subject: [PATCH] samples/openssl-hook: a library for embedding rats-tls into any program Signed-off-by: Kun Lai --- samples/CMakeLists.txt | 4 + samples/openssl-hook/CMakeLists.txt | 28 +++ samples/openssl-hook/README.md | 90 ++++++++ samples/openssl-hook/common.h | 37 ++++ samples/openssl-hook/libopenssl-hook.c | 86 ++++++++ samples/openssl-hook/openssl.c | 217 +++++++++++++++++++ src/CMakeLists.txt | 1 + src/api/rats_tls_init.c | 10 +- src/api/rats_tls_setup_ssl.c | 29 +++ src/core/rtls_common.c | 2 +- src/core/rtls_core_generate_certificate.c | 102 +++++---- src/crypto_wrappers/nullcrypto/gen_privkey.c | 2 +- src/crypto_wrappers/nullcrypto/main.c | 4 +- src/crypto_wrappers/openssl/gen_privkey.c | 65 +++--- src/crypto_wrappers/openssl/main.c | 2 +- src/include/internal/core.h | 8 +- src/include/rats-tls/api.h | 13 ++ src/include/rats-tls/crypto_wrapper.h | 2 +- src/include/rats-tls/err.h | 2 - src/include/rats-tls/tls_wrapper.h | 4 +- src/tls_wrappers/nulltls/main.c | 3 +- src/tls_wrappers/nulltls/use_cert.c | 4 +- src/tls_wrappers/openssl/CMakeLists.txt | 1 + src/tls_wrappers/openssl/main.c | 7 +- src/tls_wrappers/openssl/negotiate.c | 2 - src/tls_wrappers/openssl/openssl.h | 3 + src/tls_wrappers/openssl/setup_ssl.c | 154 +++++++++++++ src/tls_wrappers/openssl/un_negotiate.c | 7 + src/tls_wrappers/openssl/use_cert.c | 11 +- src/verifiers/CMakeLists.txt | 2 +- 30 files changed, 799 insertions(+), 103 deletions(-) create mode 100644 samples/openssl-hook/CMakeLists.txt create mode 100644 samples/openssl-hook/README.md create mode 100644 samples/openssl-hook/common.h create mode 100644 samples/openssl-hook/libopenssl-hook.c create mode 100644 samples/openssl-hook/openssl.c create mode 100644 src/api/rats_tls_setup_ssl.c create mode 100644 src/tls_wrappers/openssl/setup_ssl.c diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index c77319e..4083f4b 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -3,3 +3,7 @@ add_subdirectory(rats-tls-server) if(SGX) add_subdirectory(sgx-stub-enclave) endif() + +if(NOT SGX) + add_subdirectory(openssl-hook) +endif() diff --git a/samples/openssl-hook/CMakeLists.txt b/samples/openssl-hook/CMakeLists.txt new file mode 100644 index 0000000..5ef8bd4 --- /dev/null +++ b/samples/openssl-hook/CMakeLists.txt @@ -0,0 +1,28 @@ +project(openssl-hook) + +set(LIB_NAME ${PROJECT_NAME}_lib) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror=implicit-function-declaration -Wundef -Werror") + +set(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include/edl + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/include/rats-tls + ${RATS_TLS_INSTALL_INCLUDE_PATH} + ${RATS_TLS_INSTALL_INCLUDE_PATH}/edl + ) +set(LIBRARY_DIRS ${RATS_TLS_INSTALL_LIB_PATH}) + +include_directories(${INCLUDE_DIRS}) +link_directories(${LIBRARY_DIRS}) + +# Generate .so file +add_library(${LIB_NAME} SHARED libopenssl-hook.c + openssl.c + ) +# DO NOT link this with rats_tls.so, we will call dlopen to load it +# target_link_libraries(${LIB_NAME} rats_tls) +add_dependencies(${LIB_NAME} rats_tls) + +install(TARGETS ${LIB_NAME} + DESTINATION /usr/share/rats-tls/samples) diff --git a/samples/openssl-hook/README.md b/samples/openssl-hook/README.md new file mode 100644 index 0000000..c71473a --- /dev/null +++ b/samples/openssl-hook/README.md @@ -0,0 +1,90 @@ + +# openssl-hook + +A helper library for embedding rats-tls into a programs without recompiling it from source code, with the help of `LD_PRELOAD`. + +## How to use + +We have tested it with `curl` and `nginx`. + +### nginx + +In a TD VM, we launch a simple nginx server which holds a default page, with https enabled. + +Note that rats-tls should be compiled in `tdx` mode. + +```sh +# create a nginx configuration file, and save it as ~/nginx.conf +cat < ~/nginx.conf +daemon off; +worker_processes auto; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 5m; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256; + + server { + listen 1234 ssl; + server_name your_domain.com; + + ssl_certificate /root/cert.pem; + ssl_certificate_key /root/key.pem; + + # rest of your server configuration + } +} +EOF + +# launch the nginx server +LD_PRELOAD=/usr/share/rats-tls/samples/libopenssl-hook_lib.so nginx -c ~/nginx.conf +``` + +### curl + +Here is the client side, no TEE is required, so you can compile rats-tls with `host` mode. + +```sh +LD_PRELOAD=/usr/share/rats-tls/samples/libopenssl-hook_lib.so curl -vvvvv --resolve RATS-TLS:1234: https://RATS-TLS:1234/ +``` + +> In the current implementation, the CN field is always `RATS-TLS`. However, the curl would compare `CN` field in cert with hostname in url. Here we use `--resolve RATS-TLS:1234:` to bypass the check from curl. + +## Debug + +You can use `gdb` to to debug this library. + +```sh +gdb --args env LD_PRELOAD=/usr/share/rats-tls/samples/libopenssl-hook_lib.so +``` + +## TODO + +1. Compile-time hook. + `LD_PRELOAD` relies on the capability of `ld.so`, which does not work in SGX mode, since all object are statically linked. however, it might be possible to accomplish this with some hacks on the commandline flags of `ld` during linking. + +2. Add a executable target. + It would be better to have a tiny helper executable to launch (i.e. `openssl-hook `) instead of set env `LD_PRELOAD` manually. + Also, all configurations are currently hard-coded, and we have to provide a way to configure rats-tls. + diff --git a/samples/openssl-hook/common.h b/samples/openssl-hook/common.h new file mode 100644 index 0000000..2c65332 --- /dev/null +++ b/samples/openssl-hook/common.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2021 Intel Corporation + * Copyright (c) 2020-2023 Alibaba Cloud + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _OPENSSL_HOOK_COMMON_H_ +#define _OPENSSL_HOOK_COMMON_H_ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +extern rats_tls_handle global_rtls_handle; +extern int init_openssl_ctx(); + +inline static int dlsym_load(void **variable, const char *name_str) +{ + dlerror(); /* clear old errors */ + void *f = dlsym(RTLD_NEXT, name_str); + char *e = dlerror(); + if (e != NULL) { + fprintf(stderr, "Failed to find symbol with dlsym %s: %s\n", name_str, e); + return 0; + } + if (f == NULL) { + fprintf(stderr, "Symbol not resolved by dlsym %s\n", name_str); + return 0; + } + *variable = f; + return 1; +} + +#endif diff --git a/samples/openssl-hook/libopenssl-hook.c b/samples/openssl-hook/libopenssl-hook.c new file mode 100644 index 0000000..f537d28 --- /dev/null +++ b/samples/openssl-hook/libopenssl-hook.c @@ -0,0 +1,86 @@ +/* Copyright (c) 2021 Intel Corporation + * Copyright (c) 2020-2023 Alibaba Cloud + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common.h" + +rats_tls_handle global_rtls_handle; + +int user_callback(void *args) +{ + rtls_evidence_t *ev = (rtls_evidence_t *)args; + + fprintf(stderr, "verify_callback called, claims %p, claims_size %zu, args %p\n", + ev->custom_claims, ev->custom_claims_length, args); + for (size_t i = 0; i < ev->custom_claims_length; ++i) { + fprintf(stderr, "custom_claims[%zu] -> name: '%s' value_size: %zu value: '%.*s'\n", + i, ev->custom_claims[i].name, ev->custom_claims[i].value_size, + (int)ev->custom_claims[i].value_size, ev->custom_claims[i].value); + } + return 1; +} + +void init_rats_tls() +{ + char *env_ld_preload = getenv("LD_PRELOAD"); + char c = env_ld_preload[0]; + env_ld_preload[0] = '\0'; + // unsetenv("LD_PRELOAD"); + + /* We will not link this code with rats_tls.so, since librats_tls.so uses __attribute__((constructor)) + * for library initialization. When used with LD_PRELOAD, it becomes a fork bomb. + * Instead, we unset env LD_PRELOAD first, and then load librats_tls.so with dlopen(). The flag + * RTLD_GLOBAL is essential, since it makes symbols from librats_tls.so available for later symbol + * resolution of current library. + */ + + void *rats_tls_lib_handle = dlopen("librats_tls.so", RTLD_LAZY | RTLD_GLOBAL); + if (!rats_tls_lib_handle) { + rats_tls_lib_handle = + dlopen("/usr/local/lib/rats-tls/librats_tls.so", RTLD_LAZY | RTLD_GLOBAL); + } + if (!rats_tls_lib_handle) { + fprintf(stderr, "Failed to load librats_tls.so: %s\n", dlerror()); + return; + } + + rats_tls_conf_t conf; + memset(&conf, 0, sizeof(conf)); + conf.log_level = RATS_TLS_LOG_LEVEL_DEBUG; // TODO: command line params or get from ENV + strcpy(conf.attester_type, "\0"); + strcpy(conf.verifier_type, "tdx_ecdsa"); + strcpy(conf.crypto_type, "openssl"); + strcpy(conf.tls_type, "openssl"); + conf.cert_algo = RATS_TLS_CERT_ALGO_DEFAULT; + // conf.flags |= RATS_TLS_CONF_FLAGS_MUTUAL; + conf.flags |= RATS_TLS_CONF_FLAGS_PROVIDE_ENDORSEMENTS; + + rats_tls_err_t ret = rats_tls_init(&conf, &global_rtls_handle); + if (ret != RATS_TLS_ERR_NONE) { + fprintf(stderr, "Failed to initialize rats tls %#x\n", ret); + return; + } + + ret = rats_tls_set_verification_callback(&global_rtls_handle, user_callback); + if (ret != RATS_TLS_ERR_NONE) { + fprintf(stderr, "Failed to set verification callback %#x\n", ret); + return; + } + + env_ld_preload[0] = c; +} + +__attribute__((constructor)) void init() +{ + printf("openssl-hook init()\n"); + if (init_openssl_ctx()) { + init_rats_tls(); + } +} + +__attribute__((destructor)) void fini() +{ + printf("openssl-hook fini()\n"); +} diff --git a/samples/openssl-hook/openssl.c b/samples/openssl-hook/openssl.c new file mode 100644 index 0000000..2efbdcf --- /dev/null +++ b/samples/openssl-hook/openssl.c @@ -0,0 +1,217 @@ +/* Copyright (c) 2021 Intel Corporation + * Copyright (c) 2020-2023 Alibaba Cloud + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common.h" + +typedef void SSL_CTX; +typedef void X509_STORE_CTX; +typedef void SSL; +// https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_verify.html +typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx); + +typedef void X509; +typedef void EVP_PKEY; +typedef void RSA; +#define STACK_OF(type) void + +typedef struct { + // clang-format off + // https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_verify.html + void (*SSL_CTX_set_verify)(SSL_CTX *ctx, int mode, SSL_verify_cb verify_callback); + void (*SSL_set_verify)(SSL *ssl, int mode, SSL_verify_cb verify_callback); + // https://www.openssl.org/docs/man1.1.1/man3/SSL_accept.html + int (*SSL_accept)(SSL *ssl); + // https://www.openssl.org/docs/man1.1.1/man3/SSL_connect.html + int (*SSL_connect)(SSL *ssl); + // clang-format on +} openssl_ctx_t; + +static openssl_ctx_t openssl_ctx; + +int init_openssl_ctx() +{ + /* Check if openssl */ + void *dl_handle = dlopen("libssl.so", RTLD_LAZY | RTLD_NOLOAD); + if (!dl_handle) { + fprintf(stderr, "OpenSSL is not used, rats-tls would be disabled.\n"); + return 0; + } + + return dlsym_load((void **)&openssl_ctx.SSL_CTX_set_verify, "SSL_CTX_set_verify") && + dlsym_load((void **)&openssl_ctx.SSL_set_verify, "SSL_set_verify") && + dlsym_load((void **)&openssl_ctx.SSL_accept, "SSL_accept") && + dlsym_load((void **)&openssl_ctx.SSL_connect, "SSL_connect"); +} + +/* + * rats-tls wrapper functions + */ +int setup_verifier_with_openssl_ssl_ctx_obj(SSL_CTX *ctx) +{ + rats_tls_err_t ret = rats_tls_setup_ssl(global_rtls_handle, SETUP_VERIRIER, + OPENSSL_SSL_CTX_POINTER, ctx); + if (ret != RATS_TLS_ERR_NONE) { + fprintf(stderr, "Failed to setup verifier: %#x\n", ret); + return 0; + } + return 1; +} + +int setup_verifier_with_openssl_ssl_obj(SSL *ssl) +{ + rats_tls_err_t ret = + rats_tls_setup_ssl(global_rtls_handle, SETUP_VERIRIER, OPENSSL_SSL_POINTER, ssl); + if (ret != RATS_TLS_ERR_NONE) { + fprintf(stderr, "Failed to setup verifier: %#x\n", ret); + return 0; + } + return 1; +} + +int setup_attester_with_openssl_ssl_ctx_obj(SSL_CTX *ctx) +{ + rats_tls_err_t ret = rats_tls_setup_ssl(global_rtls_handle, SETUP_ATTESTER, + OPENSSL_SSL_CTX_POINTER, ctx); + if (ret != RATS_TLS_ERR_NONE) { + fprintf(stderr, "Failed to setup setup attester: %#x\n", ret); + return 0; + } + return 1; +} + +int setup_attester_with_openssl_ssl_obj(SSL *ssl) +{ + rats_tls_err_t ret = + rats_tls_setup_ssl(global_rtls_handle, SETUP_ATTESTER, OPENSSL_SSL_POINTER, ssl); + if (ret != RATS_TLS_ERR_NONE) { + fprintf(stderr, "Failed to setup setup attester: %#x\n", ret); + return 0; + } + return 1; +} + +/* + * Symbols (functions) that are hooked + */ + +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb verify_callback) +{ + fprintf(stderr, "SSL_CTX_set_verify() called\n"); + openssl_ctx.SSL_CTX_set_verify(ctx, mode, verify_callback); + setup_verifier_with_openssl_ssl_ctx_obj(ctx); +} + +void SSL_set_verify(SSL *ssl, int mode, SSL_verify_cb verify_callback) +{ + fprintf(stderr, "SSL_set_verify() called\n"); + openssl_ctx.SSL_set_verify(ssl, mode, verify_callback); + setup_verifier_with_openssl_ssl_obj(ssl); +} + +int SSL_accept(SSL *ssl) +{ + fprintf(stderr, "SSL_accept() called\n"); + setup_verifier_with_openssl_ssl_obj(ssl); + return openssl_ctx.SSL_accept(ssl); +} + +int SSL_connect(SSL *ssl) +{ + fprintf(stderr, "SSL_connect() called\n"); + setup_verifier_with_openssl_ssl_obj(ssl); + return openssl_ctx.SSL_connect(ssl); +} + +// https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_use_certificate.html +int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_use_certificate(SSL *ssl, X509 *x) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} +int SSL_use_certificate_ASN1(SSL *ssl, unsigned char *d, int len) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} +int SSL_use_certificate_file(SSL *ssl, const char *file, int type) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_use_certificate_chain_file(SSL *ssl, const char *file) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, unsigned char *d, long len) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} +int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, unsigned char *d, long len) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} +int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} +int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) * chain, + int override) +{ + return setup_attester_with_openssl_ssl_ctx_obj(ctx); +} +int SSL_use_cert_and_key(SSL *ssl, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) * chain, int override) +{ + return setup_attester_with_openssl_ssl_obj(ssl); +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index de69760..4fd46b5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,7 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/api/rats_tls_receive.c ${CMAKE_CURRENT_SOURCE_DIR}/api/rats_tls_transmit.c ${CMAKE_CURRENT_SOURCE_DIR}/api/rats_tls_callback.c + ${CMAKE_CURRENT_SOURCE_DIR}/api/rats_tls_setup_ssl.c ${CMAKE_CURRENT_SOURCE_DIR}/crypto_wrappers/api/crypto_wrapper_register.c ${CMAKE_CURRENT_SOURCE_DIR}/crypto_wrappers/internal/crypto_wrapper.c ${CMAKE_CURRENT_SOURCE_DIR}/crypto_wrappers/internal/rtls_crypto_wrapper_load_all.c diff --git a/src/api/rats_tls_init.c b/src/api/rats_tls_init.c index 39e64cd..0efe6e7 100644 --- a/src/api/rats_tls_init.c +++ b/src/api/rats_tls_init.c @@ -124,9 +124,13 @@ rats_tls_err_t rats_tls_init(const rats_tls_conf_t *conf, rats_tls_handle *handl /* Check whether requiring to generate TLS certificate */ if ((ctx->config.flags & RATS_TLS_CONF_FLAGS_SERVER) || (ctx->config.flags & RATS_TLS_CONF_FLAGS_MUTUAL)) { - err = rtls_core_generate_certificate(ctx); - if (err != RATS_TLS_ERR_NONE) - goto err_ctx; + /* Avoid re-generation of TLS certificates */ + if (!(ctx->flags & RATS_TLS_CTX_FLAGS_CERT_CREATED)) { + err = rtls_core_generate_certificate(ctx); + if (err != RATS_TLS_ERR_NONE) + goto err_ctx; + ctx->flags |= RATS_TLS_CTX_FLAGS_CERT_CREATED; + } } *handle = ctx; diff --git a/src/api/rats_tls_setup_ssl.c b/src/api/rats_tls_setup_ssl.c new file mode 100644 index 0000000..81c4a1f --- /dev/null +++ b/src/api/rats_tls_setup_ssl.c @@ -0,0 +1,29 @@ +/* Copyright (c) 2021 Intel Corporation + * Copyright (c) 2020-2023 Alibaba Cloud + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "internal/core.h" + +rats_tls_err_t rats_tls_setup_ssl(rats_tls_handle handle, rats_tls_setup_type setup_type, + rats_tls_ssl_obj_type obj_type, void *obj) +{ + rtls_core_context_t *ctx = (rtls_core_context_t *)handle; + + RTLS_DEBUG("handle: %p, setup_type: %#x, obj_type: %#x, obj: %p\n", ctx, setup_type, + obj_type, obj); + + if (!handle || !handle->tls_wrapper || !handle->tls_wrapper->opts || + !handle->tls_wrapper->opts->setup_ssl || !obj) + return RATS_TLS_ERR_INVALID; + + tls_wrapper_err_t err = handle->tls_wrapper->opts->setup_ssl(handle->tls_wrapper, + setup_type, obj_type, obj); + if (err != TLS_WRAPPER_ERR_NONE) + return RATS_TLS_ERR_INVALID; + + return RATS_TLS_ERR_NONE; +} diff --git a/src/core/rtls_common.c b/src/core/rtls_common.c index 891f0d8..ed036d8 100644 --- a/src/core/rtls_common.c +++ b/src/core/rtls_common.c @@ -227,7 +227,7 @@ rats_tls_log_level_t rtls_loglevel_getenv(const char *name) rats_tls_err_t rtls_instance_init(const char *name, __attribute__((unused)) const char *realpath, __attribute__((unused)) void **handle) { - *handle = dlopen(realpath, RTLD_LAZY); + *handle = dlopen(realpath, RTLD_LAZY | RTLD_DEEPBIND); if (*handle == NULL) { RTLS_ERR("failed on dlopen(): %s\n", dlerror()); return -RATS_TLS_ERR_DLOPEN; diff --git a/src/core/rtls_core_generate_certificate.c b/src/core/rtls_core_generate_certificate.c index af98da7..42d27bc 100644 --- a/src/core/rtls_core_generate_certificate.c +++ b/src/core/rtls_core_generate_certificate.c @@ -13,17 +13,67 @@ #include rats_tls_err_t rtls_core_generate_certificate(rtls_core_context_t *ctx) +{ + uint8_t *privkey_buf = NULL; + size_t privkey_len = 0; + uint8_t *cert_buf = NULL; + size_t cert_len = 0; + + rats_tls_err_t ret = RATS_TLS_ERR_NONE; + + ret = rtls_core_generate_certificate_internal(ctx, &privkey_buf, &privkey_len, &cert_buf, + &cert_len); + if (ret) + goto err; + + /* Use the TLS certificate and private key for TLS session */ + if (privkey_len) { +#if 0 + #ifndef SGX + /* Dump private key of this certificate */ + FILE *fp = fopen("/tmp/privkey.der", "wb"); + fwrite(privkey_buf, privkey_len, 1, fp); + fclose(fp); + #endif +#endif + ret = ctx->tls_wrapper->opts->use_privkey(ctx->tls_wrapper, ctx->config.cert_algo, + privkey_buf, privkey_len); + if (ret != TLS_WRAPPER_ERR_NONE) + goto err; + + ret = ctx->tls_wrapper->opts->use_cert(ctx->tls_wrapper, cert_buf, cert_len); + if (ret != TLS_WRAPPER_ERR_NONE) + goto err; + } + + ret = RATS_TLS_ERR_NONE; +err: + if (privkey_buf) + free(privkey_buf); + if (cert_buf) + free(cert_buf); + return ret; +} + +rats_tls_err_t rtls_core_generate_certificate_internal(rtls_core_context_t *ctx, + uint8_t **privkey_buf /* out */, + size_t *privkey_len /* out */, + uint8_t **cert_buf /* out */, + size_t *cert_len /* out */ +) { RTLS_DEBUG("ctx %p\n", ctx); if (!ctx || !ctx->tls_wrapper || !ctx->tls_wrapper->opts || !ctx->crypto_wrapper || !ctx->crypto_wrapper->opts || !ctx->crypto_wrapper->opts->gen_pubkey_hash || - !ctx->crypto_wrapper->opts->gen_cert) - return -RATS_TLS_ERR_INVALID; + !ctx->crypto_wrapper->opts->gen_cert || !privkey_buf || !privkey_len || !cert_buf || + !cert_len) + return RATS_TLS_ERR_INVALID; - /* Avoid re-generation of TLS certificates */ - if (ctx->flags & RATS_TLS_CTX_FLAGS_CERT_CREATED) - return RATS_TLS_ERR_NONE; + *privkey_buf = NULL; + *privkey_len = 0; + *cert_buf = NULL; + *cert_len = 0; /* Check whether the specified algorithm is supported. * @@ -40,15 +90,13 @@ rats_tls_err_t rtls_core_generate_certificate(rtls_core_context_t *ctx) break; default: RTLS_DEBUG("unknown algorithm %d\n", ctx->config.cert_algo); - return -RATS_TLS_ERR_UNSUPPORTED_CERT_ALGO; + return RATS_TLS_ERR_UNSUPPORTED_CERT_ALGO; } /* Generate the new key */ crypto_wrapper_err_t c_err; - uint8_t privkey_buf[2048]; - unsigned int privkey_len = sizeof(privkey_buf); c_err = ctx->crypto_wrapper->opts->gen_privkey(ctx->crypto_wrapper, ctx->config.cert_algo, - privkey_buf, &privkey_len); + privkey_buf, privkey_len); if (c_err != CRYPTO_WRAPPER_ERR_NONE) return c_err; @@ -160,39 +208,9 @@ rats_tls_err_t rtls_core_generate_certificate(rtls_core_context_t *ctx) if (c_err != CRYPTO_WRAPPER_ERR_NONE) return c_err; - /* Use the TLS certificate and private key for TLS session */ - if (privkey_len) { - tls_wrapper_err_t t_err; - -#if 0 - #ifndef SGX - /* Dump private key of this certificate */ - FILE *fp = fopen("/tmp/privkey.der", "wb"); - fwrite(privkey_buf, privkey_len, 1, fp); - fclose(fp); - #endif -#endif - - t_err = ctx->tls_wrapper->opts->use_privkey(ctx->tls_wrapper, ctx->config.cert_algo, - privkey_buf, privkey_len); - if (t_err != TLS_WRAPPER_ERR_NONE) { - if (cert_info.cert_buf) - free(cert_info.cert_buf); - return t_err; - } - - t_err = ctx->tls_wrapper->opts->use_cert(ctx->tls_wrapper, &cert_info); - if (t_err != TLS_WRAPPER_ERR_NONE) { - if (cert_info.cert_buf) - free(cert_info.cert_buf); - return t_err; - } - } - if (cert_info.cert_buf) - free(cert_info.cert_buf); - - /* Prevent from re-generation of TLS certificate */ - ctx->flags |= RATS_TLS_CTX_FLAGS_CERT_CREATED; + *cert_buf = cert_info.cert_buf; + cert_info.cert_buf = NULL; + *cert_len = cert_info.cert_len; return RATS_TLS_ERR_NONE; } diff --git a/src/crypto_wrappers/nullcrypto/gen_privkey.c b/src/crypto_wrappers/nullcrypto/gen_privkey.c index 4692b96..1af9311 100644 --- a/src/crypto_wrappers/nullcrypto/gen_privkey.c +++ b/src/crypto_wrappers/nullcrypto/gen_privkey.c @@ -9,7 +9,7 @@ #include crypto_wrapper_err_t nullcrypto_gen_privkey(crypto_wrapper_ctx_t *ctx, rats_tls_cert_algo_t algo, - uint8_t *privkey_buf, unsigned int *privkey_len) + uint8_t **privkey_buf, size_t *privkey_len) { RTLS_DEBUG("ctx %p, algo %d, privkey_buf %p, privkey_len %p\n", ctx, algo, privkey_buf, privkey_len); diff --git a/src/crypto_wrappers/nullcrypto/main.c b/src/crypto_wrappers/nullcrypto/main.c index 83b2352..f5de8c6 100644 --- a/src/crypto_wrappers/nullcrypto/main.c +++ b/src/crypto_wrappers/nullcrypto/main.c @@ -10,8 +10,8 @@ extern crypto_wrapper_err_t nullcrypto_pre_init(void); extern crypto_wrapper_err_t nullcrypto_init(crypto_wrapper_ctx_t *); extern crypto_wrapper_err_t nullcrypto_gen_privkey(crypto_wrapper_ctx_t *ctx, - rats_tls_cert_algo_t algo, uint8_t *privkey_buf, - unsigned int *privkey_len); + rats_tls_cert_algo_t algo, uint8_t **privkey_buf, + size_t *privkey_len); extern crypto_wrapper_err_t nullcrypto_gen_pubkey_hash(crypto_wrapper_ctx_t *, rats_tls_cert_algo_t, uint8_t *); extern crypto_wrapper_err_t nullcrypto_gen_hash(crypto_wrapper_ctx_t *ctx, hash_algo_t hash_algo, diff --git a/src/crypto_wrappers/openssl/gen_privkey.c b/src/crypto_wrappers/openssl/gen_privkey.c index 9fe4dc8..100a1cb 100644 --- a/src/crypto_wrappers/openssl/gen_privkey.c +++ b/src/crypto_wrappers/openssl/gen_privkey.c @@ -9,10 +9,10 @@ #include "openssl.h" crypto_wrapper_err_t openssl_gen_privkey(crypto_wrapper_ctx_t *ctx, rats_tls_cert_algo_t algo, - uint8_t *privkey_buf, uint32_t *privkey_len) + uint8_t **privkey_buf, uint32_t *privkey_len) { openssl_ctx *octx = NULL; - unsigned char *p = privkey_buf; + uint8_t *p = NULL; BIGNUM *e = NULL; int len = 0; int ret; @@ -20,24 +20,19 @@ crypto_wrapper_err_t openssl_gen_privkey(crypto_wrapper_ctx_t *ctx, rats_tls_cer RTLS_DEBUG("ctx %p, algo %d, privkey_buf %p, privkey_len %p\n", ctx, algo, privkey_buf, privkey_len); - if (!ctx || !privkey_len) - return -CRYPTO_WRAPPER_ERR_INVALID; - - if (privkey_buf != NULL && *privkey_len == 0) - return -CRYPTO_WRAPPER_ERR_INVALID; - - RTLS_DEBUG("%d-byte private key buffer requested ...\n", *privkey_len); + if (!ctx || !privkey_buf || !privkey_len) + return CRYPTO_WRAPPER_ERR_INVALID; octx = ctx->crypto_private; - ret = -CRYPTO_WRAPPER_ERR_NO_MEM; + ret = CRYPTO_WRAPPER_ERR_NO_MEM; if (algo == RATS_TLS_CERT_ALGO_ECC_256_SHA256) { octx->eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (octx->eckey == NULL) goto err; - ret = -CRYPTO_WRAPPER_ERR_PRIV_KEY_LEN; + ret = CRYPTO_WRAPPER_ERR_PRIV_KEY_LEN; EC_KEY_set_asn1_flag(octx->eckey, OPENSSL_EC_NAMED_CURVE); @@ -54,22 +49,22 @@ crypto_wrapper_err_t openssl_gen_privkey(crypto_wrapper_ctx_t *ctx, rats_tls_cer if (len < 0) goto err; - if (p == NULL) { - *privkey_len = (uint32_t)len; - return CRYPTO_WRAPPER_ERR_NONE; - } - - ret = -CRYPTO_WRAPPER_ERR_ECC_KEY_LEN; - - if (*privkey_len < (uint32_t)len) + p = malloc(len); + if (!p) { + ret = CRYPTO_WRAPPER_ERR_NO_MEM; goto err; + } - len = i2d_ECPrivateKey(octx->eckey, &p); + uint8_t *tmp_p = p; + len = i2d_ECPrivateKey(octx->eckey, &tmp_p); if (len < 0) goto err; - RTLS_DEBUG("ECC-256 private key (%d-byte) in DER format generated\n", len); + *privkey_buf = p; + p = NULL; + *privkey_len = len; + RTLS_DEBUG("ECC-256 private key (%d-byte) in DER format generated\n", len); } else if (algo == RATS_TLS_CERT_ALGO_RSA_3072_SHA256) { octx->key = RSA_new(); if (octx->key == NULL) @@ -78,7 +73,7 @@ crypto_wrapper_err_t openssl_gen_privkey(crypto_wrapper_ctx_t *ctx, rats_tls_cer if ((e = BN_new()) == NULL) goto err; - ret = -CRYPTO_WRAPPER_ERR_PRIV_KEY_LEN; + ret = CRYPTO_WRAPPER_ERR_PRIV_KEY_LEN; BN_set_word(e, RSA_F4); if (!RSA_generate_key_ex(octx->key, 3072, e, NULL)) goto err; @@ -87,27 +82,26 @@ crypto_wrapper_err_t openssl_gen_privkey(crypto_wrapper_ctx_t *ctx, rats_tls_cer if (len < 0) goto err; - if (p == NULL) { - *privkey_len = (uint32_t)len; - return CRYPTO_WRAPPER_ERR_NONE; - } - - ret = -CRYPTO_WRAPPER_ERR_RSA_KEY_LEN; - - if (*privkey_len < (uint32_t)len) + p = malloc(len); + if (!p) { + ret = CRYPTO_WRAPPER_ERR_NO_MEM; goto err; + } - len = i2d_RSAPrivateKey(octx->key, &p); + uint8_t *tmp_p = p; + len = i2d_RSAPrivateKey(octx->key, &tmp_p); if (len < 0) goto err; + *privkey_buf = p; + p = NULL; + *privkey_len = len; + RTLS_DEBUG("RSA-3072 private key (%d-byte) in DER format generated\n", len); } else { - return -CRYPTO_WRAPPER_ERR_UNSUPPORTED_ALGO; + return CRYPTO_WRAPPER_ERR_UNSUPPORTED_ALGO; } - *privkey_len = (uint32_t)len; - return CRYPTO_WRAPPER_ERR_NONE; err: @@ -129,5 +123,8 @@ crypto_wrapper_err_t openssl_gen_privkey(crypto_wrapper_ctx_t *ctx, rats_tls_cer if (e) BN_free(e); } + + if (p) + free(p); return ret; } diff --git a/src/crypto_wrappers/openssl/main.c b/src/crypto_wrappers/openssl/main.c index bc1daff..206ae68 100644 --- a/src/crypto_wrappers/openssl/main.c +++ b/src/crypto_wrappers/openssl/main.c @@ -11,7 +11,7 @@ crypto_wrapper_err_t openssl_pre_init(void); crypto_wrapper_err_t openssl_init(crypto_wrapper_ctx_t *ctx); crypto_wrapper_err_t openssl_gen_privkey(crypto_wrapper_ctx_t *ctx, rats_tls_cert_algo_t algo, - uint8_t *privkey_buf, unsigned int *privkey_len); + uint8_t **privkey_buf, size_t *privkey_len); crypto_wrapper_err_t openssl_gen_pubkey_hash(crypto_wrapper_ctx_t *ctx, rats_tls_cert_algo_t algo, uint8_t *hash); crypto_wrapper_err_t openssl_gen_hash(crypto_wrapper_ctx_t *ctx, hash_algo_t hash_algo, diff --git a/src/include/internal/core.h b/src/include/internal/core.h index 4697968..d4d7bab 100644 --- a/src/include/internal/core.h +++ b/src/include/internal/core.h @@ -37,7 +37,13 @@ typedef struct dirent rtls_dirent; extern rtls_core_context_t global_core_context; -extern rats_tls_err_t rtls_core_generate_certificate(rtls_core_context_t *); +extern rats_tls_err_t rtls_core_generate_certificate(rtls_core_context_t *ctx); + +extern rats_tls_err_t rtls_core_generate_certificate_internal(rtls_core_context_t *ctx, + uint8_t **privkey_buf /* out */, + size_t *privkey_len /* out */, + uint8_t **cert_buf /* out */, + size_t *cert_len /* out */); extern void rtls_exit(void); diff --git a/src/include/rats-tls/api.h b/src/include/rats-tls/api.h index 557872a..1d670a3 100644 --- a/src/include/rats-tls/api.h +++ b/src/include/rats-tls/api.h @@ -151,4 +151,17 @@ rats_tls_err_t rats_tls_receive(rats_tls_handle handle, void *buf, size_t *buf_s rats_tls_err_t rats_tls_transmit(rats_tls_handle handle, void *buf, size_t *buf_size); rats_tls_err_t rats_tls_cleanup(rats_tls_handle handle); +typedef enum { + OPENSSL_SSL_POINTER = 0x01000000, /* SSL *obj */ + OPENSSL_SSL_CTX_POINTER, /* SSL_CTX *obj */ +} rats_tls_ssl_obj_type; + +typedef enum { + SETUP_VERIRIER, + SETUP_ATTESTER, +} rats_tls_setup_type; + +rats_tls_err_t rats_tls_setup_ssl(rats_tls_handle handle, rats_tls_setup_type setup_type, + rats_tls_ssl_obj_type obj_type, void *obj); + #endif diff --git a/src/include/rats-tls/crypto_wrapper.h b/src/include/rats-tls/crypto_wrapper.h index 1a8ba6a..c12425b 100644 --- a/src/include/rats-tls/crypto_wrapper.h +++ b/src/include/rats-tls/crypto_wrapper.h @@ -35,7 +35,7 @@ typedef struct { crypto_wrapper_err_t (*pre_init)(void); crypto_wrapper_err_t (*init)(crypto_wrapper_ctx_t *ctx); crypto_wrapper_err_t (*gen_privkey)(crypto_wrapper_ctx_t *ctx, rats_tls_cert_algo_t algo, - uint8_t *privkey_buf, unsigned int *privkey_len); + uint8_t **privkey_buf, size_t *privkey_len); crypto_wrapper_err_t (*gen_pubkey_hash)(crypto_wrapper_ctx_t *ctx, rats_tls_cert_algo_t algo, uint8_t *hash); crypto_wrapper_err_t (*gen_hash)(crypto_wrapper_ctx_t *ctx, hash_algo_t hash_algo, diff --git a/src/include/rats-tls/err.h b/src/include/rats-tls/err.h index 359e8eb..c5289ae 100644 --- a/src/include/rats-tls/err.h +++ b/src/include/rats-tls/err.h @@ -125,8 +125,6 @@ typedef enum { CRYPTO_WRAPPER_ERR_INVALID, CRYPTO_WRAPPER_ERR_CERT, CRYPTO_WRAPPER_ERR_PRIV_KEY_LEN, - CRYPTO_WRAPPER_ERR_ECC_KEY_LEN, - CRYPTO_WRAPPER_ERR_RSA_KEY_LEN, CRYPTO_WRAPPER_ERR_PUB_KEY_LEN, CRYPTO_WRAPPER_ERR_UNSUPPORTED_ALGO, CRYPTO_WRAPPER_ERR_PUB_KEY_DECODE, diff --git a/src/include/rats-tls/tls_wrapper.h b/src/include/rats-tls/tls_wrapper.h index 32ad442..b12958f 100644 --- a/src/include/rats-tls/tls_wrapper.h +++ b/src/include/rats-tls/tls_wrapper.h @@ -35,8 +35,10 @@ typedef struct { tls_wrapper_err_t (*init)(tls_wrapper_ctx_t *ctx); tls_wrapper_err_t (*use_privkey)(tls_wrapper_ctx_t *ctx, rats_tls_cert_algo_t algo, void *privkey_buf, size_t privkey_len); - tls_wrapper_err_t (*use_cert)(tls_wrapper_ctx_t *ctx, rats_tls_cert_info_t *cert_info); + tls_wrapper_err_t (*use_cert)(tls_wrapper_ctx_t *ctx, uint8_t *cert_buf, size_t cert_len); tls_wrapper_err_t (*negotiate)(tls_wrapper_ctx_t *ctx, int fd); + tls_wrapper_err_t (*setup_ssl)(tls_wrapper_ctx_t *ctx, rats_tls_setup_type setup_type, + rats_tls_ssl_obj_type obj_type, void *obj); tls_wrapper_err_t (*transmit)(tls_wrapper_ctx_t *ctx, void *buf, size_t *buf_size); tls_wrapper_err_t (*receive)(tls_wrapper_ctx_t *ctx, void *buf, size_t *buf_size); tls_wrapper_err_t (*cleanup)(tls_wrapper_ctx_t *ctx); diff --git a/src/tls_wrappers/nulltls/main.c b/src/tls_wrappers/nulltls/main.c index 462abf1..c31d7cb 100644 --- a/src/tls_wrappers/nulltls/main.c +++ b/src/tls_wrappers/nulltls/main.c @@ -12,7 +12,8 @@ extern tls_wrapper_err_t nulltls_pre_init(void); extern tls_wrapper_err_t nulltls_init(tls_wrapper_ctx_t *); extern tls_wrapper_err_t nulltls_use_privkey(tls_wrapper_ctx_t *ctx, rats_tls_cert_algo_t algo, void *privkey_buf, size_t privkey_len); -extern tls_wrapper_err_t nulltls_use_cert(tls_wrapper_ctx_t *ctx, rats_tls_cert_info_t *cert_info); +extern tls_wrapper_err_t nulltls_use_cert(tls_wrapper_ctx_t *ctx, uint8_t *cert_buf, + size_t cert_len); extern tls_wrapper_err_t nulltls_negotiate(tls_wrapper_ctx_t *, int fd); extern tls_wrapper_err_t nulltls_transmit(tls_wrapper_ctx_t *, void *, size_t *); extern tls_wrapper_err_t nulltls_receive(tls_wrapper_ctx_t *, void *, size_t *); diff --git a/src/tls_wrappers/nulltls/use_cert.c b/src/tls_wrappers/nulltls/use_cert.c index f24a838..f51298d 100644 --- a/src/tls_wrappers/nulltls/use_cert.c +++ b/src/tls_wrappers/nulltls/use_cert.c @@ -7,9 +7,9 @@ #include #include -tls_wrapper_err_t nulltls_use_cert(tls_wrapper_ctx_t *ctx, rats_tls_cert_info_t *cert_info) +tls_wrapper_err_t nulltls_use_cert(tls_wrapper_ctx_t *ctx, uint8_t *cert_buf, size_t cert_len) { - RTLS_DEBUG("ctx %p, cert_info %p\n", ctx, cert_info); + RTLS_DEBUG("ctx: %p, cert_buf: %p, cert_len: %zu\n", ctx, cert_buf, cert_len); return TLS_WRAPPER_ERR_NONE; } diff --git a/src/tls_wrappers/openssl/CMakeLists.txt b/src/tls_wrappers/openssl/CMakeLists.txt index 2bc8da8..e8c4099 100644 --- a/src/tls_wrappers/openssl/CMakeLists.txt +++ b/src/tls_wrappers/openssl/CMakeLists.txt @@ -22,6 +22,7 @@ set(SOURCES cleanup.c init.c main.c negotiate.c + setup_ssl.c un_negotiate.c pre_init.c receive.c diff --git a/src/tls_wrappers/openssl/main.c b/src/tls_wrappers/openssl/main.c index c1c88fe..8d959bc 100644 --- a/src/tls_wrappers/openssl/main.c +++ b/src/tls_wrappers/openssl/main.c @@ -13,9 +13,11 @@ extern tls_wrapper_err_t openssl_tls_pre_init(void); extern tls_wrapper_err_t openssl_tls_init(tls_wrapper_ctx_t *); extern tls_wrapper_err_t openssl_tls_use_privkey(tls_wrapper_ctx_t *ctx, rats_tls_cert_algo_t algo, void *privkey_buf, size_t privkey_len); -extern tls_wrapper_err_t openssl_tls_use_cert(tls_wrapper_ctx_t *ctx, - rats_tls_cert_info_t *cert_info); +extern tls_wrapper_err_t openssl_tls_use_cert(tls_wrapper_ctx_t *ctx, uint8_t *cert_buf, + size_t cert_len); extern tls_wrapper_err_t openssl_tls_negotiate(tls_wrapper_ctx_t *, int fd); +extern tls_wrapper_err_t openssl_setup_ssl(tls_wrapper_ctx_t *ctx, rats_tls_setup_type setup_type, + rats_tls_ssl_obj_type obj_type, void *obj); extern tls_wrapper_err_t openssl_tls_transmit(tls_wrapper_ctx_t *, void *, size_t *); extern tls_wrapper_err_t openssl_tls_receive(tls_wrapper_ctx_t *, void *, size_t *); extern tls_wrapper_err_t openssl_tls_cleanup(tls_wrapper_ctx_t *); @@ -29,6 +31,7 @@ static tls_wrapper_opts_t openssl_opts = { .use_privkey = openssl_tls_use_privkey, .use_cert = openssl_tls_use_cert, .negotiate = openssl_tls_negotiate, + .setup_ssl = openssl_setup_ssl, .transmit = openssl_tls_transmit, .receive = openssl_tls_receive, .cleanup = openssl_tls_cleanup, diff --git a/src/tls_wrappers/openssl/negotiate.c b/src/tls_wrappers/openssl/negotiate.c index 8657924..2d66643 100644 --- a/src/tls_wrappers/openssl/negotiate.c +++ b/src/tls_wrappers/openssl/negotiate.c @@ -10,8 +10,6 @@ #include #include "openssl.h" -extern int verify_certificate(int preverify_ok, X509_STORE_CTX *store); - tls_wrapper_err_t openssl_internal_negotiate(tls_wrapper_ctx_t *ctx, unsigned long conf_flags, int fd, int (*verify)(int, X509_STORE_CTX *)) { diff --git a/src/tls_wrappers/openssl/openssl.h b/src/tls_wrappers/openssl/openssl.h index c18dd5d..901682e 100644 --- a/src/tls_wrappers/openssl/openssl.h +++ b/src/tls_wrappers/openssl/openssl.h @@ -23,11 +23,14 @@ #include #include #include +#include #define SSL_SUCCESS 1 extern int openssl_ex_data_idx; +extern int verify_certificate(int preverify_ok, X509_STORE_CTX *store); + typedef struct { SSL_CTX *sctx; SSL *ssl; diff --git a/src/tls_wrappers/openssl/setup_ssl.c b/src/tls_wrappers/openssl/setup_ssl.c new file mode 100644 index 0000000..17e99f0 --- /dev/null +++ b/src/tls_wrappers/openssl/setup_ssl.c @@ -0,0 +1,154 @@ +/* Copyright (c) 2021 Intel Corporation + * Copyright (c) 2020-2021 Alibaba Cloud + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "internal/core.h" +#include "openssl.h" + +tls_wrapper_err_t openssl_setup_ssl_verifier(tls_wrapper_ctx_t *ctx, rats_tls_ssl_obj_type obj_type, + void *obj) +{ + SSL_verify_cb old_verify_cb = NULL; + X509_STORE *cert_store = NULL; + int verify_mode = 0; + + switch (obj_type) { + case OPENSSL_SSL_POINTER: { + SSL *ssl = (SSL *)obj; + old_verify_cb = SSL_get_verify_callback(ssl); + SSL_CTX *ssl_ctx = SSL_get_SSL_CTX(ssl); + /* Note that we use parent SSL_CTX struct's store pointer here, however we will miss this + * if the user calls SSL_set0_verify_cert_store(). SSL_get0_verify_cert_store() is good to + * slove this problem, but it requires newer openssl version. + * See: https://www.openssl.org/docs/man1.1.1/man3/SSL_get0_verify_cert_store.html + */ + cert_store = SSL_CTX_get_cert_store(ssl_ctx); + verify_mode = SSL_get_verify_mode(ssl); + if (old_verify_cb == verify_certificate) + break; + X509_STORE_set_ex_data(cert_store, openssl_ex_data_idx, ctx); + SSL_set_verify(ssl, verify_mode, verify_certificate); + break; + } + case OPENSSL_SSL_CTX_POINTER: { + SSL_CTX *ssl_ctx = (SSL_CTX *)obj; + old_verify_cb = SSL_CTX_get_verify_callback(ssl_ctx); + cert_store = SSL_CTX_get_cert_store(ssl_ctx); + verify_mode = SSL_CTX_get_verify_mode(ssl_ctx); + if (old_verify_cb == verify_certificate) + break; + X509_STORE_set_ex_data(cert_store, openssl_ex_data_idx, ctx); + SSL_CTX_set_verify(ssl_ctx, verify_mode, verify_certificate); + // TODO: call old_verify_cb, and detect duplicate calls of this function. + break; + } + default: + RTLS_ERR("Unsupported ssl object type: %#x, obj: %p\n", obj_type, obj); + return TLS_WRAPPER_ERR_INVALID; + } + return TLS_WRAPPER_ERR_NONE; +} + +tls_wrapper_err_t openssl_setup_ssl_attester(tls_wrapper_ctx_t *ctx, rats_tls_ssl_obj_type obj_type, + void *obj) +{ + uint8_t *privkey_buf = NULL; + size_t privkey_len = 0; + uint8_t *cert_buf = NULL; + size_t cert_len = 0; + + rats_tls_err_t ret = RATS_TLS_ERR_NONE; + + ret = rtls_core_generate_certificate_internal(ctx->rtls_handle, &privkey_buf, &privkey_len, + &cert_buf, &cert_len); + + int EPKEY; + rats_tls_cert_algo_t cert_algo = ctx->rtls_handle->config.cert_algo; + if (cert_algo == RATS_TLS_CERT_ALGO_ECC_256_SHA256) { + EPKEY = EVP_PKEY_EC; + } else if (cert_algo == RATS_TLS_CERT_ALGO_RSA_3072_SHA256) { + EPKEY = EVP_PKEY_RSA; + } else { + ret = CRYPTO_WRAPPER_ERR_UNSUPPORTED_ALGO; + goto err; + } + + ERR_clear_error(); + + switch (obj_type) { + case OPENSSL_SSL_POINTER: { + SSL *ssl = (SSL *)obj; + int ssl_ret = SSL_use_certificate_ASN1(ssl, cert_buf, cert_len); + if (ssl_ret != SSL_SUCCESS) { + RTLS_ERR("Failed to setup certificate: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + ret = OPENSSL_ERR_CODE(ssl_ret); + goto err; + } + ssl_ret = SSL_use_PrivateKey_ASN1(EPKEY, ssl, privkey_buf, (long)privkey_len); + if (ssl_ret != SSL_SUCCESS) { + RTLS_ERR("Failed to setup private key: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + ret = OPENSSL_ERR_CODE(ssl_ret); + goto err; + } + break; + } + case OPENSSL_SSL_CTX_POINTER: { + SSL_CTX *ssl_ctx = (SSL_CTX *)obj; + int ssl_ret = SSL_CTX_use_certificate_ASN1(ssl_ctx, cert_len, cert_buf); + if (ssl_ret != SSL_SUCCESS) { + RTLS_ERR("Failed to setup certificate: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + ret = OPENSSL_ERR_CODE(ssl_ret); + goto err; + } + ssl_ret = + SSL_CTX_use_PrivateKey_ASN1(EPKEY, ssl_ctx, privkey_buf, (long)privkey_len); + if (ssl_ret != SSL_SUCCESS) { + RTLS_ERR("Failed to setup private key: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + ret = OPENSSL_ERR_CODE(ssl_ret); + goto err; + } + break; + } + default: + RTLS_ERR("Unsupported ssl object type: %#x, obj: %p\n", obj_type, obj); + ret = TLS_WRAPPER_ERR_INVALID; + goto err; + } + ret = TLS_WRAPPER_ERR_NONE; +err: + if (privkey_buf) + free(privkey_buf); + if (cert_buf) + free(cert_buf); + return ret; +} + +tls_wrapper_err_t openssl_setup_ssl(tls_wrapper_ctx_t *ctx, rats_tls_setup_type setup_type, + rats_tls_ssl_obj_type obj_type, void *obj) +{ + RTLS_DEBUG("handle %p, obj_type %#x, obj %p\n", ctx, obj_type, obj); + + if (!ctx || !obj) + return TLS_WRAPPER_ERR_INVALID; + + switch (setup_type) { + case SETUP_VERIRIER: + return openssl_setup_ssl_verifier(ctx, obj_type, obj); + break; + case SETUP_ATTESTER: + return openssl_setup_ssl_attester(ctx, obj_type, obj); + break; + default: + RTLS_ERR("Unsupported setup type: %#x\n", setup_type); + return TLS_WRAPPER_ERR_INVALID; + } + return TLS_WRAPPER_ERR_NONE; +} diff --git a/src/tls_wrappers/openssl/un_negotiate.c b/src/tls_wrappers/openssl/un_negotiate.c index 37c58e4..1ae19d2 100644 --- a/src/tls_wrappers/openssl/un_negotiate.c +++ b/src/tls_wrappers/openssl/un_negotiate.c @@ -223,6 +223,7 @@ int verify_certificate(int preverify_ok, X509_STORE_CTX *ctx) &evidence_buffer_size, true); if (rc != SSL_SUCCESS) { RTLS_ERR("failed to extract the evidence extensions from the certificate %d\n", rc); + X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION); return rc; } @@ -232,6 +233,7 @@ int verify_certificate(int preverify_ok, X509_STORE_CTX *ctx) free(evidence_buffer); RTLS_ERR("failed to extract the endorsements extensions from the certificate %d\n", rc); + X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION); return rc; } @@ -240,8 +242,13 @@ int verify_certificate(int preverify_ok, X509_STORE_CTX *ctx) endorsements_buffer, endorsements_buffer_size); if (t_err != TLS_WRAPPER_ERR_NONE) { RTLS_ERR("failed to verify certificate extension %#x\n", t_err); + /* Update cert verification result of current cert as X509_V_ERR_APPLICATION_VERIFICATION. + * Upper layer applcation like curl may rely on this to show the user the correct error message. */ + X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION); return 0; } + /* Clear verify errors here, so that later call to SSL_get_verify_result() will return X509_V_OK. */ + X509_STORE_CTX_set_error(ctx, X509_V_OK); return SSL_SUCCESS; } diff --git a/src/tls_wrappers/openssl/use_cert.c b/src/tls_wrappers/openssl/use_cert.c index 768295d..98c225f 100644 --- a/src/tls_wrappers/openssl/use_cert.c +++ b/src/tls_wrappers/openssl/use_cert.c @@ -8,16 +8,15 @@ #include #include "openssl.h" -tls_wrapper_err_t openssl_tls_use_cert(tls_wrapper_ctx_t *ctx, rats_tls_cert_info_t *cert_info) +tls_wrapper_err_t openssl_tls_use_cert(tls_wrapper_ctx_t *ctx, uint8_t *cert_buf, size_t cert_len) { - RTLS_DEBUG("ctx %p, cert_info %p\n", ctx, cert_info); + RTLS_DEBUG("ctx: %p, cert_buf: %p, cert_len: %zu\n", ctx, cert_buf, cert_len); - if (!ctx || !cert_info) - return -TLS_WRAPPER_ERR_INVALID; + if (!ctx || !cert_buf || !cert_len) + return TLS_WRAPPER_ERR_INVALID; openssl_ctx_t *ssl_ctx = (openssl_ctx_t *)ctx->tls_private; - int ret = SSL_CTX_use_certificate_ASN1(ssl_ctx->sctx, cert_info->cert_len, - cert_info->cert_buf); + int ret = SSL_CTX_use_certificate_ASN1(ssl_ctx->sctx, cert_len, cert_buf); if (ret != SSL_SUCCESS) { RTLS_ERR("failed to use certificate %d\n", ret); return OPENSSL_ERR_CODE(ret); diff --git a/src/verifiers/CMakeLists.txt b/src/verifiers/CMakeLists.txt index 3f0103c..aa8ec05 100644 --- a/src/verifiers/CMakeLists.txt +++ b/src/verifiers/CMakeLists.txt @@ -13,7 +13,7 @@ if(HOST OR TDX) add_subdirectory(csv) endif() -if(TDX OR SGX) +if(TDX OR SGX OR HOST) if(SGXDCAPQV_FOUND) add_subdirectory(tdx-ecdsa) else()