Skip to content

Commit

Permalink
samples/openssl-hook: a library for embedding rats-tls into any program
Browse files Browse the repository at this point in the history
Signed-off-by: Kun Lai <[email protected]>
  • Loading branch information
imlk0 committed Apr 13, 2023
1 parent 2e527ae commit 74b80b5
Show file tree
Hide file tree
Showing 30 changed files with 799 additions and 103 deletions.
4 changes: 4 additions & 0 deletions samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
28 changes: 28 additions & 0 deletions samples/openssl-hook/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
90 changes: 90 additions & 0 deletions samples/openssl-hook/README.md
Original file line number Diff line number Diff line change
@@ -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 <<EOF > ~/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:<nginx_ip_address> 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:<nginx_ip_address>` 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 <your-target-app>
```

## 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 <COMMAND [ARGS]...>`) 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.

37 changes: 37 additions & 0 deletions samples/openssl-hook/common.h
Original file line number Diff line number Diff line change
@@ -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 <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <rats-tls/api.h>

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
86 changes: 86 additions & 0 deletions samples/openssl-hook/libopenssl-hook.c
Original file line number Diff line number Diff line change
@@ -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");
}
Loading

0 comments on commit 74b80b5

Please sign in to comment.