Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate TLS credentials for user space #749

Open
wants to merge 3 commits into
base: oe_port
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 247 additions & 0 deletions src/enclave/enclave_cert.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
#include "enclave/enclave_cert.h"
#include <mbedtls/x509.h>
#include <mbedtls/x509_crt.h>
#include <openenclave/enclave.h>
#include <openenclave/attestation/attester.h>
#include <openenclave/attestation/sgx/eeid_plugin.h>
#include "openenclave/corelibc/oemalloc.h"
#include "openenclave/corelibc/oestring.h"

oe_result_t oe_sgx_eeid_attester_initialize(void);

static oe_result_t _generate_key_pair(
uint8_t** public_key_out,
size_t* public_key_size_out,
uint8_t** private_key_out,
size_t* private_key_size_out)
{
oe_result_t result = OE_FAILURE;
oe_result_t ret;
oe_asymmetric_key_params_t params;
char user_data[] = "__USER_DATA__";
size_t user_data_size = sizeof(user_data) - 1;
uint8_t* public_key = NULL;
size_t public_key_size = 0;
uint8_t* private_key = NULL;
size_t private_key_size = 0;

*public_key_out = NULL;
*public_key_size_out = 0;
*private_key_out = NULL;
*private_key_size_out = 0;

memset(&params, 0, sizeof(params));
params.type = OE_ASYMMETRIC_KEY_EC_SECP256P1;
params.format = OE_ASYMMETRIC_KEY_PEM;
params.user_data = user_data;
params.user_data_size = user_data_size;

if ((ret = oe_get_public_key_by_policy(
OE_SEAL_POLICY_UNIQUE,
&params,
&public_key,
&public_key_size,
NULL,
NULL)) != OE_OK)
{
result = ret;
goto done;
}

if ((ret = oe_get_private_key_by_policy(
OE_SEAL_POLICY_UNIQUE,
&params,
&private_key,
&private_key_size,
NULL,
NULL)) != OE_OK)
{
result = ret;
goto done;
}

*private_key_out = private_key;
*private_key_size_out = private_key_size;
private_key = NULL;

*public_key_out = public_key;
*public_key_size_out = public_key_size;
public_key = NULL;

result = OE_OK;

done:

if (private_key)
oe_free(private_key);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should use oe_free_key instead


if (public_key)
oe_free(public_key);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same


return result;
}

static oe_result_t _generate_cert_and_private_key(
const char* common_name,
uint8_t** cert_out,
size_t* cert_size_out,
uint8_t** private_key_out,
size_t* private_key_size_out)
{
oe_result_t result = OE_FAILURE;
oe_result_t ret;
uint8_t* cert = NULL;
size_t cert_size;
uint8_t* private_key = NULL;
size_t private_key_size;
uint8_t* public_key = NULL;
size_t public_key_size;
const oe_uuid_t format = {OE_FORMAT_UUID_SGX_EEID_ECDSA_P256};

*cert_out = NULL;
*cert_size_out = 0;
*private_key_out = NULL;
*private_key_size_out = 0;

if ((ret = _generate_key_pair(
&public_key, &public_key_size, &private_key, &private_key_size)) !=
OE_OK)
{
result = ret;
goto done;
}

// Initialize built-in OE attesters and the eeid attester.
oe_attester_initialize();
oe_sgx_eeid_attester_initialize();

if ((ret = oe_get_attestation_certificate_with_evidence(
&format,
(unsigned char*)common_name,
private_key,
private_key_size,
public_key,
public_key_size,
&cert,
&cert_size)) != OE_OK)
{
result = ret;
goto done;
}

*private_key_out = private_key;
*private_key_size_out = private_key_size;
private_key = NULL;

*cert_out = cert;
*cert_size_out = cert_size;
cert = NULL;

result = OE_OK;

done:

if (private_key)
oe_free_key(private_key, private_key_size, NULL, 0);

if (public_key)
oe_free_key(public_key, public_key_size, NULL, 0);

if (cert)
oe_free_attestation_certificate(cert);

return result;
}

int enclave_generate_tls_credentials(
uint8_t** cert_out,
size_t* cert_size_out,
uint8_t** private_key_out,
size_t* private_key_size_out)
{
int ret = -1;
uint8_t* cert = NULL;
size_t cert_size;
uint8_t* private_key = NULL;
size_t private_key_size;
const char* common_name = "CN=Open Enclave SDK,O=OESDK TLS,C=US";

if (cert_out)
*cert_out = NULL;

if (cert_size_out)
*cert_size_out = 0;

if (private_key_out)
*private_key_out = NULL;

if (private_key_size_out)
*private_key_size_out = 0;

if (!cert_out || !cert_size_out || !private_key_out ||
!private_key_size_out)
{
goto done;
}

/* Generate the attested certificate and private key */
if (_generate_cert_and_private_key(
common_name, &cert, &cert_size, &private_key, &private_key_size) !=
OE_OK)
{
goto done;
}

#if DEBUG
/* Verify that the certificate can be parsed as DER */
{
mbedtls_x509_crt crt;
mbedtls_x509_crt_init(&crt);

if (mbedtls_x509_crt_parse_der(&crt, cert, cert_size) != 0)
{
mbedtls_x509_crt_free(&crt);
goto done;
}

mbedtls_x509_crt_free(&crt);
}

/* Verify that the private key can be parsed as PEM */
{
mbedtls_pk_context pk;
mbedtls_pk_init(&pk);

if (mbedtls_pk_parse_key(&pk, private_key, private_key_size, NULL, 0) !=
0)
{
mbedtls_pk_free(&pk);
goto done;
}

mbedtls_pk_free(&pk);
}
#endif

*cert_out = cert;
cert = NULL;
*cert_size_out = cert_size;
*private_key_out = private_key;
private_key = NULL;
*private_key_size_out = private_key_size;

ret = 0;

done:

if (cert)
oe_free_key(cert, cert_size, NULL, 0);

if (private_key)
oe_free_key(private_key, private_key_size, NULL, 0);

if (cert)
oe_free_attestation_certificate(cert);

return ret;
}
42 changes: 42 additions & 0 deletions src/enclave/enclave_cert_user.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "enclave/enclave_cert_user.h"
#include <stdio.h>
#include <stdlib.h>

// This function and its caller should be moved to

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to wait, we can do this now, can't we?

// user space once we have a clean separation.
int sgxlkl_write_tls_credentials(
uint8_t* cert,
size_t cert_size,
uint8_t* private_key,
size_t private_key_size,
const char* cert_path,
const char* pkey_path)
{
int ret = -1;

FILE* os1 = NULL;
FILE* os2 = NULL;

if (!(os1 = fopen(cert_path, "wb")))
goto done;

if (!(os2 = fopen(pkey_path, "wb")))
goto done;

if (fwrite(cert, 1, cert_size, os1) != cert_size)
goto done;

if (fwrite(private_key, 1, private_key_size, os2) != private_key_size)
goto done;

ret = 0;

done:
if (os1)
fclose(os1);

if (os2)
fclose(os2);

return ret;
}
30 changes: 30 additions & 0 deletions src/enclave/enclave_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "openenclave/corelibc/oemalloc.h"
#include "openenclave/corelibc/oestring.h"

#include "enclave/enclave_cert.h"
#include "enclave/enclave_cert_user.h"
#include "enclave/enclave_mem.h"
#include "enclave/enclave_oe.h"
#include "enclave/enclave_util.h"
Expand All @@ -13,6 +15,9 @@
#include "enclave/wireguard_util.h"
#include "shared/env.h"

#define SGXLKL_TLS_CERT_PATH "/run/sgxlkl_cert.der"
#define SGXLKL_TLS_PRIVATE_KEY_PATH "/run/sgxlkl_private_key.pem"

extern struct mpmcq __scheduler_queue;

_Noreturn void __dls3(elf64_stack_t* conf, void* tos);
Expand Down Expand Up @@ -90,6 +95,11 @@ static void init_wireguard()

static int startmain(void* args)
{
uint8_t* cert;
size_t cert_size;
uint8_t* private_key;
size_t private_key_size;

__libc_start_init();
a_barrier();

Expand All @@ -107,6 +117,26 @@ static int startmain(void* args)
init_wireguard();
find_and_mount_disks();

/* Generate TLS certificate and private key and save them to files.
* Once we have kernel/user separation, pass the cert and private
* key to user space through the stack, and move
* sgxlkl_write_tls_credentials to user space.
*/

if (!sgxlkl_in_sw_debug_mode())
{
enclave_generate_tls_credentials(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a layering problem here; we cant call oe_* at this point in time anymore. If I'm not mistaken, the consensus was that we would generate this kind of data earlier and then pass it to the application via auxv. This would also mean that applications could pick it up directly from memory instead of a file. The current implementation would also fail on a read-only root file system. (CC @davidchisnall)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this routine is a part of the nominal userspace and will be refactored soon to make that distinction more explicit. We may not call OE APIs from here.

More generally, given that we've had so many meetings discussing the design and the mechanism for passing this via the ELF aux vector, I'd like to understand why a different approach is being pursued here.

&cert, &cert_size, &private_key, &private_key_size);

sgxlkl_write_tls_credentials(
cert,
cert_size,
private_key,
private_key_size,
SGXLKL_TLS_CERT_PATH,
SGXLKL_TLS_PRIVATE_KEY_PATH);
}

/* Launch stage 3 dynamic linker, passing in top of stack to overwrite.
* The dynamic linker will then load the application proper; here goes! */
__dls3(&sgxlkl_enclave_state.elf64_stack, __builtin_frame_address(0));
Expand Down
13 changes: 13 additions & 0 deletions src/include/enclave/enclave_cert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef _ENCLAVE_CERT_H
#define _ENCLAVE_CERT_H

#include <stddef.h>
#include <stdint.h>

int enclave_generate_tls_credentials(
uint8_t** cert_out,
size_t* cert_size_out,
uint8_t** private_key_out,
size_t* private_key_size_out);

#endif /* _ENCLAVE_CERT_H */
15 changes: 15 additions & 0 deletions src/include/enclave/enclave_cert_user.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef _ENCLAVE_CERT_USER_H
#define _ENCLAVE_CERT_USER_H

#include <stddef.h>
#include <stdint.h>

int sgxlkl_write_tls_credentials(
uint8_t* cert,
size_t cert_size,
uint8_t* private_key,
size_t private_key_size,
const char* cert_path,
const char* pkey_path);

#endif /* _ENCLAVE_CERT_USER_H */