Quellcode durchsuchen

[LibOS,Pal/{lib,Linux-SGX}] Add TLS-PSK protection to process checkpoint IPC

Previously, Graphene-SGX did not protect send/recv of checkpoint from
parent to child. This leaked all memory contents of the parent process.

This commit adds TLS-PSK (TLS with Pre-Shared Key) wrapper for process
communication. Graphene-SGX already has the logic for SGX-based local
attestation and generation of the shared key for each parent <-> child
communication channel via Diffie–Hellman key exchange. This commit
uses this pre-shared key to create an mbedTLS-based session based on
UNIX domain socketpair (parent.process.stream <-> child.process.stream).

_DkStreamSecure{Init,Free,Read,Write} internal Linux-SGX PAL functions
are added and used during child process creation and sending of the
parent-generated checkpoint. These functions are backed by crypto-layer
lib_SSL{Init,Free,Read,Write} functions which in turn use mbedTLS.
Configuration of mbedTLS is expanded to support TLS-PSK; note that for
entropy source we use only rdrand instruction inside SGX enclave (i.e.,
no untrusted host-platform sources of entropy). The only ciphersuite
currently supported for IPC is MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256.

This commit adds protection only for checkpoint IPC. After the checkpoint
is sent/received, the parent/child processes downgrade their sockets to
plain non-secure ones (by disabling TLS). This is done because child
may spawn a grandchild that also wants to communicate with grandparent,
but it is impossible for multiple processes to share same TLS context.

Additionally, this commit sanitizes "process" PAL handles during send-
handle checkpoint send (via DkSendHandle): shared key and TLS context
are zeroed out.
Dmitrii Kuvaiskii vor 4 Jahren
Ursprung
Commit
735f54d22c

+ 13 - 0
LibOS/shim/src/shim_checkpoint.c

@@ -901,6 +901,19 @@ int do_migrate_process (int (*migrate) (struct shim_cp_store *,
         goto out;
     }
 
+    /* Downgrade communication with child to non-secure (only checkpoint send is secure).
+     * Currently only relevant to SGX PAL, other PALs ignore this. */
+    PAL_STREAM_ATTR attr;
+    if (!DkStreamAttributesQueryByHandle(proc, &attr)) {
+        ret = -PAL_ERRNO;
+        goto out;
+    }
+    attr.secure = PAL_FALSE;
+    if (!DkStreamAttributesSetByHandle(proc, &attr)) {
+        ret = -PAL_ERRNO;
+        goto out;
+    }
+
     SAVE_PROFILE_INTERVAL(migrate_wait_response);
 
     /* exec != NULL implies the execve case so the new process "replaces"

+ 9 - 0
LibOS/shim/src/shim_init.c

@@ -749,6 +749,15 @@ noreturn void* shim_init (int argc, void * args)
                                     &res, NULL);
         if (ret == PAL_STREAM_ERROR)
             shim_do_exit(-PAL_ERRNO);
+
+        /* Downgrade communication with parent to non-secure (only checkpoint recv is secure).
+         * Currently only relevant to SGX PAL, other PALs ignore this. */
+        PAL_STREAM_ATTR attr;
+        if (!DkStreamAttributesQueryByHandle(PAL_CB(parent_process), &attr))
+            shim_do_exit(-PAL_ERRNO);
+        attr.secure = PAL_FALSE;
+        if (!DkStreamAttributesSetByHandle(PAL_CB(parent_process), &attr))
+            shim_do_exit(-PAL_ERRNO);
     }
 
     debug("shim process initialized\n");

+ 5 - 2
Pal/lib/Makefile

@@ -34,7 +34,10 @@ CRYPTO_PROVIDER ?= mbedtls
 # symbols.
 ifeq ($(CRYPTO_PROVIDER),mbedtls)
 subdirs += crypto/mbedtls/library
-crypto_mbedtls_library_objs = $(addsuffix .o,aes aesni asn1parse base64 bignum cipher cipher_wrap cmac dhm md md_wrap oid rsa rsa_internal sha256 platform_util)
+crypto_mbedtls_library_objs = $(addsuffix .o, aes aesni asn1parse base64 bignum cipher \
+                                              cipher_wrap cmac ctr_drbg dhm entropy gcm md \
+                                              md_wrap oid rsa rsa_internal sha256 ssl_tls \
+                                              ssl_ciphersuites ssl_cli ssl_srv platform_util)
 endif
 
 MBEDTLS_VERSION ?= 2.16.3
@@ -77,7 +80,7 @@ objs += $(foreach dir,$(subdirs),$(addprefix $(dir)/,$($(subst /,_,$(dir))_objs)
 $(addprefix $(target),crypto/adapters/mbedtls_adapter.o crypto/adapters/mbedtls_dh.o crypto/adapters/mbedtls_encoding.o): crypto/mbedtls/library/aes.c
 
 ifeq ($(CRYPTO_PROVIDER),mbedtls)
-CFLAGS += -DCRYPTO_USE_MBEDTLS
+CFLAGS += -DCRYPTO_USE_MBEDTLS -mrdrnd
 objs += crypto/adapters/mbedtls_adapter.o
 objs += crypto/adapters/mbedtls_dh.o
 objs += crypto/adapters/mbedtls_encoding.o

+ 143 - 2
Pal/lib/crypto/adapters/mbedtls_adapter.c

@@ -16,8 +16,10 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
-#include <stdint.h>
+#include <immintrin.h>
 #include <limits.h>
+#include <stdint.h>
+
 #include "api.h"
 #include "pal.h"
 #include "pal_crypto.h"
@@ -26,8 +28,10 @@
 #include "assert.h"
 #include "mbedtls/aes.h"
 #include "mbedtls/cmac.h"
-#include "mbedtls/sha256.h"
+#include "mbedtls/error.h"
+#include "mbedtls/net_sockets.h"
 #include "mbedtls/rsa.h"
+#include "mbedtls/sha256.h"
 
 int mbedtls_to_pal_error(int error)
 {
@@ -312,3 +316,140 @@ int lib_RSAFreeKey(LIB_RSA_KEY *key)
     mbedtls_rsa_free(key);
     return 0;
 }
+
+int mbedtls_hardware_poll(void* data, unsigned char* output, size_t len, size_t* olen) {
+    __UNUSED(data);
+    assert(output && olen);
+    *olen = 0;
+
+    unsigned long long rand64;
+    for (size_t i = 0; i < len; i += sizeof(rand64)) {
+        while (__builtin_ia32_rdrand64_step(&rand64) == 0)
+            /*nop*/;
+        size_t over = i + sizeof(rand64) < len ? 0 : i + sizeof(rand64) - len;
+        memcpy(output + i, &rand64, sizeof(rand64) - over);
+    }
+
+    *olen = len;
+    return 0;
+}
+
+static int recv_cb(void* ctx, uint8_t* buf, size_t len) {
+    LIB_SSL_CONTEXT* ssl_ctx = (LIB_SSL_CONTEXT*)ctx;
+    int fd = ssl_ctx->stream_fd;
+    if (fd < 0)
+        return MBEDTLS_ERR_NET_INVALID_CONTEXT;
+
+    if (len != (uint32_t)len) {
+        /* pal_recv_cb cannot receive more than 32-bit limit, trim len to fit in 32-bit */
+        len = UINT32_MAX;
+    }
+
+    int ret = ssl_ctx->pal_recv_cb(fd, buf, (uint32_t)len);
+
+    if (ret < 0) {
+        if (ret == -EINTR)
+            return MBEDTLS_ERR_SSL_WANT_READ;
+        return MBEDTLS_ERR_NET_RECV_FAILED;
+    }
+
+    return ret;
+}
+
+static int send_cb(void* ctx, uint8_t const* buf, size_t len) {
+    LIB_SSL_CONTEXT* ssl_ctx = (LIB_SSL_CONTEXT*)ctx;
+    int fd = ssl_ctx->stream_fd;
+    if (fd < 0)
+        return MBEDTLS_ERR_NET_INVALID_CONTEXT;
+
+    if (len != (uint32_t)len) {
+        /* pal_send_cb cannot send more than 32-bit limit, trim len to fit in 32-bit */
+        len = UINT32_MAX;
+    }
+
+    int ret = ssl_ctx->pal_send_cb(fd, buf, (uint32_t)len);
+    if (ret < 0) {
+        if (ret == -EINTR)
+            return MBEDTLS_ERR_SSL_WANT_WRITE;
+        return MBEDTLS_ERR_NET_SEND_FAILED;
+    }
+
+    return ret;
+}
+
+int lib_SSLInit(LIB_SSL_CONTEXT* ssl_ctx, int stream_fd, bool is_server,
+                const uint8_t* psk, size_t psk_size,
+                int (*pal_recv_cb)(int fd, void* buf, uint32_t len),
+                int (*pal_send_cb)(int fd, const void* buf, uint32_t len)) {
+    int ret;
+
+    memset(ssl_ctx, 0, sizeof(*ssl_ctx));
+
+    ssl_ctx->ciphersuites[0] = MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256;
+    memset(&ssl_ctx->ciphersuites[1], 0, sizeof(ssl_ctx->ciphersuites[1]));
+
+    ssl_ctx->pal_recv_cb = pal_recv_cb;
+    ssl_ctx->pal_send_cb = pal_send_cb;
+    ssl_ctx->stream_fd   = stream_fd;
+
+    mbedtls_entropy_init(&ssl_ctx->entropy);
+    mbedtls_ctr_drbg_init(&ssl_ctx->ctr_drbg);
+    mbedtls_ssl_config_init(&ssl_ctx->conf);
+    mbedtls_ssl_init(&ssl_ctx->ssl);
+
+    ret = mbedtls_ctr_drbg_seed(&ssl_ctx->ctr_drbg, mbedtls_entropy_func, &ssl_ctx->entropy, NULL, 0);
+    if (ret != 0)
+        return -PAL_ERROR_DENIED;
+
+    ret = mbedtls_ssl_config_defaults(&ssl_ctx->conf,
+                                      is_server ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
+                                      MBEDTLS_SSL_TRANSPORT_STREAM,
+                                      MBEDTLS_SSL_PRESET_DEFAULT);
+    if (ret != 0)
+        return -PAL_ERROR_DENIED;
+
+    mbedtls_ssl_conf_rng(&ssl_ctx->conf, mbedtls_ctr_drbg_random, &ssl_ctx->ctr_drbg);
+    mbedtls_ssl_conf_ciphersuites(&ssl_ctx->conf, ssl_ctx->ciphersuites);
+
+    const unsigned char psk_identity[] = "dummy";
+    ret = mbedtls_ssl_conf_psk(&ssl_ctx->conf, psk, psk_size, psk_identity, sizeof(psk_identity) - 1);
+    if (ret != 0)
+        return -PAL_ERROR_DENIED;
+
+    ret = mbedtls_ssl_setup(&ssl_ctx->ssl, &ssl_ctx->conf);
+    if (ret != 0)
+        return -PAL_ERROR_DENIED;
+
+    mbedtls_ssl_set_bio(&ssl_ctx->ssl, ssl_ctx, send_cb, recv_cb, NULL);
+
+    while ((ret = mbedtls_ssl_handshake(&ssl_ctx->ssl)) != 0) {
+        if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
+            break;
+    }
+    if (ret != 0)
+        return -PAL_ERROR_DENIED;
+
+    return 0;
+}
+
+int lib_SSLFree(LIB_SSL_CONTEXT* ssl_ctx) {
+    mbedtls_ssl_free(&ssl_ctx->ssl);
+    mbedtls_ssl_config_free(&ssl_ctx->conf);
+    mbedtls_ctr_drbg_free(&ssl_ctx->ctr_drbg);
+    mbedtls_entropy_free(&ssl_ctx->entropy);
+    return 0;
+}
+
+int lib_SSLRead(LIB_SSL_CONTEXT* ssl_ctx, uint8_t* buf, size_t len) {
+    int ret = mbedtls_ssl_read(&ssl_ctx->ssl, buf, len);
+    if (ret <= 0)
+       return -PAL_ERROR_DENIED;
+    return ret;
+}
+
+int lib_SSLWrite(LIB_SSL_CONTEXT* ssl_ctx, const uint8_t* buf, size_t len) {
+    int ret = mbedtls_ssl_write(&ssl_ctx->ssl, buf, len);
+    if (ret <= 0)
+       return -PAL_ERROR_DENIED;
+    return ret;
+}

+ 17 - 4
Pal/lib/crypto/config.h

@@ -19,24 +19,37 @@
 #ifndef MBEDTLS_CONFIG_H
 #define MBEDTLS_CONFIG_H
 
-#define MBEDTLS_AES_C
 #define MBEDTLS_AESNI_C
+#define MBEDTLS_AES_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_BASE64_C
 #define MBEDTLS_BIGNUM_C
 #define MBEDTLS_CIPHER_C
 #define MBEDTLS_CMAC_C
+#define MBEDTLS_CTR_DRBG_C
 #define MBEDTLS_DHM_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_GCM_C
 #define MBEDTLS_GENPRIME
 #define MBEDTLS_HAVE_ASM
 #define MBEDTLS_HAVE_X86_64
+#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
 #define MBEDTLS_MD_C
+#define MBEDTLS_NET_C
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#define MBEDTLS_OID_C
 #define MBEDTLS_PKCS1
 #define MBEDTLS_PKCS1_V15
-#define MBEDTLS_OID_C
 #define MBEDTLS_PLATFORM_C
 #define MBEDTLS_RSA_C
 #define MBEDTLS_SHA256_C
-#define MBEDTLS_BASE64_C
-#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256
+#define MBEDTLS_SSL_CLI_C
+#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
 
 #define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
 

+ 23 - 0
Pal/lib/pal_crypto.h

@@ -51,6 +51,21 @@ typedef struct {
     mbedtls_cipher_type_t cipher;
     mbedtls_cipher_context_t ctx;
 } LIB_AESCMAC_CONTEXT;
+
+#include "crypto/mbedtls/include/mbedtls/ctr_drbg.h"
+#include "crypto/mbedtls/include/mbedtls/entropy.h"
+#include "crypto/mbedtls/include/mbedtls/ssl.h"
+typedef struct {
+    mbedtls_entropy_context entropy;
+    mbedtls_ctr_drbg_context ctr_drbg;
+    mbedtls_ssl_config conf;
+    mbedtls_ssl_context ssl;
+    int ciphersuites[2];  /* [0] is actual ciphersuite, [1] must be 0 to indicate end of array */
+    int (*pal_recv_cb)(int fd, void* buf, uint32_t len);
+    int (*pal_send_cb)(int fd, const void* buf, uint32_t len);
+    int stream_fd;
+} LIB_SSL_CONTEXT;
+
 #endif /* CRYPTO_USE_MBEDTLS */
 
 #ifndef CRYPTO_PROVIDER_SPECIFIED
@@ -142,4 +157,12 @@ int lib_ASN1GetSerial(uint8_t** ptr, const uint8_t* end, enum asn1_tag* tag, boo
 int lib_ASN1GetBitstring(uint8_t** ptr, const uint8_t* end, uint8_t** str, size_t* len);
 int lib_ASN1GetLargeNumberLength(uint8_t** ptr, const uint8_t* end, size_t* len);
 
+/* SSL/TLS */
+int lib_SSLInit(LIB_SSL_CONTEXT* ssl_ctx, int stream_fd, bool is_server,
+                const uint8_t* psk, size_t psk_size,
+                int (*pal_recv_cb)(int fd, void* buf, uint32_t len),
+                int (*pal_send_cb)(int fd, const void* buf, uint32_t len));
+int lib_SSLFree(LIB_SSL_CONTEXT* ssl_ctx);
+int lib_SSLRead(LIB_SSL_CONTEXT* ssl_ctx, uint8_t* buf, size_t len);
+int lib_SSLWrite(LIB_SSL_CONTEXT* ssl_ctx, const uint8_t* buf, size_t len);
 #endif

+ 47 - 8
Pal/src/host/Linux-SGX/db_process.c

@@ -272,6 +272,7 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri, const char ** args)
     child->process.cargo       = cargo_fd;
     child->process.pid         = child_pid;
     child->process.nonblocking = PAL_FALSE;
+    child->process.ssl_ctx     = NULL;
 
     ret = _DkStreamKeyExchange(child, &child->process.session_key);
     if (ret < 0)
@@ -287,6 +288,11 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri, const char ** args)
     if (ret < 0)
         goto failed;
 
+    ret = _DkStreamSecureInit(child, /*is_server=*/true, &child->process.session_key,
+                              (LIB_SSL_CONTEXT**)&child->process.ssl_ctx);
+    if (ret < 0)
+        goto failed;
+
     *handle = child;
     return 0;
 
@@ -317,10 +323,11 @@ int init_child_process (PAL_HANDLE * parent_handle)
     SET_HANDLE_TYPE(parent, process);
     HANDLE_HDR(parent)->flags |= RFD(0)|WFD(0)|RFD(1)|WFD(1);
 
-    parent->process.stream     = pal_sec.stream_fd;
-    parent->process.cargo      = pal_sec.cargo_fd;
-    parent->process.pid        = pal_sec.ppid;
+    parent->process.stream      = pal_sec.stream_fd;
+    parent->process.cargo       = pal_sec.cargo_fd;
+    parent->process.pid         = pal_sec.ppid;
     parent->process.nonblocking = PAL_FALSE;
+    parent->process.ssl_ctx     = NULL;
 
     int ret = _DkStreamKeyExchange(parent, &parent->process.session_key);
     if (ret < 0)
@@ -336,6 +343,11 @@ int init_child_process (PAL_HANDLE * parent_handle)
     if (ret < 0)
         return ret;
 
+    ret = _DkStreamSecureInit(parent, /*is_server=*/false, &parent->process.session_key,
+                              (LIB_SSL_CONTEXT**)&parent->process.ssl_ctx);
+    if (ret < 0)
+        return ret;
+
     *parent_handle = parent;
     return 0;
 }
@@ -364,8 +376,15 @@ static int64_t proc_read (PAL_HANDLE handle, uint64_t offset, uint64_t count,
     if (count >= (1ULL << (sizeof(unsigned int) * 8)))
         return -PAL_ERROR_INVAL;
 
-    int bytes = ocall_read(handle->process.stream, buffer, count);
-    return IS_ERR(bytes) ? unix_to_pal_error(ERRNO(bytes)) : bytes;
+    int bytes;
+    if (handle->process.ssl_ctx) {
+        bytes = _DkStreamSecureRead(handle->process.ssl_ctx, buffer, count);
+    } else {
+        bytes = ocall_read(handle->process.stream, buffer, count);
+        bytes = IS_ERR(bytes) ? unix_to_pal_error(ERRNO(bytes)) : bytes;
+    }
+
+    return bytes;
 }
 
 static int64_t proc_write (PAL_HANDLE handle, uint64_t offset, uint64_t count,
@@ -377,9 +396,13 @@ static int64_t proc_write (PAL_HANDLE handle, uint64_t offset, uint64_t count,
     if (count >= (1ULL << (sizeof(unsigned int) * 8)))
         return -PAL_ERROR_INVAL;
 
-    int bytes = ocall_write(handle->process.stream, buffer, count);
-    if (IS_ERR(bytes))
-        return unix_to_pal_error(ERRNO(bytes));
+    int bytes;
+    if (handle->process.ssl_ctx) {
+        bytes = _DkStreamSecureWrite(handle->process.ssl_ctx, buffer, count);
+    } else {
+        bytes = ocall_write(handle->process.stream, buffer, count);
+        bytes = IS_ERR(bytes) ? unix_to_pal_error(ERRNO(bytes)) : bytes;
+    }
 
     return bytes;
 }
@@ -396,6 +419,11 @@ static int proc_close (PAL_HANDLE handle)
         handle->process.cargo = PAL_IDX_POISON;
     }
 
+    if (handle->process.ssl_ctx) {
+        _DkStreamSecureFree((LIB_SSL_CONTEXT*)handle->process.ssl_ctx);
+        handle->process.ssl_ctx = NULL;
+    }
+
     return 0;
 }
 
@@ -434,6 +462,7 @@ static int proc_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
     attr->handle_type  = HANDLE_HDR(handle)->type;
     attr->nonblocking  = handle->process.nonblocking;
     attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
+    attr->secure = handle->process.ssl_ctx ? PAL_TRUE : PAL_FALSE;
 
     /* get number of bytes available for reading */
     ret = ocall_fionread(handle->process.stream);
@@ -467,6 +496,16 @@ static int proc_attrsetbyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
         handle->process.nonblocking = attr->nonblocking;
     }
 
+    if (!attr->secure && handle->process.ssl_ctx) {
+        /* remove TLS protection from process.stream */
+        _DkStreamSecureFree((LIB_SSL_CONTEXT*)handle->process.ssl_ctx);
+        handle->process.ssl_ctx = NULL;
+    } else if (attr->secure && !handle->process.ssl_ctx) {
+        /* adding TLS protection for process.stream is not yet implemented */
+        SGX_DBG(DBG_E, "Securing a non-secure process handle is not supported!\n");
+        return -PAL_ERROR_NOTSUPPORT;
+    }
+
     return 0;
 }
 

+ 15 - 0
Pal/src/host/Linux-SGX/db_streams.c

@@ -151,6 +151,12 @@ int handle_serialize(PAL_HANDLE handle, void** data) {
     if (dsz2)
         memcpy(buffer + hdlsz + dsz1, d2, dsz2);
 
+    if (PAL_GET_TYPE(handle) == pal_type_process) {
+        /* must not leak session key and SSL context -> zero them */
+        memset(buffer + offsetof(struct pal_handle, process.session_key), 0, sizeof(handle->process.session_key));
+        memset(buffer + offsetof(struct pal_handle, process.ssl_ctx), 0, sizeof(handle->process.ssl_ctx));
+    }
+
     *data = buffer;
     return hdlsz + dsz1 + dsz2;
 }
@@ -243,6 +249,15 @@ int handle_deserialize(PAL_HANDLE* handle, const void* data, int size) {
     if (!hdl)
         return ret;
 
+    if (PAL_GET_TYPE(hdl) == pal_type_process) {
+        /* must not have leaked session key and SSL context, verify */
+        static PAL_SESSION_KEY zero_session_key;
+        __UNUSED(zero_session_key); /* otherwise GCC with Release build complains */
+
+        assert(memcmp(hdl->process.session_key, zero_session_key, sizeof(zero_session_key)) == 0);
+        assert(hdl->process.ssl_ctx == 0);
+    }
+
     *handle = hdl;
     return 0;
 }

+ 41 - 0
Pal/src/host/Linux-SGX/enclave_framework.c

@@ -1274,6 +1274,47 @@ out:
     return ret;
 }
 
+int _DkStreamSecureInit(PAL_HANDLE stream, bool is_server, PAL_SESSION_KEY* session_key,
+                        LIB_SSL_CONTEXT** out_ssl_ctx) {
+    int stream_fd;
+
+    if (IS_HANDLE_TYPE(stream, process))
+        stream_fd = stream->process.stream;
+    else
+        return -PAL_ERROR_BADHANDLE;
+
+
+    LIB_SSL_CONTEXT* ssl_ctx = malloc(sizeof(*ssl_ctx));
+    if (!ssl_ctx)
+        return -PAL_ERROR_NOMEM;
+
+    int ret = lib_SSLInit(ssl_ctx, stream_fd, is_server,
+                          (const uint8_t*)session_key, sizeof(*session_key),
+                          ocall_read, ocall_write);
+
+    if (ret != 0) {
+        free(ssl_ctx);
+        return ret;
+    }
+
+    *out_ssl_ctx = ssl_ctx;
+    return 0;
+}
+
+int _DkStreamSecureFree(LIB_SSL_CONTEXT* ssl_ctx) {
+    lib_SSLFree(ssl_ctx);
+    free(ssl_ctx);
+    return 0;
+}
+
+int _DkStreamSecureRead(LIB_SSL_CONTEXT* ssl_ctx, uint8_t* buf, size_t len) {
+    return lib_SSLRead(ssl_ctx, buf, len);
+}
+
+int _DkStreamSecureWrite(LIB_SSL_CONTEXT* ssl_ctx, const uint8_t* buf, size_t len) {
+    return lib_SSLWrite(ssl_ctx, buf, len);
+}
+
 /*
  * Restore an sgx_cpu_context_t as generated by .Lhandle_exception. Execution will
  * continue as specified by the rip in the context.

+ 1 - 0
Pal/src/host/Linux-SGX/pal_host.h

@@ -150,6 +150,7 @@ typedef struct pal_handle
             PAL_IDX pid;
             PAL_BOL nonblocking;
             PAL_SESSION_KEY session_key;
+            void* ssl_ctx;
         } process;
 
         struct pal_handle_thread thread;

+ 12 - 4
Pal/src/host/Linux-SGX/pal_linux.h

@@ -17,16 +17,18 @@
 #ifndef PAL_LINUX_H
 #define PAL_LINUX_H
 
+#include "api.h"
+#include "pal.h"
+#include "pal_crypto.h"
 #include "pal_defs.h"
 #include "pal_linux_defs.h"
-#include "pal.h"
-#include "api.h"
 
 #include "linux_types.h"
-#include "sgx_arch.h"
-#include "sgx_tls.h"
 #include "sgx_api.h"
+#include "sgx_arch.h"
 #include "sgx_attest.h"
+#include "sgx_tls.h"
+
 #include "enclave_ocalls.h"
 
 #include <linux/mman.h>
@@ -178,6 +180,12 @@ int _DkStreamReportRequest(PAL_HANDLE stream, sgx_sign_data_t* data,
 int _DkStreamReportRespond(PAL_HANDLE stream, sgx_sign_data_t* data,
                            check_mr_enclave_t check_mr_enclave);
 
+int _DkStreamSecureInit(PAL_HANDLE stream, bool is_server, PAL_SESSION_KEY* session_key,
+                        LIB_SSL_CONTEXT** out_ssl_ctx);
+int _DkStreamSecureFree(LIB_SSL_CONTEXT* ssl_ctx);
+int _DkStreamSecureRead(LIB_SSL_CONTEXT* ssl_ctx, uint8_t* buf, size_t len);
+int _DkStreamSecureWrite(LIB_SSL_CONTEXT* ssl_ctx, const uint8_t* buf, size_t len);
+
 #include "sgx_arch.h"
 
 #define PAL_ENCLAVE_INITIALIZED     0x0001ULL

+ 1 - 0
Pal/src/pal.h

@@ -369,6 +369,7 @@ typedef struct {
     PAL_BOL disconnected;
     PAL_BOL nonblocking;
     PAL_BOL readable, writable, runnable;
+    PAL_BOL secure;
     PAL_FLG share_flags;
     PAL_NUM pending_size;
     PAL_IDX no_of_fds;