├── whitepaper.pdf ├── ecdsa-sample-data ├── ecdsa-ratls.der ├── pckcert-rsa3072.der ├── quote-ppid-clear.dat ├── quote-ppid-rsa3072.dat ├── qeIdentity.json ├── intermediateCaCrl.pem ├── rootCaCrl.pem ├── real │ └── trustedRootCaCert.pem ├── trustedRootCaCert.pem ├── pckcert-rsa3072.pem ├── pckCert.pem ├── tcbInfo.json ├── tcbSignChain.pem └── pckSignChain.pem ├── wolfssl-ra.h ├── mbedtls-ra-attester.h ├── sgxlkl ├── ratls │ ├── buildenv.sh │ └── Makefile ├── https-server │ ├── buildenv.sh │ ├── Makefile │ └── https-server.py ├── ldpreload.c └── Makefile ├── ra-attester_private.h ├── wolfssl-ra-attester.h ├── curl_helper.h ├── ias-ra.h ├── NOTICE ├── ecdsa-ra-attester.h ├── sgx_report.S ├── 00-wolfssl-allow-large-certificate-request-msg.patch ├── LICENSE ├── 00-graphene-driver-dcap.patch ├── ra_tls.edl ├── graphene-sgx-linux-driver-2.1.patch ├── apps └── secret-provisioning-example │ ├── show-secrets.c │ ├── show-secrets.manifest │ ├── redis-server.manifest │ ├── README.md │ ├── redis-server-grab-secret.c │ ├── show-secrets-grab-secret.c │ ├── Makefile │ └── README.html ├── ra.c ├── tests ├── 00_sgxsdk_server_client.py ├── regression.py ├── ra-challenger.c ├── 00_ecdsa_attester_challenger.py ├── ra-attester.c ├── 00_attester_challenger.py ├── 00_sgxlkl_server_client.py ├── 00_graphene_server_client.py └── 00_secrect_provisioning_example.py ├── mbedtls-enlarge-cert-write-buffer.patch ├── ra-challenger.h ├── wolfssl-ra.c ├── .gitignore ├── ra_private.h ├── sgxsdk-ra-attester_t.c ├── ra-attester.h ├── .gitlab-ci.yml ├── sgxsdk-ra-attester_u.c ├── container-build.sh ├── ssl-server.manifest ├── ra-challenger_private.h ├── ra_tls_options.c.sh ├── ra-attester.manifest ├── ra.h ├── ratls-wolfssl.mk ├── Dockerfile-ubuntu16.04 ├── Dockerfile-ubuntu18.04 ├── ecdsa-ra-attester.c ├── README-ECDSA.md ├── openssl-client.c ├── mbedtls-ssl-server.patch ├── README-ECDSA.html ├── openssl-ra-attester.c ├── 00-graphene-flexible-launch-control.patch ├── mbedtls-client.patch ├── mbedtls-ra-challenger.c ├── ias_sign_ca_cert.c ├── ra-challenger.c ├── ias-ra.c ├── README.md └── mbedtls-ra-attester.c /whitepaper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-security-research/sgx-ra-tls/HEAD/whitepaper.pdf -------------------------------------------------------------------------------- /ecdsa-sample-data/ecdsa-ratls.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-security-research/sgx-ra-tls/HEAD/ecdsa-sample-data/ecdsa-ratls.der -------------------------------------------------------------------------------- /ecdsa-sample-data/pckcert-rsa3072.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-security-research/sgx-ra-tls/HEAD/ecdsa-sample-data/pckcert-rsa3072.der -------------------------------------------------------------------------------- /ecdsa-sample-data/quote-ppid-clear.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-security-research/sgx-ra-tls/HEAD/ecdsa-sample-data/quote-ppid-clear.dat -------------------------------------------------------------------------------- /ecdsa-sample-data/quote-ppid-rsa3072.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-security-research/sgx-ra-tls/HEAD/ecdsa-sample-data/quote-ppid-rsa3072.dat -------------------------------------------------------------------------------- /wolfssl-ra.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void sha256_rsa_pubkey 4 | ( 5 | unsigned char hash[SHA256_DIGEST_SIZE], 6 | RsaKey* key 7 | ); 8 | -------------------------------------------------------------------------------- /mbedtls-ra-attester.h: -------------------------------------------------------------------------------- 1 | #include "ra-attester.h" 2 | 3 | void mbedtls_create_key_and_x509 4 | ( 5 | mbedtls_pk_context* key, 6 | mbedtls_x509_crt* cert, 7 | const struct ra_tls_options* opts 8 | ); 9 | -------------------------------------------------------------------------------- /sgxlkl/ratls/buildenv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ex 4 | 5 | PATH=/usr/sbin:/sbin:/usr/bin:/bin 6 | 7 | cd /home 8 | echo "http://dl-cdn.alpinelinux.org/alpine/v3.6/community" >> /etc/apk/repositories 9 | apk update 10 | apk add ca-certificates 11 | -------------------------------------------------------------------------------- /ra-attester_private.h: -------------------------------------------------------------------------------- 1 | #ifndef __RA_ATTESTER_PRIVATE_H__ 2 | #define __RA_ATTESTER_PRIVATE_H__ 3 | 4 | void create_report 5 | ( 6 | sgx_target_info_t* target_info, 7 | const sgx_report_data_t* report_data, 8 | sgx_report_t* report 9 | ); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /sgxlkl/https-server/buildenv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ex 4 | 5 | PATH=/usr/sbin:/sbin:/usr/bin:/bin 6 | 7 | cd /home 8 | echo "http://dl-cdn.alpinelinux.org/alpine/v3.6/community" >> /etc/apk/repositories 9 | apk update 10 | apk add python 11 | apk add ca-certificates 12 | -------------------------------------------------------------------------------- /wolfssl-ra-attester.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void wolfssl_create_key_and_x509 5 | ( 6 | uint8_t* der_key, 7 | int* der_key_len, 8 | uint8_t* der_cert, 9 | int* der_cert_len, 10 | const struct ra_tls_options* opts 11 | ); 12 | -------------------------------------------------------------------------------- /curl_helper.h: -------------------------------------------------------------------------------- 1 | struct buffer_and_size { 2 | char* data; 3 | size_t len; 4 | }; 5 | 6 | void http_get 7 | ( 8 | CURL* curl, 9 | const char* url, 10 | struct buffer_and_size* header, 11 | struct buffer_and_size* body, 12 | struct curl_slist* request_headers, 13 | char* request_body 14 | ); 15 | -------------------------------------------------------------------------------- /ias-ra.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | 5 | void obtain_attestation_verification_report( 6 | const sgx_quote_t* quote, 7 | const uint32_t quote_size, 8 | const struct ra_tls_options* opts, 9 | attestation_verification_report_t* attn_report 10 | ); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Integrating Intel SGX Remote Attestation with Transport Layer Security 2 | Copyright 2017 Intel(R) Corporation 3 | 4 | This software was developed at Intel Labs 5 | (https://www.intel.com/intellabs). This software is a research proof 6 | of concept to demonstrate the integration of Intel SGX Remote 7 | Attestation with the Transport Layer Security protocol. 8 | 9 | This software not intended for production use. -------------------------------------------------------------------------------- /ecdsa-ra-attester.h: -------------------------------------------------------------------------------- 1 | #ifndef __ECDSA_RA_ATTESTER__ 2 | #define __ECDSA_RA_ATTESTER__ 3 | 4 | int connect_to_quote_service(void); 5 | 6 | void get_quote_from_quote_service 7 | ( 8 | int sockfd, 9 | const sgx_report_t* report, 10 | uint8_t* quote, 11 | uint32_t quote_len 12 | ); 13 | 14 | void get_target_info_from_quote_service 15 | ( 16 | int sockfd, 17 | sgx_target_info_t* target_info, 18 | uint32_t* quote_size 19 | ); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /sgx_report.S: -------------------------------------------------------------------------------- 1 | // Copied from Graphene-SGX. 2 | 3 | #define EREPORT 0 4 | 5 | /* 6 | * sgx_report: 7 | * Generate SGX hardware signed report. 8 | */ 9 | .global sgx_report 10 | .type sgx_report, @function 11 | 12 | sgx_report: 13 | .cfi_startproc 14 | 15 | push %rbx 16 | push %rcx 17 | mov %rdi, %rbx 18 | mov %rsi, %rcx 19 | mov $EREPORT, %rax 20 | ENCLU 21 | pop %rcx 22 | pop %rbx 23 | ret 24 | 25 | .cfi_endproc 26 | .size sgx_report, .-sgx_report 27 | -------------------------------------------------------------------------------- /00-wolfssl-allow-large-certificate-request-msg.patch: -------------------------------------------------------------------------------- 1 | diff --git a/wolfssl/internal.h b/wolfssl/internal.h 2 | index 9c77120..3c922dd 100644 3 | --- a/wolfssl/internal.h 4 | +++ b/wolfssl/internal.h 5 | @@ -1272,7 +1272,7 @@ enum Misc { 6 | 7 | /* max size of a handshake message, currently set to the certificate */ 8 | #ifndef MAX_HANDSHAKE_SZ 9 | - #define MAX_HANDSHAKE_SZ MAX_CERTIFICATE_SZ 10 | + #define MAX_HANDSHAKE_SZ ((MAX_CERTIFICATE_SZ) * 4) 11 | #endif 12 | 13 | #ifndef SESSION_TICKET_LEN 14 | -------------------------------------------------------------------------------- /ecdsa-sample-data/qeIdentity.json: -------------------------------------------------------------------------------- 1 | {"qeIdentity":{"version":1,"issueDate":"2018-08-22T12:00:00Z","nextUpdate":"2019-08-22T12:00:00Z","miscselect":"00000000","miscselectMask":"00000000","attributes":"00000000000000000000000000000000","attributesMask":"00000000000000000000000000000000","mrsigner":"0000000000000000000000000000000000000000000000000000000000000000","isvprodid":0,"isvsvn":0},"signature":"895d38107dfa252a8023e383d264fd194502cc3319d4fe8b276e801e304a3d5ae5d4693975c1958a63283ae63e0aacab9bc5885ca4e4b6a9d492f0b79572e790"} -------------------------------------------------------------------------------- /ecdsa-sample-data/intermediateCaCrl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIBLTCB0wIBATAKBggqhkjOPQQDAjBwMSIwIAYDVQQDDBlJbnRlbCBTR1ggUENL 3 | IFBsYXRmb3JtIENBMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEUMBIGA1UE 4 | BwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYDVQQGEwJVUxcNMTgwNDEz 5 | MDYyOTE2WhgPNDc1NjAzMDkwNzI5MTZaoDAwLjALBgNVHRQEBAICAcgwHwYDVR0j 6 | BBgwFoAU9NAFMTj5fxOq+D26KYv1M9bn3fEwCgYIKoZIzj0EAwIDSQAwRgIhAI4N 7 | 5ONjwGvLk8dFIGFk9QRwmrnaDGneUf/PG/HUFG0NAiEA9gU7Y4WUytsFUFCzaQaG 8 | DkzpBVW/P41zk08yUQPrjJM= 9 | -----END X509 CRL----- 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017, Intel(R) Corporation (http://www.intel.com) 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /00-graphene-driver-dcap.patch: -------------------------------------------------------------------------------- 1 | diff --git a/graphene-sgx.h b/graphene-sgx.h 2 | index ac15319..fe97ee9 100644 3 | --- a/graphene-sgx.h 4 | +++ b/graphene-sgx.h 5 | @@ -16,7 +16,9 @@ 6 | #define __packed __attribute__((packed)) 7 | #endif 8 | 9 | -#if SDK_DRIVER_VERSION >= KERNEL_VERSION(1, 9, 0) 10 | +#if SDK_DRIVER_VERSION >= KERNEL_VERSION(2, 4, 0) 11 | +#include "linux-sgx-driver/include/uapi/asm/sgx.h" 12 | +#elif SDK_DRIVER_VERSION >= KERNEL_VERSION(1, 9, 0) 13 | /* 14 | * isgx_user.h renamed as sgx_user.h in SGX driver 1.9: 15 | * https://github.com/intel/linux-sgx-driver/commit/45c139d4a824091b3923d5677ae8794e9d45abc0 16 | -------------------------------------------------------------------------------- /ra_tls.edl: -------------------------------------------------------------------------------- 1 | enclave { 2 | 3 | include "ra.h" 4 | include "ra-attester.h" 5 | include "sgx_report.h" 6 | 7 | trusted { 8 | public void dummy(void); 9 | }; 10 | 11 | untrusted { 12 | /* define OCALLs here. */ 13 | void ocall_sgx_init_quote([out] sgx_target_info_t* target_info); 14 | void ocall_remote_attestation([in] sgx_report_t* report, 15 | [in] const struct ra_tls_options* opts, 16 | [out] attestation_verification_report_t* attn_report 17 | ); 18 | }; 19 | }; 20 | -------------------------------------------------------------------------------- /ecdsa-sample-data/rootCaCrl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIBkDCCATYCAQEwCgYIKoZIzj0EAwIwaDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJv 3 | b3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50 4 | YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYTAlVTFw0xODA0MTMwNjI5MTZa 5 | GA80NzU2MDMwOTA3MjkxNlowajAmAgUA/v7++hgPNDEyMjAxMzEyMzAwMDBaMAww 6 | CgYDVR0VBAMKAQEwJwIGAN7eokRUGA80MTIyMDEzMTIzMDAwMFowDDAKBgNVHRUE 7 | AwoBAjAXAgQTU0VlGA80MTIyMDEzMTIzMDAwMFqgLzAtMAoGA1UdFAQDAgF7MB8G 8 | A1UdIwQYMBaAFBDhc3qmYD7k+H+jcVa2R0GXdPT2MAoGCCqGSM49BAMCA0gAMEUC 9 | IQCKE/sQgp9Y/9UOakIDq+jyF2tHsQumMw90AaLc4hXoIwIgNri6FXHE8KMwBgDw 10 | RtqFyBz88nNT22kLhQdYbF9ewcY= 11 | -----END X509 CRL----- 12 | -------------------------------------------------------------------------------- /graphene-sgx-linux-driver-2.1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Pal/src/host/Linux-SGX/sgx_framework.c b/Pal/src/host/Linux-SGX/sgx_framework.c 2 | index c4ea9f0..c7b6ff8 100644 3 | --- a/Pal/src/host/Linux-SGX/sgx_framework.c 4 | +++ b/Pal/src/host/Linux-SGX/sgx_framework.c 5 | @@ -345,7 +345,7 @@ int init_enclave(sgx_arch_secs_t * secs, 6 | error = "Invalid measurement"; break; 7 | case SGX_INVALID_SIGNATURE: 8 | error = "Invalid signature"; break; 9 | - case SGX_INVALID_LICENSE: 10 | + case SGX_INVALID_EINITTOKEN: 11 | error = "Invalid EINIT token"; break; 12 | case SGX_INVALID_CPUSVN: 13 | error = "Invalid CPU SVN"; break; 14 | -------------------------------------------------------------------------------- /apps/secret-provisioning-example/show-secrets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[], char *envp[]) 6 | { 7 | printf("------Show Command Line Arguments------\n"); 8 | printf("The number of arguments: %d\n", argc - 1); 9 | 10 | for(int i = 1; i < argc; i++) { 11 | printf("[%d] %s\n", i, (char *)argv[i]); 12 | } 13 | 14 | printf("------Show Environment Variables \"SECRET\"------\n"); 15 | const char* env_name = "SECRET="; 16 | int index = 0; 17 | while (envp[index]) { 18 | if (strncmp(env_name, envp[index], strlen(env_name)) == 0) { 19 | printf("%s\n", envp[index]); 20 | break; 21 | } 22 | ++index; 23 | } 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /ra.c: -------------------------------------------------------------------------------- 1 | /* Definitions common to attester and verifier. */ 2 | 3 | #include 4 | #include 5 | 6 | #define OID(N) {0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF8, 0x4D, 0x8A, 0x39, (N)} 7 | 8 | const uint8_t ias_response_body_oid[] = OID(0x02); 9 | const uint8_t ias_root_cert_oid[] = OID(0x03); 10 | const uint8_t ias_leaf_cert_oid[] = OID(0x04); 11 | const uint8_t ias_report_signature_oid[] = OID(0x05); 12 | 13 | const uint8_t quote_oid[] = OID(0x06); 14 | const uint8_t pck_crt_oid[] = OID(0x07); 15 | const uint8_t pck_sign_chain_oid[] = OID(0x08); 16 | const uint8_t tcb_info_oid[] = OID(0x09); 17 | const uint8_t tcb_sign_chain_oid[] = OID(0x0a); 18 | const uint8_t qe_identity_oid[] = OID(0x0b); 19 | const uint8_t root_ca_crl_oid[] = OID(0x0c); 20 | const uint8_t pck_crl_oid[] = OID(0x0d); 21 | 22 | const size_t ias_oid_len = sizeof(ias_response_body_oid); 23 | -------------------------------------------------------------------------------- /tests/00_sgxsdk_server_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | from subprocess import * 5 | from time import sleep 6 | from shlex import split 7 | import sys 8 | 9 | class SGXSDKTestCase(): 10 | def setup(self): 11 | pass 12 | def teardown(self): 13 | pass 14 | def main(self): 15 | for client in ['mbedtls-client', 'wolfssl-client', 'openssl-client -p 11111'] : 16 | server_process = None 17 | try: 18 | server_process = Popen('exec ./App -s', 19 | cwd='deps/wolfssl-examples/SGX_Linux', 20 | shell=True) 21 | sleep(5) 22 | 23 | # Verify server process started correctly. 24 | assert server_process.poll() == None 25 | 26 | check_call(split("./"+client)) 27 | finally: 28 | if server_process: 29 | server_process.terminate() 30 | -------------------------------------------------------------------------------- /mbedtls-enlarge-cert-write-buffer.patch: -------------------------------------------------------------------------------- 1 | diff --git a/library/x509write_crt.c b/library/x509write_crt.c 2 | index d1d9a22..41a1ee1 100644 3 | --- a/library/x509write_crt.c 4 | +++ b/library/x509write_crt.c 5 | @@ -302,7 +302,7 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, 6 | unsigned char *c, *c2; 7 | unsigned char hash[64]; 8 | unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; 9 | - unsigned char tmp_buf[2048]; 10 | + unsigned char tmp_buf[4*2048]; 11 | size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; 12 | size_t len = 0; 13 | mbedtls_pk_type_t pk_alg; 14 | @@ -436,7 +436,7 @@ int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, 15 | void *p_rng ) 16 | { 17 | int ret; 18 | - unsigned char output_buf[4096]; 19 | + unsigned char output_buf[2*4096]; 20 | size_t olen = 0; 21 | 22 | if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), 23 | -------------------------------------------------------------------------------- /tests/regression.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import glob 4 | import imp 5 | import os 6 | import sys 7 | 8 | def determine_testcases(): 9 | tcs = [] 10 | py_files = [] 11 | 12 | if len(sys.argv) > 1: 13 | py_files = sys.argv[1:] 14 | else: 15 | py_files = glob.glob('tests/[0-9]*.py') 16 | 17 | print(py_files) 18 | for f in py_files: 19 | modname = os.path.basename(f).replace('.py', '') 20 | mod = imp.load_source(modname, f) 21 | for attr in dir(mod): 22 | if 'TestCase' in attr: 23 | tcs.append([mod, attr]) 24 | 25 | return tcs 26 | 27 | def main(): 28 | 29 | for (mod, tc_class) in determine_testcases(): 30 | print('Executing '+mod.__name__+':'+tc_class) 31 | testcase = getattr(mod, tc_class)() 32 | testcase.setup() 33 | try: 34 | testcase.main() 35 | finally: 36 | testcase.teardown() 37 | 38 | if __name__ == '__main__': 39 | main() 40 | -------------------------------------------------------------------------------- /ecdsa-sample-data/real/trustedRootCaCert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICjjCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw 3 | aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv 4 | cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ 5 | BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDExMVoXDTMzMDUyMTEwNDExMFowaDEaMBgG 6 | A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 7 | aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT 8 | AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 9 | 1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB 10 | uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ 11 | MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 12 | ZWwuY29tL0ludGVsU0dYUm9vdENBLmNybDAdBgNVHQ4EFgQUImUM1lqdNInzg7SV 13 | Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI 14 | KoZIzj0EAwIDSAAwRQIgQQs/08rycdPauCFk8UPQXCMAlsloBe7NwaQGTcdpa0EC 15 | IQCUt8SGvxKmjpcM/z0WP9Dvo8h2k5du1iWDdBkAn+0iiA== 16 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /ecdsa-sample-data/trustedRootCaCert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICjjCCAjSgAwIBAgIUEOFzeqZgPuT4f6NxVrZHQZd09PYwCgYIKoZIzj0EAwIw 3 | aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv 4 | cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ 5 | BgNVBAYTAlVTMB4XDTE4MDQxMzA2MjkxNloXDTQ5MTIzMTIyNTk1OVowaDEaMBgG 6 | A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 7 | aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT 8 | AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuwQGsBa6R1otjvetm7mpwUSx 9 | 7TDvTcLLbW/Q/4auUXJpyjnkPya9dDiohaXbcj4bfphUWjWds+yiRhtI3nXj3aOB 10 | uzCBuDAfBgNVHSMEGDAWgBQQ4XN6pmA+5Ph/o3FWtkdBl3T09jBSBgNVHR8ESzBJ 11 | MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 12 | ZWwuY29tL0ludGVsU0dYUm9vdENBLmNybDAdBgNVHQ4EFgQUEOFzeqZgPuT4f6Nx 13 | VrZHQZd09PYwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI 14 | KoZIzj0EAwIDSAAwRQIhAOlL11bn1kkn1vPkEwBWR4WsZqxrxVRLK4QhFARZLlOs 15 | AiBo+AbagH8sCIgSu5WNjRBVG5UES4mOQbSJAL7mO8pDcA== 16 | -----END CERTIFICATE----- 17 | -------------------------------------------------------------------------------- /ra-challenger.h: -------------------------------------------------------------------------------- 1 | #ifndef _RA_CHALLENGER_H_ 2 | #define _RA_CHALLENGER_H_ 3 | 4 | #include 5 | 6 | /** 7 | * Extract an Intel SGX quote from an Intel Attestation Service (IAS) report. 8 | */ 9 | void get_quote_from_report 10 | ( 11 | const uint8_t* report /* in */, 12 | const int report_len /* in */, 13 | sgx_quote_t* quote 14 | ); 15 | 16 | /** 17 | * Extract an Intel SGX quote from a DER-encoded X.509 certificate. 18 | */ 19 | void get_quote_from_cert 20 | ( 21 | const uint8_t* der_crt, 22 | uint32_t der_crt_len, 23 | sgx_quote_t* q 24 | ); 25 | 26 | /** 27 | * Verify SGX-related X.509 extensions. 28 | * @return 0 if verification succeeds, 1 otherwise. 29 | */ 30 | int verify_sgx_cert_extensions 31 | ( 32 | uint8_t* der_crt, 33 | uint32_t der_crt_len 34 | ); 35 | 36 | /** 37 | * Pretty-print information of RA-TLS certificate to file descriptor. 38 | */ 39 | void dprintf_ratls_cert 40 | ( 41 | int fd, 42 | uint8_t* der_crt, 43 | uint32_t der_crt_len 44 | ); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /wolfssl-ra.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include "ra.h" 8 | #include "wolfssl-ra.h" 9 | 10 | void sha256_rsa_pubkey 11 | ( 12 | unsigned char hash[SHA256_DIGEST_SIZE], 13 | RsaKey* key 14 | ) 15 | { 16 | // Expect a 3072 bit RSA key. 17 | assert(key->n.used == 48 /* == 3072 / 8 / 8 */); 18 | 19 | uint8_t buf[1024]; 20 | /* SetRsaPublicKey() only exports n and e without wrapping them in 21 | additional ASN.1 (PKCS#1). */ 22 | int pub_rsa_key_der_len = SetRsaPublicKey(buf, key, sizeof(buf), 0); 23 | assert(pub_rsa_key_der_len == rsa_pub_3072_raw_der_len); 24 | 25 | Sha256 sha; 26 | wc_InitSha256(&sha); 27 | wc_Sha256Update(&sha, buf, pub_rsa_key_der_len); 28 | wc_Sha256Final(&sha, hash); 29 | } 30 | 31 | /* This function only exists to make edger8r happy. There must be at 32 | least one trusted (ECALL) function. */ 33 | void dummy(void) { 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # -*- mode: gitignore; -*- 2 | *~ 3 | \#*\# 4 | /.emacs.desktop 5 | /.emacs.desktop.lock 6 | *.elc 7 | auto-save-list 8 | tramp 9 | .\#* 10 | 11 | # Org-mode 12 | .org-id-locations 13 | *_archive 14 | 15 | # flymake-mode 16 | *_flymake.* 17 | 18 | # eshell files 19 | /eshell/history 20 | /eshell/lastdir 21 | 22 | # elpa packages 23 | /elpa/ 24 | 25 | # reftex files 26 | *.rel 27 | 28 | # AUCTeX auto folder 29 | /auto/ 30 | 31 | # cask packages 32 | .cask/ 33 | dist/ 34 | 35 | # Flycheck 36 | flycheck_*.el 37 | 38 | # server auth directory 39 | /server/ 40 | 41 | # projectiles files 42 | .projectile 43 | 44 | # directory configuration 45 | .dir-locals.el 46 | 47 | *.o 48 | *.a 49 | *.so 50 | deps/ 51 | local/ 52 | 53 | # Generated protobuf sources 54 | messages.pb-c.c 55 | messages.pb-c.h 56 | 57 | # Executables 58 | mbedtls-client 59 | mbedtls-ssl-server 60 | openssl-client 61 | wolfssl-client 62 | wolfssl-ssl-server 63 | sgxlkl-wolfssl-ssl-server 64 | wolfssl-ssl-server-mutual 65 | wolfssl-client-mutual 66 | 67 | # Graphene-SGX 68 | *.sig 69 | *.token 70 | *.manifest.sgx 71 | 72 | # OSX stuff 73 | ._* 74 | .DS_Store 75 | -------------------------------------------------------------------------------- /ra_private.h: -------------------------------------------------------------------------------- 1 | /* Interface to do remote attestation against Intel Attestation 2 | Service. Two implementations exist: (1) sgxsdk-ra-attester_* to be 3 | used with the SGX SDK. (2) nonsdk-ra-attester.c to be used with 4 | Graphene-SGX. */ 5 | 6 | #ifndef _RA_PRIVATE_H 7 | #define _RA_PRIVATE_H 8 | 9 | struct ra_tls_options; 10 | 11 | void do_remote_attestation(sgx_report_data_t* report_data, 12 | const struct ra_tls_options* opts, 13 | attestation_verification_report_t* r); 14 | 15 | extern const uint8_t ias_response_body_oid[]; 16 | extern const uint8_t ias_root_cert_oid[]; 17 | extern const uint8_t ias_leaf_cert_oid[]; 18 | extern const uint8_t ias_report_signature_oid[]; 19 | 20 | extern const uint8_t quote_oid[]; 21 | extern const uint8_t pck_crt_oid[]; 22 | extern const uint8_t pck_sign_chain_oid[]; 23 | extern const uint8_t tcb_info_oid[]; 24 | extern const uint8_t tcb_sign_chain_oid[]; 25 | extern const uint8_t qe_identity_oid[]; 26 | extern const uint8_t root_ca_crl_oid[]; 27 | extern const uint8_t pck_crl_oid[]; 28 | 29 | extern const size_t ias_oid_len; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /sgxsdk-ra-attester_t.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "ra.h" 7 | #include "ra-attester.h" 8 | #include "ra_private.h" 9 | #include "ra_tls_t.h" // OCALLs 10 | 11 | /* Trusted portion (called from within the enclave) to do remote 12 | attestation with the SGX SDK. */ 13 | void do_remote_attestation 14 | ( 15 | sgx_report_data_t* report_data, 16 | const struct ra_tls_options* opts, 17 | attestation_verification_report_t* attn_report 18 | ) 19 | { 20 | sgx_target_info_t target_info = {0, }; 21 | ocall_sgx_init_quote(&target_info); 22 | 23 | sgx_report_t report = {0, }; 24 | sgx_status_t status = sgx_create_report(&target_info, report_data, &report); 25 | assert(status == SGX_SUCCESS); 26 | 27 | ocall_remote_attestation(&report, opts, attn_report); 28 | } 29 | 30 | void ra_tls_create_report( 31 | sgx_report_t* report 32 | ) 33 | { 34 | sgx_target_info_t target_info = {0, }; 35 | sgx_report_data_t report_data = {0, }; 36 | memset(report, 0, sizeof(*report)); 37 | 38 | sgx_create_report(&target_info, &report_data, report); 39 | } 40 | -------------------------------------------------------------------------------- /tests/ra-challenger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef OPENSSL 10 | #include 11 | #endif 12 | 13 | #include "ra-challenger.h" 14 | 15 | /** 16 | * Read DER-encoded cert from argv[1] and verify. 17 | * 18 | * This is a simple unit test for the verification logic. 19 | */ 20 | int main(int argc, char* argv[]) { 21 | 22 | #ifdef OPENSSL 23 | OpenSSL_add_all_algorithms(); 24 | #endif 25 | 26 | if (argc < 2) { 27 | fprintf(stderr, "Usage: %s certificate\n", argv[0]); 28 | return 1; 29 | } 30 | 31 | int fd = open(argv[1], O_RDONLY); 32 | struct stat st; 33 | fstat(fd, &st); 34 | uint8_t der_crt[st.st_size]; 35 | int32_t der_crt_len = read(fd, der_crt, st.st_size); 36 | assert(der_crt_len == st.st_size); 37 | 38 | int rc = verify_sgx_cert_extensions(der_crt, der_crt_len); 39 | printf("SGX RA-TLS certificate verification ... %s\n", (rc == 0) ? "SUCCESS" : "FAIL"); 40 | 41 | dprintf_ratls_cert(STDOUT_FILENO, der_crt, der_crt_len); 42 | 43 | return rc; 44 | } 45 | -------------------------------------------------------------------------------- /sgxlkl/ratls/Makefile: -------------------------------------------------------------------------------- 1 | ALPINE_MAJOR=3.6 2 | ALPINE_VERSION=3.6.1 3 | ALPINE_ARCH=x86_64 4 | 5 | ROOT_FS=sgxlkl-miniroot-fs.img 6 | ALPINE_TAR=alpine-minirootfs.tar.gz 7 | MOUNTPOINT=/media/ext4disk 8 | IMAGE_SIZE_MB=500 9 | 10 | ESCALATE_CMD=sudo 11 | 12 | .DELETE_ON_ERROR: 13 | .PHONY: all clean 14 | 15 | all: $(ROOT_FS) 16 | 17 | clean: 18 | test -f $(ROOT_FS) && rm $(ROOT_FS) || true 19 | 20 | $(ALPINE_TAR): 21 | curl -L -o "$@" "https://nl.alpinelinux.org/alpine/v$(ALPINE_MAJOR)/releases/$(ALPINE_ARCH)/alpine-minirootfs-$(ALPINE_VERSION)-$(ALPINE_ARCH).tar.gz" 22 | 23 | $(ROOT_FS): $(ALPINE_TAR) buildenv.sh 24 | dd if=/dev/zero of="$@" count=$(IMAGE_SIZE_MB) bs=1M 25 | mkfs.ext4 "$@" 26 | $(ESCALATE_CMD) mkdir -p $(MOUNTPOINT) 27 | $(ESCALATE_CMD) mount -t ext4 -o loop "$@" $(MOUNTPOINT) 28 | $(ESCALATE_CMD) tar -C $(MOUNTPOINT) -xvf $(ALPINE_TAR) 29 | $(ESCALATE_CMD) cp /etc/resolv.conf $(MOUNTPOINT)/etc/resolv.conf 30 | $(ESCALATE_CMD) cp ../../../../sgxlkl-wolfssl-ssl-server $(MOUNTPOINT)/ 31 | $(ESCALATE_CMD) install buildenv.sh $(MOUNTPOINT)/usr/sbin 32 | $(ESCALATE_CMD) chroot $(MOUNTPOINT) /bin/sh /usr/sbin/buildenv.sh 33 | $(ESCALATE_CMD) umount $(MOUNTPOINT) 34 | $(ESCALATE_CMD) chown $(USER) "$@" 35 | -------------------------------------------------------------------------------- /sgxlkl/https-server/Makefile: -------------------------------------------------------------------------------- 1 | ALPINE_MAJOR=3.6 2 | ALPINE_VERSION=3.6.1 3 | ALPINE_ARCH=x86_64 4 | 5 | ROOT_FS=sgxlkl-miniroot-fs.img 6 | ALPINE_TAR=alpine-minirootfs.tar.gz 7 | MOUNTPOINT=/media/ext4disk 8 | IMAGE_SIZE_MB=500 9 | 10 | ESCALATE_CMD=sudo 11 | 12 | .DELETE_ON_ERROR: 13 | .PHONY: all clean 14 | 15 | all: $(ROOT_FS) 16 | 17 | clean: 18 | test -f $(ROOT_FS) && rm $(ROOT_FS) || true 19 | 20 | $(ALPINE_TAR): 21 | curl -L -o "$@" "https://nl.alpinelinux.org/alpine/v$(ALPINE_MAJOR)/releases/$(ALPINE_ARCH)/alpine-minirootfs-$(ALPINE_VERSION)-$(ALPINE_ARCH).tar.gz" 22 | 23 | $(ROOT_FS): $(ALPINE_TAR) buildenv.sh 24 | dd if=/dev/zero of="$@" count=$(IMAGE_SIZE_MB) bs=1M 25 | mkfs.ext4 "$@" 26 | $(ESCALATE_CMD) mkdir -p $(MOUNTPOINT) 27 | $(ESCALATE_CMD) mount -t ext4 -o loop "$@" $(MOUNTPOINT) 28 | $(ESCALATE_CMD) tar -C $(MOUNTPOINT) -xvf $(ALPINE_TAR) 29 | $(ESCALATE_CMD) cp /etc/resolv.conf $(MOUNTPOINT)/etc/resolv.conf 30 | $(ESCALATE_CMD) cp https-server.py $(MOUNTPOINT)/ 31 | $(ESCALATE_CMD) cp ../../../ldpreload.so $(MOUNTPOINT)/ 32 | $(ESCALATE_CMD) install buildenv.sh $(MOUNTPOINT)/usr/sbin 33 | $(ESCALATE_CMD) chroot $(MOUNTPOINT) /bin/sh /usr/sbin/buildenv.sh 34 | $(ESCALATE_CMD) umount $(MOUNTPOINT) 35 | $(ESCALATE_CMD) chown $(USER) "$@" 36 | -------------------------------------------------------------------------------- /ra-attester.h: -------------------------------------------------------------------------------- 1 | #ifndef _RA_ATTESTER_H_ 2 | #define _RA_ATTESTER_H_ 3 | 4 | #include 5 | 6 | struct ra_tls_options { 7 | sgx_spid_t spid; 8 | sgx_quote_sign_type_t quote_type; 9 | /* NULL-terminated string of domain name/IP, port and path prefix, 10 | e.g., api.trustedservices.intel.com/sgx/dev for development and 11 | api.trustedservices.intel.com/sgx for production. */ 12 | const char ias_server[512]; 13 | const char subscription_key[32]; 14 | }; 15 | 16 | struct ecdsa_ra_tls_options { 17 | char subscription_key[32]; 18 | }; 19 | 20 | void create_key_and_x509 21 | ( 22 | uint8_t* der_key, 23 | int* der_key_len, 24 | uint8_t* der_cert, 25 | int* der_cert_len, 26 | const struct ra_tls_options* opts 27 | ); 28 | 29 | void create_key_and_x509_pem 30 | ( 31 | uint8_t* pem_key, 32 | int* pem_key_len, 33 | uint8_t* pem_cert, 34 | int* pem_cert_len, 35 | const struct ra_tls_options* opts 36 | ); 37 | 38 | #ifdef RATLS_ECDSA 39 | void ecdsa_create_key_and_x509 40 | ( 41 | uint8_t* der_key, 42 | int* der_key_len, 43 | uint8_t* der_cert, 44 | int* der_cert_len, 45 | const struct ecdsa_ra_tls_options* opts 46 | ); 47 | #endif 48 | 49 | void ra_tls_create_report( 50 | sgx_report_t* report 51 | ); 52 | #endif 53 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | epid-ubuntu-16.04: 2 | tags: 3 | - sgx 4 | image: ratls-ubuntu16.04 5 | only: 6 | - web 7 | - schedules 8 | script: 9 | - ./build.sh sgxsdk 10 | - ./build.sh graphene 11 | - ./build.sh sgxlkl 12 | - make -C apps/secret-provisioning-example 13 | - make check 14 | 15 | epid-ubuntu-18.04: 16 | tags: 17 | - sgx 18 | image: ratls-ubuntu18.04 19 | only: 20 | - web 21 | - schedules 22 | script: 23 | - ./build.sh sgxsdk 24 | - ./build.sh graphene 25 | - ./build.sh sgxlkl 26 | - make -C apps/secret-provisioning-example 27 | - make check 28 | 29 | ecdsa-ubuntu-16.04: 30 | tags: 31 | - sgx-ecdsa 32 | image: ratls-ubuntu16.04 33 | only: 34 | - web 35 | - schedules 36 | script: 37 | - ECDSA=1 ./build.sh graphene 38 | - ECDSA=1 make wolfssl-ra-attester 39 | - ECDSA=1 make wolfssl-ra-challenger 40 | - make -C deps/SGXDataCenterAttestationPrimitives/SampleCode/QuoteServiceSample 41 | - ECDSA=1 make check 42 | 43 | ecdsa-ubuntu-18.04: 44 | tags: 45 | - sgx-ecdsa 46 | image: ratls-ubuntu18.04 47 | only: 48 | - web 49 | - schedules 50 | script: 51 | - ECDSA=1 ./build.sh graphene 52 | - ECDSA=1 make wolfssl-ra-attester 53 | - ECDSA=1 make wolfssl-ra-challenger 54 | - make -C deps/SGXDataCenterAttestationPrimitives/SampleCode/QuoteServiceSample 55 | - ECDSA=1 make check 56 | -------------------------------------------------------------------------------- /sgxsdk-ra-attester_u.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | /* Untrusted code to do remote attestation with the SGX SDK. */ 11 | 12 | void ocall_remote_attestation 13 | ( 14 | sgx_report_t* report, 15 | const struct ra_tls_options* opts, 16 | attestation_verification_report_t* attn_report 17 | ) 18 | { 19 | // produce quote 20 | uint32_t quote_size; 21 | sgx_calc_quote_size(NULL, 0, "e_size); 22 | 23 | sgx_quote_t* quote = (sgx_quote_t*) calloc(1, quote_size); 24 | 25 | sgx_status_t status; 26 | status = sgx_get_quote(report, 27 | opts->quote_type, 28 | &opts->spid, 29 | NULL, 30 | NULL, 31 | 0, 32 | NULL, 33 | quote, 34 | quote_size); 35 | assert(SGX_SUCCESS == status); 36 | 37 | // verify against IAS 38 | obtain_attestation_verification_report(quote, quote_size, opts, attn_report); 39 | } 40 | 41 | void ocall_sgx_init_quote 42 | ( 43 | sgx_target_info_t* target_info 44 | ) 45 | { 46 | sgx_epid_group_id_t gid; 47 | sgx_status_t status = sgx_init_quote(target_info, &gid); 48 | assert(status == SGX_SUCCESS); 49 | } 50 | -------------------------------------------------------------------------------- /container-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Build project from scratch in a Docker container. 4 | 5 | set -e 6 | set -x 7 | 8 | REPO_DIR=$(readlink -f .) 9 | TEMP_DIR=$(mktemp -d /var/tmp/ratls-XXX) 10 | 11 | POSITIONAL=() 12 | while [[ $# -gt 0 ]] 13 | do 14 | key="$1" 15 | 16 | case $key in 17 | -i|--image) 18 | IMAGE="$2" 19 | shift # past argument 20 | shift # past value 21 | ;; 22 | -b|--branch) 23 | REPO_BRANCH="$2" 24 | shift 25 | shift 26 | ;; 27 | -k|--keep) 28 | CMD=" ; bash" 29 | shift # past argument 30 | ;; 31 | *) # unknown option 32 | POSITIONAL+=("$1") # save it in an array for later 33 | shift # past argument 34 | ;; 35 | esac 36 | done 37 | set -- "${POSITIONAL[@]}" # restore positional parameters 38 | 39 | pushd $TEMP_DIR 40 | git clone $REPO_DIR 41 | cd $(basename $REPO_DIR) 42 | [ -n "$REPO_BRANCH" ] && git checkout $REPO_BRANCH 43 | 44 | # --privileged=true is required for SGX-LKL only. The build process 45 | # for SGX-LKL wants to mount things, uses iptables, etc. 46 | 47 | docker run --device=/dev/isgx --device=/dev/sgx --device=/dev/gsgx \ 48 | --privileged=true \ 49 | -v /var/run/aesmd:/var/run/aesmd \ 50 | -v$(pwd):/project \ 51 | -e SPID -e EPID_SUBSCRIPTION_KEY -e ECDSA_SUBSCRIPTION_KEY \ 52 | -it $IMAGE bash -c "cd /project $CMD" 53 | popd 54 | -------------------------------------------------------------------------------- /sgxlkl/https-server/https-server.py: -------------------------------------------------------------------------------- 1 | # This is a demonstration of how to use RA-TLS without actually 2 | # interfacing with the RA-TLS library directly. Instead, the RA-TLS 3 | # key and certificate are generated at startup and exposed through the 4 | # file system. The application accesses the key and certificate by 5 | # reading from the file system. 6 | 7 | import base64 8 | import BaseHTTPServer, SimpleHTTPServer 9 | import ssl 10 | 11 | def rsa_key_der_to_pem(key_der): 12 | out = '-----BEGIN RSA PRIVATE KEY-----\n' 13 | i = 0 14 | for c in base64.b64encode(key_der): 15 | if (i == 64): 16 | out += '\n' 17 | i = 0 18 | out += c 19 | i += 1 20 | out += '\n' 21 | out += '-----END RSA PRIVATE KEY-----' 22 | return out 23 | 24 | # The RA-TLS library currently only exposes the key and certificate as 25 | # in DER format. The Python API expects them in PEM format. Hence, we 26 | # convert them here. 27 | crt_pem = ssl.DER_cert_to_PEM_cert(open('/tmp/crt').read()) 28 | f = open('/tmp/crt.pem', 'w') 29 | f.write(crt_pem) 30 | f.close() 31 | 32 | with open('/tmp/key.pem', 'w') as f: 33 | print >> f, rsa_key_der_to_pem(open('/tmp/key').read()) 34 | 35 | # Start the HTTPS web server 36 | ip = '10.0.1.1' 37 | port = 4443 38 | 39 | print "Server listening on %s:%d\n" % (ip, port) 40 | httpd = BaseHTTPServer.HTTPServer((ip, port), SimpleHTTPServer.SimpleHTTPRequestHandler) 41 | httpd.socket = ssl.wrap_socket (httpd.socket, keyfile='/tmp/key.pem', certfile='/tmp/crt.pem', server_side=True) 42 | httpd.serve_forever() 43 | -------------------------------------------------------------------------------- /ssl-server.manifest: -------------------------------------------------------------------------------- 1 | loader.preload = file:deps/graphene/Runtime/libsysdb.so 2 | loader.env.LD_LIBRARY_PATH = /lib 3 | loader.debug_type = none 4 | loader.syscall_symbol = syscalldb 5 | 6 | fs.mount.lib.type = chroot 7 | fs.mount.lib.path = /lib 8 | fs.mount.lib.uri = file:deps/graphene/Runtime 9 | 10 | fs.mount.bin.type = chroot 11 | fs.mount.bin.path = /bin 12 | fs.mount.bin.uri = file:/bin 13 | 14 | fs.mount.etc.type = chroot 15 | fs.mount.etc.path = /etc 16 | fs.mount.etc.uri = file:/etc 17 | 18 | sgx.enclave_size = 256M 19 | sys.brk.size = 4M 20 | sys.stack.size = 4M 21 | 22 | # sgx-related 23 | sgx.trusted_files.ld = file:deps/graphene/Runtime/ld-linux-x86-64.so.2 24 | sgx.trusted_files.libc = file:deps/graphene/Runtime/libc.so.6 25 | sgx.trusted_files.libdl = file:deps/graphene/Runtime/libdl.so.2 26 | sgx.trusted_files.libm = file:deps/graphene/Runtime/libm.so.6 27 | sgx.trusted_files.libpthread = file:deps/graphene/Runtime/libpthread.so.0 28 | sgx.trusted_files.libprotobufc = file:deps/graphene/Runtime/libprotobuf-c.so.1 29 | sgx.trusted_files.libresolv = file:deps/graphene/Runtime/libresolv.so.2 30 | sgx.trusted_files.libnssdnsso2 = file:deps/graphene/Runtime/libnss_dns.so.2 31 | sgx.trusted_files.libcrypto = file:deps/graphene/Runtime/libcrypto.so.1.0.0 32 | sgx.trusted_files.libz = file:deps/graphene/Runtime/libz.so.1 33 | sgx.trusted_files.libssl = file:deps/graphene/Runtime/libssl.so.1.0.0 34 | 35 | # BUG Graphene cannot handle '-' character in trusted_files name 36 | 37 | sgx.trusted_files.cacertificates = file:/etc/ssl/certs/ca-certificates.crt 38 | sgx.trusted_files.etcresolv = file:/etc/resolv.conf 39 | -------------------------------------------------------------------------------- /ra-challenger_private.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | extern const uint8_t ias_response_body_oid[]; 7 | extern const uint8_t ias_root_cert_oid[]; 8 | extern const uint8_t ias_leaf_cert_oid[]; 9 | extern const uint8_t ias_report_signature_oid[]; 10 | 11 | extern const uint8_t quote_oid[]; 12 | extern const uint8_t pck_crt_oid[]; 13 | extern const uint8_t pck_sign_chain_oid[]; 14 | extern const uint8_t tcb_info_oid[]; 15 | extern const uint8_t tcb_sign_chain_oid[]; 16 | 17 | extern const size_t ias_oid_len; 18 | 19 | void get_quote_from_extension 20 | ( 21 | uint8_t* ext, 22 | size_t ext_len, 23 | sgx_quote_t* q 24 | ); 25 | 26 | int find_oid 27 | ( 28 | const unsigned char* ext, size_t ext_len, 29 | const unsigned char* oid, size_t oid_len, 30 | unsigned char** val, size_t* len 31 | ); 32 | 33 | void extract_x509_extensions 34 | ( 35 | uint8_t* ext, 36 | int ext_len, 37 | attestation_verification_report_t* attn_report 38 | ); 39 | 40 | int extract_x509_extension 41 | ( 42 | uint8_t* ext, 43 | int ext_len, 44 | const uint8_t* oid, 45 | size_t oid_len, 46 | uint8_t* data, 47 | uint32_t* data_len, 48 | uint32_t data_max_len 49 | ); 50 | 51 | void ecdsa_extract_x509_extensions 52 | ( 53 | uint8_t* ext, 54 | int ext_len, 55 | ecdsa_attestation_evidence_t* evidence 56 | ); 57 | 58 | /** 59 | * @return 1 if it is an EPID-based attestation RA-TLS 60 | * certificate. Otherwise, 0. 61 | */ 62 | int is_epid_ratls_cert 63 | ( 64 | const uint8_t* der_crt, 65 | uint32_t der_crt_len 66 | ); 67 | -------------------------------------------------------------------------------- /ra_tls_options.c.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # set -x 4 | 5 | if [[ -z "$ECDSA_SUBSCRIPTION_KEY" ]] && ( [[ -z "$SPID" ]] || [[ -z "$EPID_SUBSCRIPTION_KEY" ]] ); then 6 | echo "Either SPID and EPID_SUBSCRIPTION_KEY or ECDSA_SUBSCRIPTION_KEY is required!" 7 | exit 1 8 | fi 9 | 10 | if ( [[ ! -z "$SPID" ]] && [[ -z "$EPID_SUBSCRIPTION_KEY" ]] ) || \ 11 | ( [[ -z "$SPID" ]] && [[ ! -z "$EPID_SUBSCRIPTION_KEY" ]] ); then 12 | echo "For EPID, Both SPID and EPID_SUBSCRIPTION_KEY must be set!" 13 | exit 1 14 | fi 15 | 16 | if ( [[ "$QUOTE_TYPE" != "SGX_LINKABLE_SIGNATURE" ]] ) && \ 17 | ( [[ "$QUOTE_TYPE" != "SGX_UNLINKABLE_SIGNATURE" ]] ); then 18 | echo "QUOTE_TYPE must be one of SGX_UNLINKABLE_SIGNATURE or SGX_LINKABLE_SIGNATURE" 19 | exit 1 20 | fi 21 | 22 | SPID_BYTE_ARRAY=$(echo $SPID | python -c 'import sys ; s = sys.stdin.readline().strip(); print("".join(["0x"+s[2*i:2*i+2]+"," for i in range(len(s)/2)]))') 23 | 24 | cat < 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ra-attester.h" 9 | 10 | /* Use this in conjuction with Graphene-SGX, SCONE or SGX-LKL to 11 | expose the RA-TLS key and certificate as ordinary files to the 12 | application. This enables the use of RA-TLS without modifying the 13 | application simply by loading the key and certificate from a 14 | file. This is useful, for example, if the application cannot be 15 | modified (source code unavailable) or it is inconvenient to 16 | interface with C code (applications written for managed 17 | runtimes). */ 18 | 19 | uint8_t key[2048]; uint8_t crt[8192]; 20 | int key_len = sizeof(key); 21 | int crt_len = sizeof(crt); 22 | 23 | /* On SCONE and SGX-LKL /tmp is an in-memory file system protected by 24 | SGX. BEWARE: Graphene-SGX has no concept of a protected file system 25 | and writing the key to /tmp will expose it to the outside. */ 26 | #define FSROOT "/tmp" 27 | 28 | static const char* key_path = FSROOT"/key"; 29 | static const char* crt_path = FSROOT"/crt"; 30 | 31 | extern struct ra_tls_options my_ra_tls_options; 32 | 33 | 34 | /* We use a constructor function in combination with LD_PRELOAD to 35 | generate the key and certificate during the application's 36 | initialization. */ 37 | static __attribute__((constructor)) 38 | void init(void) { 39 | create_key_and_x509(key, &key_len, crt, &crt_len, &my_ra_tls_options); 40 | 41 | int fd = open(key_path, O_WRONLY|O_CREAT); 42 | assert(fd != -1); 43 | int ret = write(fd, key, key_len); 44 | assert(ret == key_len); 45 | close(fd); 46 | fd = open(crt_path, O_WRONLY|O_CREAT); 47 | assert(fd != -1); 48 | ret = write(fd, crt, crt_len); 49 | assert(ret == crt_len); 50 | close(fd); 51 | } 52 | -------------------------------------------------------------------------------- /tests/ra-attester.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ra-attester.h" 10 | 11 | extern struct ecdsa_ra_tls_options my_ecdsa_ra_tls_options; 12 | extern struct ra_tls_options my_ra_tls_options; 13 | 14 | static void write_buffer(const unsigned char* buf, 15 | int32_t len, 16 | const char* filename) 17 | { 18 | int fd = open(filename, O_CREAT | O_WRONLY, S_IRWXU); 19 | assert(fd > 0); 20 | ssize_t written = write(fd, buf, len); 21 | assert(written == len); 22 | close(fd); 23 | } 24 | 25 | static void usage(char* argv[]) { 26 | fprintf(stderr, "Usage: %s [epid|ecdsa]\n", argv[0]); 27 | } 28 | 29 | int main(int argc, char* argv[]) { 30 | (void) argc; 31 | (void) argv; 32 | 33 | uint8_t der_key[2048]; 34 | uint8_t der_crt[4*4096]; 35 | int32_t der_key_len = sizeof(der_key); 36 | int32_t der_crt_len = sizeof(der_crt); 37 | 38 | if (argc < 2) { 39 | usage(argv); 40 | return 1; 41 | } 42 | 43 | if (0 == strcmp(argv[1], "epid")) { 44 | create_key_and_x509(der_key, &der_key_len, 45 | der_crt, &der_crt_len, 46 | &my_ra_tls_options); 47 | } else if (0 == strcmp(argv[1], "ecdsa")) { 48 | #ifdef RATLS_ECDSA 49 | ecdsa_create_key_and_x509(der_key, &der_key_len, 50 | der_crt, &der_crt_len, 51 | &my_ecdsa_ra_tls_options); 52 | #else 53 | assert(0 && "not supported"); 54 | #endif 55 | } else { 56 | usage(argv); 57 | return 1; 58 | } 59 | 60 | write_buffer(der_crt, der_crt_len, "crt.der"); 61 | write_buffer(der_key, der_key_len, "key.der"); 62 | } 63 | -------------------------------------------------------------------------------- /ra.h: -------------------------------------------------------------------------------- 1 | #ifndef _RA_H_ 2 | #define _RA_H_ 3 | 4 | typedef struct { 5 | uint8_t ias_report[2*1024]; 6 | uint32_t ias_report_len; 7 | uint8_t ias_sign_ca_cert[2*1024]; 8 | uint32_t ias_sign_ca_cert_len; 9 | uint8_t ias_sign_cert[2*1024]; 10 | uint32_t ias_sign_cert_len; 11 | uint8_t ias_report_signature[2*1024]; 12 | uint32_t ias_report_signature_len; 13 | } attestation_verification_report_t; 14 | 15 | static const int rsa_3072_der_len = 1766; 16 | static const int rsa_pub_3072_pcks_der_len = 422; 17 | static const int rsa_pub_3072_pcks_header_len = 24; 18 | static const int rsa_pub_3072_raw_der_len = 398; /* rsa_pub_3072_pcks_der_len - pcks_nr_1_header_len */ 19 | 20 | typedef struct { 21 | uint8_t quote[2048]; 22 | uint32_t quote_len; 23 | /* Certificiate in PEM format. */ 24 | uint8_t pck_crt[2048]; 25 | uint32_t pck_crt_len; 26 | /* Certificate chain in PEM format. */ 27 | uint8_t pck_sign_chain[4096]; 28 | uint32_t pck_sign_chain_len; 29 | /* JSON data as published by 30 | https://api.portal.trustedservices.intel.com/documentation#pcs-tcb-info */ 31 | uint8_t tcb_info[4096]; 32 | uint32_t tcb_info_len; 33 | /* Certificate chain in PEM format. */ 34 | uint8_t tcb_sign_chain[4096]; 35 | uint32_t tcb_sign_chain_len; 36 | /* JSON data, e.g., as obtained from 37 | https://api.portal.trustedservices.intel.com/documentation#pcs-qe-identity */ 38 | uint8_t qe_identity[1024]; 39 | uint32_t qe_identity_len; 40 | /* PEM-encoded CRL as published by 41 | https://certificates.trustedservices.intel.com/IntelSGXRootCA.crl */ 42 | uint8_t root_ca_crl[1024]; 43 | uint32_t root_ca_crl_len; 44 | /* PEM-encoded certificate revocation list as published by 45 | https://api.portal.trustedservices.intel.com/documentation#pcs-revocation */ 46 | uint8_t pck_crl[1024]; 47 | uint32_t pck_crl_len; 48 | 49 | } ecdsa_attestation_evidence_t; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /ecdsa-sample-data/tcbSignChain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICjjCCAjSgAwIBAgIUEOFzeqZgPuT4f6NxVrZHQZd09PYwCgYIKoZIzj0EAwIw 3 | aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv 4 | cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ 5 | BgNVBAYTAlVTMB4XDTE4MDQxMzA2MjkxNloXDTQ5MTIzMTIyNTk1OVowaDEaMBgG 6 | A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 7 | aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT 8 | AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuwQGsBa6R1otjvetm7mpwUSx 9 | 7TDvTcLLbW/Q/4auUXJpyjnkPya9dDiohaXbcj4bfphUWjWds+yiRhtI3nXj3aOB 10 | uzCBuDAfBgNVHSMEGDAWgBQQ4XN6pmA+5Ph/o3FWtkdBl3T09jBSBgNVHR8ESzBJ 11 | MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 12 | ZWwuY29tL0ludGVsU0dYUm9vdENBLmNybDAdBgNVHQ4EFgQUEOFzeqZgPuT4f6Nx 13 | VrZHQZd09PYwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI 14 | KoZIzj0EAwIDSAAwRQIhAOlL11bn1kkn1vPkEwBWR4WsZqxrxVRLK4QhFARZLlOs 15 | AiBo+AbagH8sCIgSu5WNjRBVG5UES4mOQbSJAL7mO8pDcA== 16 | -----END CERTIFICATE----- 17 | -----BEGIN CERTIFICATE----- 18 | MIICjDCCAjKgAwIBAgIUTj70/cEc2epu7ogRe1tA/w/jQjswCgYIKoZIzj0EAwIw 19 | aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv 20 | cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ 21 | BgNVBAYTAlVTMB4XDTE4MDQxMzA2MjkxNloXDTMzMDQxMzA2MjkxNlowbDEeMBwG 22 | A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw 23 | b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD 24 | VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKn+5vklcuXzbsZ5XTxB 25 | N/yUDN1f/b8ThNrSOZhrcK1WBfcRJSHkKAN//78QXLOIJkvZMrUX8mBijnk83/20 26 | zQ+jgbUwgbIwHwYDVR0jBBgwFoAUEOFzeqZgPuT4f6NxVrZHQZd09PYwUgYDVR0f 27 | BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz 28 | LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5jcmwwHQYDVR0OBBYEFE4+9P3BHNnq 29 | bu6IEXtbQP8P40I7MA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG 30 | SM49BAMCA0gAMEUCIQDWPnhs8IwpEcEX0eZ8aOAqKdpNukMOGc138r09RohJOQIg 31 | Q4MUZCYBUCgGY5Ao5TEiJ9SR2EKem7VhYfg+AY4RM7E= 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /ecdsa-sample-data/pckSignChain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICjjCCAjSgAwIBAgIUEOFzeqZgPuT4f6NxVrZHQZd09PYwCgYIKoZIzj0EAwIw 3 | aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv 4 | cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ 5 | BgNVBAYTAlVTMB4XDTE4MDQxMzA2MjkxNloXDTQ5MTIzMTIyNTk1OVowaDEaMBgG 6 | A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 7 | aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT 8 | AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuwQGsBa6R1otjvetm7mpwUSx 9 | 7TDvTcLLbW/Q/4auUXJpyjnkPya9dDiohaXbcj4bfphUWjWds+yiRhtI3nXj3aOB 10 | uzCBuDAfBgNVHSMEGDAWgBQQ4XN6pmA+5Ph/o3FWtkdBl3T09jBSBgNVHR8ESzBJ 11 | MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 12 | ZWwuY29tL0ludGVsU0dYUm9vdENBLmNybDAdBgNVHQ4EFgQUEOFzeqZgPuT4f6Nx 13 | VrZHQZd09PYwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI 14 | KoZIzj0EAwIDSAAwRQIhAOlL11bn1kkn1vPkEwBWR4WsZqxrxVRLK4QhFARZLlOs 15 | AiBo+AbagH8sCIgSu5WNjRBVG5UES4mOQbSJAL7mO8pDcA== 16 | -----END CERTIFICATE----- 17 | -----BEGIN CERTIFICATE----- 18 | MIICmDCCAj2gAwIBAgIVAPTQBTE4+X8Tqvg9uimL9TPW593xMAoGCCqGSM49BAMC 19 | MGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD 20 | b3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw 21 | CQYDVQQGEwJVUzAeFw0xODA0MTMwNjI5MTZaFw0zMzA0MTMwNjI5MTZaMHAxIjAg 22 | BgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs 23 | IENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex 24 | CzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsQQP2FJ7f/ha 25 | 3WQ5e5HX872S4npgY3jX97c5T3B845kqRK5gMs/ALqJup5MfquflKuB54RBtmkZ7 26 | OHdiketvWKOBuzCBuDAfBgNVHSMEGDAWgBQQ4XN6pmA+5Ph/o3FWtkdBl3T09jBS 27 | BgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy 28 | dmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmNybDAdBgNVHQ4EFgQU9NAF 29 | MTj5fxOq+D26KYv1M9bn3fEwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB 30 | Af8CAQAwCgYIKoZIzj0EAwIDSQAwRgIhAOLkf8+Fdwyyj9i0cS4vdjCt+lZ0YLni 31 | AEuwPpA6VR/AAiEAnwb+647LF8dFWOMwOBe33lR19DwACWwaUFrJtuVlMuQ= 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /tests/00_attester_challenger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | from subprocess import * 5 | from time import sleep 6 | from shlex import split 7 | import sys 8 | 9 | 10 | # Create RA-TLS certificates with three different TLS 11 | # libraries. Verifies each of the three certificates with every TLS 12 | # library. Uses Graphene-SGX to run the code in an enclave. 13 | 14 | class TestCase: 15 | 16 | socat_process = None 17 | 18 | def setup(self): 19 | self.socat_process = Popen("exec socat -t10 TCP-LISTEN:1234,bind=127.0.0.1,reuseaddr,fork,range=127.0.0.0/8 UNIX-CLIENT:/var/run/aesmd/aesm.socket", shell=True) 20 | 21 | sleep(1) 22 | assert self.socat_process.poll() == None 23 | 24 | def teardown(self): 25 | check_call(split('rm -rf /tmp/openssl-epid-crt.der /tmp/wolfssl-epid-crt.der /tmp/mbedtls-epid-crt.der')) 26 | if self.socat_process: 27 | self.socat_process.terminate() 28 | self.socat_process = None 29 | 30 | def verify(self): 31 | pass 32 | 33 | def main(self) : 34 | check_call(split("deps/graphene/Runtime/pal-Linux-SGX openssl-ra-attester epid")) 35 | check_call(split("mv crt.der /tmp/openssl-epid-crt.der")) 36 | check_call(split("deps/graphene/Runtime/pal-Linux-SGX wolfssl-ra-attester epid")) 37 | check_call(split("mv crt.der /tmp/wolfssl-epid-crt.der")) 38 | check_call(split("deps/graphene/Runtime/pal-Linux-SGX mbedtls-ra-attester epid")) 39 | check_call(split("mv crt.der /tmp/mbedtls-epid-crt.der")) 40 | 41 | for lib in ['mbedtls', 'wolfssl', 'openssl']: 42 | check_call(split('./openssl-ra-challenger /tmp/%s-epid-crt.der' % (lib) )) 43 | check_call(split('./wolfssl-ra-challenger /tmp/%s-epid-crt.der' % (lib) )) 44 | check_call(split('./mbedtls-ra-challenger /tmp/%s-epid-crt.der' % (lib) )) 45 | 46 | if __name__ == '__main__': 47 | tc = TestCase() 48 | try: 49 | tc.setup() 50 | tc.main() 51 | finally: 52 | tc.teardown() 53 | -------------------------------------------------------------------------------- /apps/secret-provisioning-example/show-secrets.manifest: -------------------------------------------------------------------------------- 1 | loader.preload = file:../../deps/graphene/Runtime/libsysdb.so 2 | loader.exec = file:show-secrets 3 | loader.env.LD_PRELOAD=/lib/show-secrets-grab-secret.so 4 | loader.env.LD_LIBRARY_PATH = /lib:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu 5 | loader.debug_type = none 6 | 7 | fs.mount.lib.type = chroot 8 | fs.mount.lib.path = /lib 9 | fs.mount.lib.uri = file:../../deps/graphene/Runtime/ 10 | 11 | fs.mount.lib2.type = chroot 12 | fs.mount.lib2.path = /lib/x86_64-linux-gnu 13 | fs.mount.lib2.uri = file:/lib/x86_64-linux-gnu 14 | 15 | fs.mount.etc.type = chroot 16 | fs.mount.etc.path = /etc 17 | fs.mount.etc.uri = file:/etc 18 | 19 | sys.stack.size = 1m 20 | sys.brk.size = 64M 21 | glibc.heap_size = 16M 22 | 23 | sgx.enclave_size = 256M 24 | sgx.thread_num = 3 25 | 26 | sgx.trusted_files.ld = file:../../deps/graphene/Runtime/ld-linux-x86-64.so.2 27 | sgx.trusted_files.libc = file:../../deps/graphene/Runtime/libc.so.6 28 | sgx.trusted_files.libdl = file:../../deps/graphene/Runtime/libdl.so.2 29 | sgx.trusted_files.libm = file:../../deps/graphene/Runtime/libm.so.6 30 | sgx.trusted_files.libpthread = file:../../deps/graphene/Runtime/libpthread.so.0 31 | sgx.trusted_files.libnss1 = file:/lib/x86_64-linux-gnu/libnss_compat.so.2 32 | sgx.trusted_files.libnss2 = file:/lib/x86_64-linux-gnu/libnss_files.so.2 33 | sgx.trusted_files.libnss3 = file:/lib/x86_64-linux-gnu/libnss_nis.so.2 34 | sgx.trusted_files.libnss4 = file:/lib/x86_64-linux-gnu/libnss_myhostname.so.2 35 | sgx.trusted_files.libmdns4 = file:/lib/x86_64-linux-gnu/libnss_mdns4_minimal.so.2 36 | sgx.trusted_files.libnsl = file:/lib/x86_64-linux-gnu/libnsl.so.1 37 | sgx.trusted_files.libnssdns = file:../../deps/graphene/Runtime/libnss_dns.so.2 38 | sgx.trusted_files.libresolv = file:../../deps/graphene/Runtime/libresolv.so.2 39 | 40 | sgx.allowed_files.nsswitchconf = file:/etc/nsswitch.conf 41 | sgx.allowed_files.hostconf = file:/etc/host.conf 42 | sgx.allowed_files.hosts = file:/etc/hosts 43 | 44 | sgx.trusted_files.provision = file:../../deps/graphene/Runtime/show-secrets-grab-secret.so 45 | sgx.trusted_files.verifiercrt = file:secret-provisioning-service-crt.pem 46 | 47 | sgx.trusted_files.cacertificates = file:/etc/ssl/certs/ca-certificates.crt 48 | sgx.trusted_files.resolvconf = file:/etc/resolv.conf 49 | -------------------------------------------------------------------------------- /apps/secret-provisioning-example/redis-server.manifest: -------------------------------------------------------------------------------- 1 | loader.preload = file:../../deps/graphene/Runtime/libsysdb.so 2 | loader.exec = file:redis/src/redis-server 3 | loader.env.LD_PRELOAD=/lib/redis-server-grab-secret.so 4 | loader.env.LD_LIBRARY_PATH = /lib:/usr/lib:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu 5 | loader.debug_type = none 6 | 7 | fs.mount.lib.type = chroot 8 | fs.mount.lib.path = /lib 9 | fs.mount.lib.uri = file:../../deps/graphene/Runtime/ 10 | 11 | fs.mount.lib2.type = chroot 12 | fs.mount.lib2.path = /lib/x86_64-linux-gnu 13 | fs.mount.lib2.uri = file:/lib/x86_64-linux-gnu 14 | 15 | fs.mount.usr.type = chroot 16 | fs.mount.usr.path = /usr 17 | fs.mount.usr.uri = file:/usr 18 | 19 | fs.mount.etc.type = chroot 20 | fs.mount.etc.path = /etc 21 | fs.mount.etc.uri = file:/etc 22 | 23 | sys.stack.size = 1m 24 | sys.brk.size = 64M 25 | glibc.heap_size = 16M 26 | 27 | sgx.enclave_size = 512M 28 | sgx.thread_num = 16 29 | 30 | sgx.trusted_files.ld = file:../../deps/graphene/Runtime/ld-linux-x86-64.so.2 31 | sgx.trusted_files.libc = file:../../deps/graphene/Runtime/libc.so.6 32 | sgx.trusted_files.libdl = file:../../deps/graphene/Runtime/libdl.so.2 33 | sgx.trusted_files.libm = file:../../deps/graphene/Runtime/libm.so.6 34 | sgx.trusted_files.libpthread = file:../../deps/graphene/Runtime/libpthread.so.0 35 | # libjemalloc is required to run the "apt-get install"-version of redis-server on Ubuntu. 36 | sgx.trusted_files.libjemalloc = file:/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 37 | 38 | sgx.trusted_files.libnss1 = file:/lib/x86_64-linux-gnu/libnss_compat.so.2 39 | sgx.trusted_files.libnss2 = file:/lib/x86_64-linux-gnu/libnss_files.so.2 40 | sgx.trusted_files.libnss3 = file:/lib/x86_64-linux-gnu/libnss_nis.so.2 41 | sgx.trusted_files.libnss4 = file:/lib/x86_64-linux-gnu/libnss_myhostname.so.2 42 | sgx.trusted_files.libnss5 = file:/lib/x86_64-linux-gnu/libnss_mdns4_minimal.so.2 43 | sgx.trusted_files.libnsl = file:/lib/x86_64-linux-gnu/libnsl.so.1 44 | sgx.trusted_files.libnssdns = file:../../deps/graphene/Runtime/libnss_dns.so.2 45 | sgx.trusted_files.libresolv = file:../../deps/graphene/Runtime/libresolv.so.2 46 | sgx.trusted_files.librt = file:../../deps/graphene/Runtime/librt.so.1 47 | 48 | sgx.allowed_files.nsswitchconf = file:/etc/nsswitch.conf 49 | sgx.allowed_files.gaiconf = file:/etc/gai.conf 50 | sgx.allowed_files.hostconf = file:/etc/host.conf 51 | sgx.allowed_files.hosts = file:/etc/hosts 52 | 53 | sgx.trusted_files.provision = file:../../deps/graphene/Runtime/redis-server-grab-secret.so 54 | sgx.trusted_files.servicecrt = file:secret-provisioning-service-crt.pem 55 | 56 | sgx.trusted_files.cacertificates = file:/etc/ssl/certs/ca-certificates.crt 57 | sgx.trusted_files.resolvconf = file:/etc/resolv.conf 58 | -------------------------------------------------------------------------------- /tests/00_sgxlkl_server_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | from subprocess import * 5 | from time import sleep 6 | from shlex import split 7 | import sys 8 | 9 | external_iface = 'eth0' 10 | if 'EXTERNAL_IFACE' in os.environ: 11 | external_iface = os.environ['EXTERNAL_IFACE'] 12 | 13 | class SGXLKLTestCase(): 14 | socat_process = None 15 | 16 | def setup_iptables(self): 17 | cmds = ["sudo ip tuntap add dev sgxlkl_tap0 mode tap user `whoami`", 18 | "sudo ip link set dev sgxlkl_tap0 up", 19 | "sudo ip addr add dev sgxlkl_tap0 10.0.1.254/24", 20 | "sudo iptables -I FORWARD -i sgxlkl_tap0 -o "+external_iface+" -s 10.0.1.0/24 -m conntrack --ctstate NEW -j ACCEPT", 21 | "sudo iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT", 22 | "sudo iptables -t nat -I POSTROUTING -o "+external_iface+" -j MASQUERADE"] 23 | 24 | for cmd in cmds: 25 | check_call(cmd, shell=True) 26 | 27 | def setup(self): 28 | self.setup_iptables() 29 | 30 | self.socat_process = Popen("exec socat -t10 TCP-LISTEN:1234,bind=10.0.1.254,reuseaddr,fork,range=10.0.1.0/8 UNIX-CLIENT:/var/run/aesmd/aesm.socket", shell=True) 31 | sleep(1) 32 | assert self.socat_process.poll() == None 33 | 34 | def teardown_iptables(self): 35 | cmds = ["sudo iptables -t nat -D POSTROUTING -o "+external_iface+" -j MASQUERADE", 36 | "sudo iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT", 37 | "sudo iptables -D FORWARD -s 10.0.1.0/24 -i sgxlkl_tap0 -o "+external_iface+" -m conntrack --ctstate NEW -j ACCEPT", 38 | "sudo ip tuntap del dev sgxlkl_tap0 mode tap"] 39 | 40 | for cmd in cmds: 41 | check_call(split(cmd)) 42 | 43 | def teardown(self): 44 | self.socat_process.terminate() 45 | self.socat_process = None 46 | self.teardown_iptables() 47 | 48 | def main(self): 49 | server_process = None 50 | cmd = 'exec sgxlkl/sgx-lkl/build/sgx-lkl-run sgxlkl/sgx-lkl/apps/ratls/sgxlkl-miniroot-fs.img /sgxlkl-wolfssl-ssl-server' 51 | env = dict(os.environ) 52 | env.update({'SGXLKL_TAP' : 'sgxlkl_tap0', 53 | 'SGXLKL_VERBOSE' : '1', 54 | 'RATLS_AESMD_IP' : '10.0.1.254'}) 55 | 56 | server_process = Popen(cmd, env=env, shell=True) 57 | sleep(10) 58 | assert server_process.poll() == None 59 | 60 | check_call(split('./openssl-client -p 11111 -h 10.0.1.1')) 61 | 62 | server_process.terminate() 63 | sleep(1) 64 | assert server_process.poll() != None 65 | -------------------------------------------------------------------------------- /ratls-wolfssl.mk: -------------------------------------------------------------------------------- 1 | # Makefile to build the wolfSSL-based remote attestation TLS library. 2 | 3 | ######## Intel(R) SGX SDK Settings ######## 4 | SGX_SDK ?= /opt/intel/sgxsdk 5 | SGX_MODE ?= HW 6 | SGX_ARCH ?= x64 7 | PROJECT_ROOT ?= $(shell readlink -f .) 8 | 9 | WOLFSSL_ROOT := $(shell readlink -f deps/wolfssl) 10 | 11 | SGX_COMMON_CFLAGS := -m64 12 | SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 13 | SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign 14 | SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r 15 | 16 | ifeq ($(SGX_DEBUG), 1) 17 | ifeq ($(SGX_PRERELEASE), 1) 18 | $(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) 19 | endif 20 | endif 21 | 22 | ifeq ($(SGX_DEBUG), 1) 23 | SGX_COMMON_CFLAGS += -O0 -g 24 | else 25 | SGX_COMMON_CFLAGS += -O2 26 | endif 27 | 28 | ifneq ($(SGX_MODE), HW) 29 | Trts_Library_Name := sgx_trts_sim 30 | Service_Library_Name := sgx_tservice_sim 31 | else 32 | Trts_Library_Name := sgx_trts 33 | Service_Library_Name := sgx_tservice 34 | endif 35 | 36 | Library_Name := sgx_ra_tls_wolfssl 37 | 38 | # -DFP_MAX_BITS=8192 required for RSA keys > 2048 bits to work 39 | Wolfssl_C_Extra_Flags := -DSGX_SDK -DWOLFSSL_SGX -DWOLFSSL_SGX_ATTESTATION -DUSER_TIME -DWOLFSSL_CERT_EXT -DFP_MAX_BITS=8192 40 | 41 | Wolfssl_C_Files := $(PROJECT_ROOT)/wolfssl-ra-attester.c \ 42 | $(PROJECT_ROOT)/wolfssl-ra-challenger.c \ 43 | $(PROJECT_ROOT)/sgxsdk-ra-attester_t.c \ 44 | $(PROJECT_ROOT)/ra-challenger.c \ 45 | $(PROJECT_ROOT)/wolfssl-ra.c \ 46 | $(PROJECT_ROOT)/ra_tls_t.c \ 47 | $(PROJECT_ROOT)/ra_tls_options.c 48 | 49 | Wolfssl_Include_Paths := -I$(WOLFSSL_ROOT)/ \ 50 | -I$(WOLFSSL_ROOT)/wolfcrypt/ \ 51 | -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport 52 | 53 | Compiler_Warnings := -Wall -Wextra -Wwrite-strings -Wlogical-op -Wshadow -Werror 54 | Flags_Just_For_C := -Wno-implicit-function-declaration -std=c11 55 | Common_C_Cpp_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Wolfssl_Include_Paths) -fno-builtin-printf -I. 56 | Wolfssl_C_Flags := $(Compiler_Warnings) $(Flags_Just_For_C) $(Common_C_Cpp_Flags) $(Wolfssl_C_Extra_Flags) 57 | 58 | Wolfssl_C_Objects := $(Wolfssl_C_Files:.c=.o) 59 | 60 | override CFLAGS += $(Wolfssl_C_Flags) 61 | 62 | .PHONY: all run clean mrproper 63 | 64 | all: libsgx_ra_tls_wolfssl.a 65 | 66 | ######## Library Objects ######## 67 | 68 | ra_tls_t.c ra_tls_u.c ra_tls_t.h ra_tls_u.h : ra_tls.edl 69 | $(SGX_EDGER8R) $^ --search-path $(SGX_SDK)/include 70 | 71 | libsgx_ra_tls_wolfssl.a: ra_tls_t.o ra_tls_u.o $(Wolfssl_C_Objects) 72 | ar rcs $@ $(Wolfssl_C_Objects) 73 | @echo "LINK => $@" 74 | 75 | clean: 76 | @rm -f $(Wolfssl_C_Objects) 77 | 78 | mrproper: clean 79 | @rm -f ra_tls_t.c ra_tls_t.h ra_tls_u.h ra_tls_u.c libsgx_ra_tls_wolfssl.a 80 | -------------------------------------------------------------------------------- /Dockerfile-ubuntu16.04: -------------------------------------------------------------------------------- 1 | # Software dependencies to build/run RA-TLS on Ubuntu 16.04. 2 | 3 | FROM ubuntu:16.04 4 | # FROM sconecuratedimages/crosscompilers:releasecandidate 5 | 6 | # RUN sed -i 's/security\./old-releases\./g' /etc/apt/sources.list && sed -i 's/archive\./old-releases\./g' /etc/apt/sources.list 7 | 8 | RUN apt-get update 9 | RUN apt-get install -y --no-install-recommends clang-6.0 coreutils git wget \ 10 | openssh-client build-essential cmake libssl-dev libprotoc-dev \ 11 | protobuf-compiler libprotobuf-dev libprotobuf-c-dev protobuf-c-compiler \ 12 | autoconf libtool ca-certificates automake pkgconf vim-common unzip 13 | 14 | # Required for apps/redis-secrect-provisioning-example 15 | RUN apt-get install -y libnss-myhostname libnss-mdns 16 | # Required by package version of redis-server 17 | RUN apt-get install -y libjemalloc1 18 | 19 | RUN ln -s /usr/bin/clang++-6.0 /usr/bin/clang++ && \ 20 | ln -s /usr/bin/clang-6.0 /usr/bin/clang 21 | 22 | # Required for scripts in tests/ 23 | RUN apt-get install -y python3 24 | 25 | # Graphene requirements 26 | RUN apt-get install -y --no-install-recommends bison gawk python3 python3-crypto python3-pip \ 27 | python3-setuptools python3-wheel socat 28 | 29 | RUN pip3 install protobuf 30 | 31 | # SCONE requirements 32 | RUN apt-get install -y --no-install-recommends libprotoc-dev pkgconf protobuf-compiler # to compile libprotobuf-c 33 | # SGX-LKL 34 | RUN apt-get install -y --no-install-recommends curl sudo make gcc bc python xutils-dev iproute2 iptables 35 | 36 | RUN wget https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1604/libsgx-dcap-ql-dbg_1.0.101.48192-xenial1_amd64.deb \ 37 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1604/libsgx-dcap-ql-dev_1.0.101.48192-xenial1_amd64.deb \ 38 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1604/libsgx-dcap-ql_1.0.101.48192-xenial1_amd64.deb \ 39 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1604/libsgx-enclave-common-dev_2.4.100.48163-xenial1_amd64.deb \ 40 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1604/libsgx-enclave-common_2.4.100.48163-xenial1_amd64.deb \ 41 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1604/sgx_linux_x64_sdk_2.4.100.48163.bin 42 | 43 | RUN dpkg -i libsgx-enclave-common_2.4.100.48163-xenial1_amd64.deb 44 | RUN dpkg -i libsgx-enclave-common_2.4.100.48163-xenial1_amd64.deb libsgx-enclave-common-dev_2.4.100.48163-xenial1_amd64.deb 45 | RUN dpkg -i libsgx-dcap-ql_1.0.101.48192-xenial1_amd64.deb 46 | RUN dpkg -i libsgx-dcap-ql-dbg_1.0.101.48192-xenial1_amd64.deb libsgx-dcap-ql-dev_1.0.101.48192-xenial1_amd64.deb 47 | RUN printf 'no\n/opt/intel\n' | bash sgx_linux_x64_sdk_2.4.100.48163.bin 48 | 49 | RUN echo 'Defaults env_keep += "http_proxy https_proxy no_proxy"' >> /etc/sudoers 50 | -------------------------------------------------------------------------------- /Dockerfile-ubuntu18.04: -------------------------------------------------------------------------------- 1 | # Software dependencies to build/run RA-TLS on Ubuntu 18.04. 2 | 3 | FROM ubuntu:18.04 4 | 5 | RUN apt-get update 6 | RUN apt-get install -y --no-install-recommends gcc-5 libc6-dev g++ make dpkg-dev \ 7 | clang-6.0 coreutils git wget openssh-client cmake libssl-dev \ 8 | libprotoc-dev protobuf-compiler libprotobuf-dev libprotobuf-c-dev \ 9 | protobuf-c-compiler autoconf libtool ca-certificates automake pkgconf \ 10 | unzip rename vim-common 11 | 12 | RUN ln -s /usr/bin/clang++-6.0 /usr/bin/clang++ && \ 13 | ln -s /usr/bin/clang-6.0 /usr/bin/clang 14 | 15 | # Required for apps/redis-secrect-provisioning-example 16 | RUN apt-get install -y libnss-myhostname libnss-mdns 17 | 18 | # Required by package version of redis-server 19 | RUN apt-get install -y libjemalloc1 20 | 21 | # Graphene requirements 22 | RUN apt-get install -y --no-install-recommends bison gawk python3 python3-protobuf python3-crypto socat 23 | 24 | # SCONE requirements 25 | RUN apt-get install -y --no-install-recommends libprotoc-dev pkgconf protobuf-compiler # to compile libprotobuf-c 26 | # SGX-LKL 27 | RUN apt-get install -y --no-install-recommends curl sudo make gcc bc python xutils-dev iproute2 iptables 28 | 29 | RUN wget https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1804/libsgx-dcap-ql-dbg_1.0.101.48192-bionic1_amd64.deb \ 30 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1804/libsgx-dcap-ql-dev_1.0.101.48192-bionic1_amd64.deb \ 31 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1804/libsgx-dcap-ql_1.0.101.48192-bionic1_amd64.deb \ 32 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1804/libsgx-enclave-common-dbgsym_2.4.100.48163-bionic1_amd64.ddeb \ 33 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1804/libsgx-enclave-common-dev_2.4.100.48163-bionic1_amd64.deb \ 34 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1804/libsgx-enclave-common_2.4.100.48163-bionic1_amd64.deb \ 35 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1804/sgx_linux_x64_driver_dcap_4f32b98.bin \ 36 | https://download.01.org/intel-sgx/dcap-1.0.1/dcap_installer/ubuntuServer1804/sgx_linux_x64_sdk_2.4.100.48163.bin 37 | 38 | # Works around an issue (https://github.com/intel/linux-sgx/issues/395) 39 | # with installing .deb packages inside Docker 40 | RUN mkdir /etc/init 41 | 42 | RUN dpkg -i libsgx-enclave-common_2.4.100.48163-bionic1_amd64.deb 43 | RUN dpkg -i libsgx-enclave-common-dev_2.4.100.48163-bionic1_amd64.deb 44 | RUN dpkg -i libsgx-dcap-ql_1.0.101.48192-bionic1_amd64.deb 45 | RUN dpkg -i libsgx-dcap-ql-dbg_1.0.101.48192-bionic1_amd64.deb libsgx-dcap-ql-dev_1.0.101.48192-bionic1_amd64.deb 46 | RUN printf 'no\n/opt/intel\n' | bash sgx_linux_x64_sdk_2.4.100.48163.bin 47 | 48 | RUN echo 'Defaults env_keep += "http_proxy https_proxy no_proxy"' >> /etc/sudoers 49 | -------------------------------------------------------------------------------- /tests/00_graphene_server_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | from subprocess import * 5 | from time import sleep 6 | from shlex import split 7 | import sys 8 | 9 | class MutualAttestationTestCase(): 10 | socat_process = None 11 | server_process = None 12 | client_process = None 13 | 14 | def setup(self): 15 | self.socat_process = Popen("exec socat -t10 TCP-LISTEN:1234,bind=127.0.0.1,reuseaddr,fork,range=127.0.0.0/8 UNIX-CLIENT:/var/run/aesmd/aesm.socket", shell=True) 16 | sleep(1) 17 | assert self.socat_process.poll() == None 18 | 19 | def teardown(self): 20 | if self.socat_process: 21 | self.socat_process.terminate() 22 | self.socat_process = None 23 | if self.server_process: 24 | if self.server_process.poll() == None: 25 | self.server_process.terminate() 26 | self.server_process = None 27 | if self.client_process: 28 | if self.client_process.poll() == None: 29 | self.client_process.terminate() 30 | self.client_process = None 31 | 32 | def verify(self): 33 | pass 34 | def main(self): 35 | cmd = 'exec deps/graphene/Runtime/pal-Linux-SGX wolfssl-ssl-server-mutual' 36 | self.server_process = Popen(cmd, shell=True) 37 | sleep(10) 38 | 39 | cmd = 'exec deps/graphene/Runtime/pal-Linux-SGX wolfssl-client-mutual' 40 | self.client_process = Popen(cmd, shell=True) 41 | for _ in range(10): 42 | if self.client_process.poll() != None: 43 | break 44 | sleep(1) 45 | 46 | assert (self.client_process.poll() == 0) 47 | 48 | class GrapheneSGXTestCase(): 49 | socat_process = None 50 | server_process = None 51 | 52 | def setup(self): 53 | self.socat_process = Popen("exec socat -t10 TCP-LISTEN:1234,bind=127.0.0.1,reuseaddr,fork,range=127.0.0.0/8 UNIX-CLIENT:/var/run/aesmd/aesm.socket", shell=True) 54 | sleep(1) 55 | assert self.socat_process.poll() == None 56 | 57 | def teardown(self): 58 | if self.socat_process: 59 | self.socat_process.terminate() 60 | if self.server_process: 61 | if self.server_process.poll() == None: 62 | self.server_process.terminate() 63 | self.server_process = None 64 | 65 | def main(self): 66 | for server in ['wolfssl-ssl-server', 'mbedtls-ssl-server'] : 67 | cmd = "exec deps/graphene/Runtime/pal-Linux-SGX ./%s" % (server) 68 | self.server_process = Popen(cmd, shell=True) 69 | sleep(10) 70 | assert self.server_process.poll() == None 71 | 72 | for client in ['mbedtls-client', 'wolfssl-client', 'openssl-client -p 11111'] : 73 | check_call(split('./' + client)) 74 | 75 | self.server_process.terminate() 76 | for i in range(5): 77 | if self.server_process.poll(): 78 | break 79 | sleep(1) 80 | sigterm = 15 81 | assert self.server_process.poll() == sigterm 82 | -------------------------------------------------------------------------------- /tests/00_secrect_provisioning_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | from subprocess import Popen, run, PIPE 5 | from time import sleep 6 | from shlex import split 7 | import sys 8 | import unittest 9 | 10 | class RedisProvisioningTestCase(unittest.TestCase): 11 | socat_process = None 12 | verifier_process = None 13 | redis_process = None 14 | old_cwd = None 15 | 16 | # Expected by unittest.TestCase. 17 | # TODO: Unify setUp() and setup(). 18 | def setUp(self): 19 | self.setup() 20 | 21 | def setup(self): 22 | self.socat_process = Popen("exec socat -t10 TCP-LISTEN:1234,bind=127.0.0.1,reuseaddr,fork,range=127.0.0.0/8 UNIX-CLIENT:/var/run/aesmd/aesm.socket", shell=True) 23 | sleep(1) 24 | assert self.socat_process.poll() == None 25 | 26 | self.old_cwd = os.getcwd() 27 | os.chdir('apps/secret-provisioning-example') 28 | 29 | cmd = 'exec ./secret-provisioning-service' 30 | self.verifier_process = Popen(cmd, shell=True) 31 | sleep(2) 32 | 33 | def teardown(self): 34 | if self.socat_process: 35 | self.socat_process.terminate() 36 | self.socat_process = None 37 | if self.verifier_process: 38 | if self.verifier_process.poll() == None: 39 | self.verifier_process.terminate() 40 | self.verifier_process = None 41 | if self.redis_process: 42 | if self.redis_process.poll() == None: 43 | # .terminate() does not seem to work properly with 44 | # redis-server and this version of Graphene 45 | self.redis_process.kill() 46 | self.redis_process = None 47 | 48 | # Expected by unittest.TestCase. 49 | # TODO: Unify tearDown() and teardown(). 50 | def tearDown(self): 51 | self.teardown() 52 | os.chdir(self.old_cwd) 53 | 54 | def verify(self): 55 | pass 56 | 57 | def test_redis_server(self): 58 | cmd = 'exec ../../deps/graphene/Runtime/pal-Linux-SGX ./redis-server.manifest.sgx --save "" --protected-mode no --requirepass XXXXX' 59 | self.redis_process = Popen(cmd, shell=True) 60 | for _ in range(10): 61 | if self.redis_process.poll() != None: 62 | break 63 | sleep(1) 64 | 65 | p = run('redis/src/redis-cli -a intelsgxrocks! ping', 66 | shell=True, stdout=PIPE, timeout=3) 67 | self.assertTrue(p.stdout.decode().strip() == "PONG") 68 | 69 | # redis-server may actually exit with non-zero return 70 | # status. That's fine. 71 | # assert (self.redis_process.poll() == 0) 72 | 73 | def test_show_secret(self): 74 | cmd = 'exec ../../deps/graphene/Runtime/pal-Linux-SGX ./show-secrets.manifest.sgx --requirepass XxxXXxxXX' 75 | p = Popen(cmd, shell=True, stdout=PIPE, env={'SECRET':'not-the-real-thing'}) 76 | outs, errs = p.communicate(timeout=10) 77 | 78 | outs = outs.decode() 79 | 80 | self.assertTrue(outs.find('SECRET=42istheanswer') != -1) 81 | self.assertTrue(outs.find('Overwriting as `--requirepass 42istheanswer!`') != -1) 82 | 83 | def main(self): 84 | self.test_redis_server() 85 | self.test_show_secret() 86 | 87 | if __name__ == '__main__': 88 | unittest.main() 89 | -------------------------------------------------------------------------------- /ecdsa-ra-attester.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "sgx_report.h" 9 | #include "ecdsa-aesmd-messages.pb-c.h" 10 | 11 | #include "ra-attester_private.h" 12 | 13 | /** 14 | * Establish connection to Quote Service. 15 | */ 16 | int connect_to_quote_service(void) 17 | { 18 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 19 | assert(-1 != sockfd); 20 | struct sockaddr_in srvaddr = {0, }; 21 | srvaddr.sin_family = AF_INET; 22 | srvaddr.sin_port = htons(12345); 23 | inet_pton(AF_INET, "127.0.0.1", &srvaddr.sin_addr); 24 | int rc = connect(sockfd, (struct sockaddr*) &srvaddr, sizeof(srvaddr)); 25 | assert(-1 != rc); 26 | return sockfd; 27 | } 28 | 29 | /** 30 | * Low-level socket I/O to obtain quoting enclave's target info and 31 | * quote size. 32 | */ 33 | void get_target_info_from_quote_service 34 | ( 35 | int sockfd, 36 | sgx_target_info_t* target_info, 37 | uint32_t* quote_size 38 | ) 39 | { 40 | Quoteservice__Message__Request__InitQuoteRequest request = 41 | QUOTESERVICE__MESSAGE__REQUEST__INIT_QUOTE_REQUEST__INIT; 42 | Quoteservice__Message__Request wrapper_msg = 43 | QUOTESERVICE__MESSAGE__REQUEST__INIT; 44 | wrapper_msg.initquoterequest = &request; 45 | uint32_t payload_len = quoteservice__message__request__get_packed_size(&wrapper_msg); 46 | uint32_t total_len = payload_len + sizeof(payload_len); 47 | uint8_t buf[1024]; 48 | assert(total_len <= sizeof(buf)); 49 | memcpy(buf, (uint8_t*) &payload_len, sizeof(payload_len)); 50 | quoteservice__message__request__pack(&wrapper_msg, buf + sizeof(payload_len)); 51 | int rc = send(sockfd, buf, total_len, 0); 52 | assert(rc == (int) total_len); 53 | 54 | rc = recv(sockfd, (uint8_t*) &payload_len, sizeof(payload_len), 0); 55 | assert(rc == sizeof(payload_len)); 56 | assert(payload_len <= sizeof(buf)); 57 | rc = recv(sockfd, buf, payload_len, 0); 58 | assert(rc == (int) payload_len); 59 | Quoteservice__Message__Response* msg = 60 | quoteservice__message__response__unpack(NULL, payload_len, buf); 61 | assert(NULL != msg->initquoteresponse); 62 | Quoteservice__Message__Response__InitQuoteResponse* response = 63 | msg->initquoteresponse; 64 | assert(response->has_targetinfo); 65 | assert(response->targetinfo.len == sizeof(*target_info)); 66 | memcpy(target_info, response->targetinfo.data, response->targetinfo.len); 67 | *quote_size = response->quote_size; 68 | } 69 | 70 | /** 71 | * Low-level socket I/O with "Quote Service" to obtain quote based on report. 72 | */ 73 | void get_quote_from_quote_service 74 | ( 75 | int sockfd, 76 | const sgx_report_t* report, 77 | uint8_t* quote, 78 | uint32_t quote_len 79 | ) 80 | { 81 | Quoteservice__Message__Request__GetQuoteRequest request = 82 | QUOTESERVICE__MESSAGE__REQUEST__GET_QUOTE_REQUEST__INIT; 83 | Quoteservice__Message__Request wrapper_msg = 84 | QUOTESERVICE__MESSAGE__REQUEST__INIT; 85 | wrapper_msg.getquoterequest = &request; 86 | request.report.data = (uint8_t*) report; 87 | request.report.len = sizeof(*report); 88 | 89 | /* print_byte_array(stdout, (uint8_t*) report, sizeof(*report)); */ 90 | /* printf("\n"); */ 91 | 92 | uint32_t payload_len = quoteservice__message__request__get_packed_size(&wrapper_msg); 93 | uint32_t total_len = payload_len + sizeof(payload_len); 94 | uint8_t buf[4096]; 95 | assert(total_len <= sizeof(buf)); 96 | memcpy(buf, (uint8_t*) &payload_len, sizeof(payload_len)); 97 | quoteservice__message__request__pack(&wrapper_msg, buf + sizeof(payload_len)); 98 | int rc = send(sockfd, buf, total_len, 0); 99 | assert(rc == (int) total_len); 100 | 101 | rc = recv(sockfd, (uint8_t*) &payload_len, sizeof(payload_len), 0); 102 | assert(rc == sizeof(payload_len)); 103 | assert(payload_len <= sizeof(buf)); 104 | rc = recv(sockfd, buf, payload_len, 0); 105 | assert(rc == (int) payload_len); 106 | Quoteservice__Message__Response* msg = 107 | quoteservice__message__response__unpack(NULL, payload_len, buf); 108 | assert(NULL != msg->getquoteresponse); 109 | Quoteservice__Message__Response__GetQuoteResponse* response = 110 | msg->getquoteresponse; 111 | assert(response->has_quote); 112 | assert(response->quote.len == quote_len); 113 | memcpy(quote, response->quote.data, response->quote.len); 114 | } 115 | -------------------------------------------------------------------------------- /apps/secret-provisioning-example/README.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | This project demonstrates how to provision an SGX application with secrets after remotely attesting it. We demonstrate this with two applications, one of which is Redis. Redis can be configured with a password which clients must provide before the server accepts commands from them. The password is usually provided either in a configuration file or as a command line argument. We demonstrate how to provision the password only after attesting the Redis server. We also have a second [application](show-secrets.c) to demonstrate how to provision secrets passed in environment variables. 4 | 5 | The Redis server runs inside an SGX enclave with the help of Graphene. After instantiating the enclave, but before the Redis server runs, we execute additional code (captured in the `redis-server-grab-secret.so` helper library and LDPRELOADed in the Redis manifest) to remotely attest to a [secret provisioning service](secret-provisioning-service.c). The secret provisioning service only releases the password to the Redis server after successfully verifying its SGX identity. 6 | 7 | The Redis server is completely unmodified. This project assumes that Redis is called with `--requirepass `. After the helper library receives the password from the secret provisioning service, it overwrites this command-line argument with `--requirepass `. 8 | 9 | The Redis server communicates securely with the secret provisioning service over mutually authenticated TLS. The provisioning service uses a standard (self-signed) [X.509 certificate](secret-provisioning-service-crt.pem) as its identity. The Redis server uses an RA-TLS certificate to authenticate to the provisioning service. The provisioning service has the Redis server's SGX identity backed at build time (cf. [redis_server_sgx_identity.c](redis_server_sgx_identity.c)). The provisioning service verifies the SGX identity information in the RA-TLS certificate before sending the secret to the remote party. 10 | 11 | ``` 12 | X.509 TLS RA-TLS plain text 13 | Secret Provisioning <--------------> Redis <----------> Client 14 | Service (verifier) 15 | ``` 16 | 17 | This demonstrator focuses on the remote provisioning of the password. The Redis server and client communicate in plain text, exposing the password to any man-in-the-middle attacker. To prevent this, the Redis server and client should also use an encrypted communication channel; either by enabling [TLS in Redis itself](https://github.com/antirez/redis/pull/4855/) or through Graphene's network shield. 18 | 19 | # Build 20 | 21 | Prepare everything by executing `make`. To avoid building Redis from source, specify the path to an existing Redis binary as follows: `export REDIS_SERVER_BINARY=/usr/bin/redis-server`. 22 | 23 | # Run 24 | 25 | Start the secret provisioning service with `./secret-provisioning-service`. A single service delivers secrets to multiple applications based on their SGX identity. 26 | 27 | Expose AESMD's domain socket via TCP such that it can be reached from within Graphene 28 | 29 | ``` bash 30 | socat -t10 TCP-LISTEN:1234,bind=127.0.0.1,reuseaddr,fork,range=127.0.0.0/8 UNIX-CLIENT:/var/run/aesmd/aesm.socket & 31 | ``` 32 | 33 | Start the Redis server with `make redis-server-run`. 34 | 35 | Redis prints a couple of messages after the secret provisioning service released the password. 36 | 37 | Test with `[redis/src/]redis-cli -a intelsgxrocks! ping`. [Output should be](https://redis.io/topics/rediscli) `PONG`. A different password will result in Redis telling you that the authentication failed. 38 | 39 | The [show-secrets](show-secrets.c) application demonstrates how to provision a secret to an environment variable (in addition to a secret command line argument). Run the application with `make show-secrets-run`. It will print some messages, that are hopefully self-explanatory. 40 | 41 | # Notes 42 | 43 | ## On weak vs strong symbols, dlsym and LD_PRELOAD 44 | 45 | For transparent provisioning of the secret password to Redis, we initially hoped to overload existing functions in Redis via LD_PRELOAD. However, LD_PRELOAD of course only works if the symbol you are trying to override is resolved dynamically which Redis' internal functions are not. LD_PRELOAD is only able to overwrite functions residing in shared libraries. 46 | 47 | ## Patching command-line arguments of Redis 48 | 49 | The current implementation patches command-line argument `--requirepass ` to Redis to inject the secret password. It relies on a clever trick to modify argv through a constructor in the shared library (cf. https://sourceware.org/ml/libc-help/2009-11/msg00006.html). Alternatively, one could create or modify the Redis configuration file (redis.conf) with the password. Note that the passing of argc, argv and envp to library constructors is glibc-specific behavior. 50 | -------------------------------------------------------------------------------- /README-ECDSA.md: -------------------------------------------------------------------------------- 1 | # ECDSA-based Attestation 2 | 3 | ECDSA-based attestation is an alternative to the EPID-based attestation model for environments where platform privacy is less of a concern and/or the specific deployment precludes interaction with external services (e.g., Intel Attestation Service) during the attestation process. The [ECDSA attestation white paper](https://software.intel.com/sites/default/files/managed/f1/b8/intel-sgx-support-for-third-party-attestation.pdf) provides additional information. In particular Section 3.1 describes the chain of trust from the platform-local attestation key to Intel. 4 | 5 | For RA-TLS, the main impact of ECDSA-based attestation is the different attestation evidence embedded in the RA-TLS certificate. The [RA-TLS whitepaper](whitepaper.pdf) has more details on this. 6 | 7 | ## Prerequisites 8 | 9 | Follow the official [installation instructions](https://01.org/intel-softwareguard-extensions/downloads/intel-sgx-dcap-linux-1.0.1-release) to prepare the system to compile the RA-TLS library and its sample programs. Ensure you can successfully run the [quote generation](https://github.com/intel/SGXDataCenterAttestationPrimitives/tree/master/SampleCode/QuoteGenerationSample) and [quote verification](https://github.com/intel/SGXDataCenterAttestationPrimitives/tree/master/QuoteVerification/Src) sample programs from the DCAP software distribution. Most notably, ECDSA attestation currently requires a different SGX kernel driver. Keep this in mind when switching between EPID and ECDSA. 10 | 11 | In particular, the Intel SGX Data Center Attestation Primitives (DCAP) come with their own SGX driver and require the SGX SDK v2.4. 12 | 13 | The Dockerfile [Dockerfile.template](Dockerfile.template) documents the software dependencies that must be installed on the system to successfully compile the RA-TLS library and its sample programs. 14 | 15 | To use ECDSA-based attestation an [API token must be acquired](https://api.portal.trustedservices.intel.com/provisioning-certification). The registration process will provide a subscription key for the ECDSA-related API endpoints. The script [ra_tls_options.c.sh](ra_tls_options.c.sh) generates a C source file with these values. Either define the environment variables before building or invoke the script manually before building, i.e., `ECDSA_SUBSCRIPTION_KEY=... bash ra_tls_options.c.sh`. See [ra_tls_options.c.sh](ra_tls_options.c.sh) for the specific variable format. 16 | 17 | ## Build 18 | 19 | We provide a [Dockerfile template](Dockerfile.template) to build everything in a container. To create the Docker image issue ```make docker-image```. Because Graphene by default builds its kernel module, kernel headers are required. The make target specializes the template Dockerfile (Dockerfile-ecdsa.template) to include headers for the host's kernel version. 20 | 21 | If the platform meets all the requirements for ECDSA-based attestation, EPID attestation should continue to work as expected. However, when switching between EPID and ECDSA, run "make mrproper" to reset the state before rebuilding the stack. 22 | 23 | ``` 24 | ECDSA=1 ./build.sh graphene && \ 25 | ECDSA=1 make wolfssl-ra-attester && \ 26 | ECDSA=1 make wolfssl-ra-challenger && \ 27 | make -C deps/SGXDataCenterAttestationPrimitives/SampleCode/QuoteServiceSample 28 | ``` 29 | 30 | Go get a coffee. It will take a while. 31 | 32 | ### Kernel Modules 33 | 34 | Two Linux kernel modules must be loaded for SGX and Graphene. 35 | 36 | The sources for the Intel SGX Linux driver for DCAP are located in ```deps/SGXDataCenterAttestationPrimitives/driver/linux/```. Build and load as usual: ```cd deps/SGXDataCenterAttestationPrimitives/driver/linux && make && sudo insmod intel_sgx.ko``` 37 | 38 | The Graphene driver sources are in ```deps/graphene/Pal/src/host/Linux-SGX/sgx-driver```. It is built automatically with the rest of Graphene. Load as usual: ```sudo insmod deps/graphene/Pal/src/host/Linux-SGX/sgx-driver/graphene-sgx.ko``` 39 | 40 | ## Run 41 | 42 | First, start the background service that connects application enclaves to the quoting enclave. The original DCAP library assumes a quoting enclave runs alongside each and every application enclave. To enable applications developed independently of the Intel SGX SDK to use the quoting enclave a service akin to AESMD is required for now. 43 | 44 | ``` 45 | deps/SGXDataCenterAttestationPrimitives/SampleCode/QuoteServiceSample/app & 46 | ``` 47 | 48 | We provide two sample programs to demonstrate ECDSA-based attestation within RA-TLS: An attester to generate an RA-TLS certificate and key; a challenger to verify the ECDSA-based RA-TLS certificate. 49 | 50 | To run the attester execute 51 | 52 | ``` 53 | deps/graphene/Runtime/pal-Linux-SGX ./wolfssl-ra-attester ecdsa 54 | ``` 55 | 56 | This program outputs an ECDSA-based RA-TLS certificate and the corresponding private key in ```crt.der``` and ```key.der```, respectively. 57 | 58 | To verify the RA-TLS certificate run 59 | 60 | ``` 61 | LD_LIBRARY_PATH=deps/local/lib ./wolfssl-ra-challenger crt.der 62 | ``` 63 | -------------------------------------------------------------------------------- /apps/secret-provisioning-example/redis-server-grab-secret.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "mbedtls/config.h" 8 | #include "mbedtls/net_sockets.h" 9 | #include "mbedtls/debug.h" 10 | #include "mbedtls/ssl.h" 11 | #include "mbedtls/entropy.h" 12 | #include "mbedtls/ctr_drbg.h" 13 | #include "mbedtls/error.h" 14 | #include "mbedtls/certs.h" 15 | 16 | #include "mbedtls-ra-attester.h" 17 | 18 | unsigned char secret[1024]; 19 | 20 | extern struct ra_tls_options my_ra_tls_options; 21 | 22 | static 23 | void ssl_read_exactly_n_bytes(mbedtls_ssl_context* ssl, unsigned char* p, int len) { 24 | int bytes_read = 0; 25 | int ret; 26 | do { 27 | ret = mbedtls_ssl_read(ssl, p + bytes_read, len - bytes_read); 28 | if (ret == MBEDTLS_ERR_SSL_WANT_READ || 29 | ret == MBEDTLS_ERR_SSL_WANT_WRITE) { 30 | continue; 31 | } 32 | 33 | assert(ret >= 0); 34 | if (ret == 0) break; 35 | bytes_read += ret; 36 | if (bytes_read == len) break; 37 | } while (1); 38 | assert(bytes_read == len); 39 | } 40 | 41 | int grab_secret_from_provisioning_service(int argc, char **argv, char **env) { 42 | (void)env; 43 | 44 | /* Connect to verifier / secret provisioning service. */ 45 | mbedtls_net_context srv_fd; 46 | const char *personalize = __FILE__; 47 | mbedtls_entropy_context entropy; 48 | mbedtls_ctr_drbg_context ctr_drbg; 49 | mbedtls_ssl_context ssl; 50 | mbedtls_ssl_config conf; 51 | mbedtls_x509_crt srvcert; 52 | 53 | mbedtls_x509_crt crt; 54 | mbedtls_pk_context key; 55 | 56 | mbedtls_net_init(&srv_fd); 57 | mbedtls_ssl_init(&ssl); 58 | mbedtls_ssl_config_init(&conf); 59 | mbedtls_ctr_drbg_init(&ctr_drbg); 60 | mbedtls_x509_crt_init(&srvcert); 61 | 62 | /* Generate RA-TLS certificate and key. */ 63 | mbedtls_x509_crt_init(&crt); 64 | mbedtls_pk_init(&key); 65 | mbedtls_create_key_and_x509(&key, &crt, &my_ra_tls_options); 66 | 67 | mbedtls_entropy_init(&entropy); 68 | assert(0 == mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, 69 | &entropy, 70 | (const unsigned char*) personalize, 71 | strlen(personalize))); 72 | 73 | 74 | assert(0 == mbedtls_net_connect(&srv_fd, "127.0.0.1", 75 | "12345", MBEDTLS_NET_PROTO_TCP)); 76 | 77 | assert(0 == mbedtls_ssl_config_defaults(&conf, 78 | MBEDTLS_SSL_IS_CLIENT, 79 | MBEDTLS_SSL_TRANSPORT_STREAM, 80 | MBEDTLS_SSL_PRESET_DEFAULT)); 81 | 82 | mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); 83 | mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); 84 | /* mbedtls_ssl_conf_dbg(&conf, my_debug, stdout); */ 85 | assert(0 == mbedtls_x509_crt_parse_file(&srvcert, "secret-provisioning-service-crt.pem")); 86 | 87 | mbedtls_ssl_conf_ca_chain(&conf, &srvcert, NULL); 88 | assert(0 == mbedtls_ssl_conf_own_cert(&conf, &crt, &key)); 89 | 90 | assert(0 == mbedtls_ssl_setup(&ssl, &conf)); 91 | mbedtls_ssl_set_bio(&ssl, &srv_fd, mbedtls_net_send, 92 | mbedtls_net_recv, NULL); 93 | 94 | int ret; 95 | while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { 96 | assert(ret == MBEDTLS_ERR_SSL_WANT_READ || 97 | ret == MBEDTLS_ERR_SSL_WANT_WRITE); 98 | } 99 | 100 | 101 | /* Grab secret from secret provisioning service. */ 102 | int32_t secret_size; 103 | ssl_read_exactly_n_bytes(&ssl, (unsigned char*) &secret_size, sizeof(secret_size)); 104 | assert(secret_size <= (int) sizeof(secret)); 105 | ssl_read_exactly_n_bytes(&ssl, (unsigned char*) secret, secret_size); 106 | 107 | printf(" > Provisioning successful. Secret is: %s\n", (char*)secret); 108 | 109 | /* Patch --requirepass command-line argument to point to obtained secret. */ 110 | const char* requirepass = "--requirepass"; 111 | for (int i = 0; i < argc; i++) { 112 | if ((strncmp(requirepass, argv[i], strlen(requirepass)) == 0) && (i + 1 < argc)) { 113 | printf(" > Found `%s `. Overwriting as `%s %s`\n", 114 | requirepass, requirepass, (char*)secret); 115 | argv[i + 1] = (char*) secret; 116 | } 117 | } 118 | 119 | return 0; 120 | } 121 | 122 | /* Passing argc, argv and envp to constructor functions is 123 | * glibc-specific behavior. This allows to intercept argc, argv, and 124 | * envp, and modify argv/enpv for our secret-provisioning purpose. */ 125 | __attribute__((section(".init_array"))) 126 | void *grab_secret_from_provisioning_service_constructor = &grab_secret_from_provisioning_service; 127 | -------------------------------------------------------------------------------- /openssl-client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "ra-challenger.h" 14 | 15 | int verify_callback 16 | ( 17 | int preverify_ok, 18 | X509_STORE_CTX *ctx 19 | ) 20 | { 21 | /* We expect OpenSSL's default verification logic to complain 22 | about a self-signed certificate. That's fine. */ 23 | X509* crt = X509_STORE_CTX_get_current_cert(ctx); 24 | if (preverify_ok == 0) { 25 | int err = X509_STORE_CTX_get_error(ctx); 26 | assert(err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT); 27 | } 28 | 29 | int der_len = i2d_X509(crt, NULL); 30 | assert(der_len > 0); 31 | 32 | unsigned char der[der_len]; 33 | unsigned char *p = der; 34 | i2d_X509(crt, &p); 35 | 36 | int rc = verify_sgx_cert_extensions(der, der_len); 37 | printf("Verifying SGX certificate extensions ... %s\n", rc == 0 ? "Success" : "Fail"); 38 | return !rc; 39 | } 40 | 41 | static 42 | void print_sgx_crt_info(X509* crt) { 43 | int der_len = i2d_X509(crt, NULL); 44 | assert(der_len > 0); 45 | 46 | unsigned char der[der_len]; 47 | unsigned char *p = der; 48 | i2d_X509(crt, &p); 49 | 50 | sgx_quote_t quote; 51 | get_quote_from_cert(der, der_len, "e); 52 | sgx_report_body_t* body = "e.report_body; 53 | 54 | printf("Certificate's SGX information:\n"); 55 | printf(" . MRENCLAVE = "); 56 | for (int i=0; i < SGX_HASH_SIZE; ++i) printf("%02x", body->mr_enclave.m[i]); 57 | printf("\n"); 58 | 59 | printf(" . MRSIGNER = "); 60 | for (int i=0; i < SGX_HASH_SIZE; ++i) printf("%02x", body->mr_signer.m[i]); 61 | printf("\n"); 62 | } 63 | 64 | static char* host = (char*) "localhost"; 65 | static int port = 443; 66 | 67 | static 68 | void parse_arguments(int argc, char** argv) { 69 | static struct option opts[] = { 70 | {"port", required_argument, 0, 'p'}, 71 | {"hostname/IP", required_argument, 0, 'h'} 72 | }; 73 | 74 | while (1) { 75 | int c; 76 | int option_index = 0; 77 | 78 | c = getopt_long(argc, argv, "p:h:", opts, &option_index); 79 | 80 | /* Detect the end of the options. */ 81 | if (c == -1) 82 | break; 83 | 84 | switch (c) { 85 | case 'p': 86 | port = atoi(optarg); 87 | break; 88 | case 'h': 89 | host = optarg; 90 | break; 91 | } 92 | } 93 | } 94 | 95 | int main(int argc, char **argv) 96 | { 97 | (void) argc; 98 | (void) argv; 99 | 100 | int ret; 101 | 102 | parse_arguments(argc, argv); 103 | 104 | SSL_load_error_strings(); 105 | ERR_load_crypto_strings(); 106 | 107 | OpenSSL_add_all_algorithms(); 108 | SSL_library_init(); 109 | 110 | SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_client_method()); 111 | assert(ctx != NULL); 112 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, &verify_callback); 113 | 114 | BIO *bio = BIO_new_ssl_connect(ctx); 115 | assert(bio != NULL); 116 | 117 | SSL *ssl; 118 | BIO_get_ssl(bio, &ssl); 119 | SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 120 | 121 | char hostname[255]; 122 | ret = snprintf(hostname, sizeof(hostname), "%s:%d:https", host, port); 123 | assert(ret > 0); 124 | BIO_set_conn_hostname(bio, hostname); 125 | 126 | if (BIO_do_connect(bio) <= 0) { 127 | BIO_free_all(bio); 128 | printf("errored; unable to connect.\n"); 129 | ERR_print_errors_fp(stderr); 130 | return -1; 131 | } 132 | 133 | X509* crt = SSL_get_peer_certificate(ssl); 134 | print_sgx_crt_info(crt); 135 | 136 | char request[1024] = {0, }; 137 | strcpy(request, "GET / HTTP/1.1\r\n\r\n"); 138 | 139 | fcntl(0, F_SETFL, O_NONBLOCK); 140 | ssize_t sz = read(0, request, sizeof(request)); 141 | /* Do not check for errors, since there may well be no input. */ 142 | assert(sz < (ssize_t) sizeof(request)); /* Input too large. */ 143 | 144 | if (BIO_puts(bio, request) <= 0) { 145 | BIO_free_all(bio); 146 | printf("errored; unable to write.\n"); 147 | ERR_print_errors_fp(stderr); 148 | return -1; 149 | } 150 | 151 | char tmpbuf[1024+1]; 152 | 153 | for (;;) { 154 | int ssllen = BIO_read(bio, tmpbuf, 1024); 155 | if (ssllen == 0) { 156 | break; 157 | } else if (ssllen < 0) { 158 | if (!BIO_should_retry(bio)) { 159 | printf("errored; read failed.\n"); 160 | ERR_print_errors_fp(stderr); 161 | break; 162 | } 163 | } else { 164 | tmpbuf[ssllen] = 0; 165 | printf("%s", tmpbuf); 166 | } 167 | } 168 | 169 | BIO_free_all(bio); 170 | 171 | return 0; 172 | } 173 | -------------------------------------------------------------------------------- /mbedtls-ssl-server.patch: -------------------------------------------------------------------------------- 1 | diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c 2 | index fd54f17..9a2f1ea 100644 3 | --- a/programs/ssl/ssl_server.c 4 | +++ b/programs/ssl/ssl_server.c 5 | @@ -73,13 +73,13 @@ int main( void ) 6 | #include "mbedtls/ssl_cache.h" 7 | #endif 8 | 9 | -#define HTTP_RESPONSE \ 10 | - "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ 11 | - "

mbed TLS Test Server

\r\n" \ 12 | - "

Successful connection using: %s

\r\n" 13 | - 14 | #define DEBUG_LEVEL 0 15 | 16 | +#include 17 | + 18 | +#include "mbedtls-ra-attester.h" 19 | +#include "ra-challenger.h" 20 | + 21 | static void my_debug( void *ctx, int level, 22 | const char *file, int line, 23 | const char *str ) 24 | @@ -90,6 +90,8 @@ static void my_debug( void *ctx, int level, 25 | fflush( (FILE *) ctx ); 26 | } 27 | 28 | +extern struct ra_tls_options my_ra_tls_options; 29 | + 30 | int main( void ) 31 | { 32 | int ret, len; 33 | @@ -119,54 +121,25 @@ int main( void ) 34 | mbedtls_entropy_init( &entropy ); 35 | mbedtls_ctr_drbg_init( &ctr_drbg ); 36 | 37 | -#if defined(MBEDTLS_DEBUG_C) 38 | mbedtls_debug_set_threshold( DEBUG_LEVEL ); 39 | -#endif 40 | 41 | /* 42 | - * 1. Load the certificates and private RSA key 43 | + * 1. Generate the certificate and private RSA key 44 | */ 45 | - mbedtls_printf( "\n . Loading the server cert. and key..." ); 46 | + mbedtls_printf( "\n . Generating the server cert. and key..." ); 47 | fflush( stdout ); 48 | 49 | - /* 50 | - * This demonstration program uses embedded test certificates. 51 | - * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the 52 | - * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). 53 | - */ 54 | - ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, 55 | - mbedtls_test_srv_crt_len ); 56 | - if( ret != 0 ) 57 | - { 58 | - mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); 59 | - goto exit; 60 | - } 61 | - 62 | - ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, 63 | - mbedtls_test_cas_pem_len ); 64 | - if( ret != 0 ) 65 | - { 66 | - mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); 67 | - goto exit; 68 | - } 69 | - 70 | - ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, 71 | - mbedtls_test_srv_key_len, NULL, 0 ); 72 | - if( ret != 0 ) 73 | - { 74 | - mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); 75 | - goto exit; 76 | - } 77 | + mbedtls_create_key_and_x509(&pkey, &srvcert, &my_ra_tls_options); 78 | 79 | mbedtls_printf( " ok\n" ); 80 | 81 | /* 82 | * 2. Setup the listening TCP socket 83 | */ 84 | - mbedtls_printf( " . Bind on https://localhost:4433/ ..." ); 85 | + mbedtls_printf( " . Bind on https://localhost:11111/ ..." ); 86 | fflush( stdout ); 87 | 88 | - if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) 89 | + if( ( ret = mbedtls_net_bind( &listen_fd, "127.0.0.1", "11111", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) 90 | { 91 | mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); 92 | goto exit; 93 | @@ -252,7 +225,10 @@ reset: 94 | if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, 95 | NULL, 0, NULL ) ) != 0 ) 96 | { 97 | + char errbuf[512]; 98 | + mbedtls_strerror(ret, errbuf, sizeof(errbuf)); 99 | mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); 100 | + mbedtls_printf("%s\n", errbuf); 101 | goto exit; 102 | } 103 | 104 | @@ -326,8 +302,25 @@ reset: 105 | mbedtls_printf( " > Write to client:" ); 106 | fflush( stdout ); 107 | 108 | - len = sprintf( (char *) buf, HTTP_RESPONSE, 109 | - mbedtls_ssl_get_ciphersuite( &ssl ) ); 110 | + sgx_quote_t quote; 111 | + get_quote_from_cert(srvcert.raw.p, srvcert.raw.len, "e); 112 | + sgx_report_body_t* body = "e.report_body; 113 | + 114 | + char mrenclave_hex_str[SGX_HASH_SIZE * 2 + 1] = {0, }; 115 | + char mrsigner_hex_str[SGX_HASH_SIZE * 2 + 1] = {0, }; 116 | + for (int i = 0; i < SGX_HASH_SIZE; ++i) { 117 | + sprintf(&mrenclave_hex_str[i*2], "%02x", body->mr_enclave.m[i]); 118 | + sprintf(&mrsigner_hex_str[i*2], "%02x", body->mr_signer.m[i]); 119 | + } 120 | + 121 | + const char* http_response = "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ 122 | + "

mbed TLS Test Server

\r\n" \ 123 | + "

Successful connection using: %s
\r\n" \ 124 | + "MRENCLAVE is %s
\r\nMRSIGNER is %s

\r\n"; 125 | + 126 | + len = snprintf((char *) buf, sizeof (buf) - 1, http_response, 127 | + mbedtls_ssl_get_ciphersuite(&ssl), 128 | + mrenclave_hex_str, mrsigner_hex_str); 129 | 130 | while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 ) 131 | { 132 | @@ -345,7 +338,7 @@ reset: 133 | } 134 | 135 | len = ret; 136 | - mbedtls_printf( " %d bytes written\n\n%s\n", len, (char *) buf ); 137 | + mbedtls_printf(" %d bytes written\n", len); 138 | 139 | mbedtls_printf( " . Closing the connection..." ); 140 | 141 | -------------------------------------------------------------------------------- /sgxlkl/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all: 3 | $(MAKE) sgx-lkl/apps/ratls/sgxlkl-miniroot-fs.img 4 | $(MAKE) sgx-lkl/apps/https-server/sgxlkl-miniroot-fs.img 5 | 6 | .PHONY: sgx-lkl 7 | sgx-lkl: 8 | [ ! -d $@ ] && git clone https://github.com/lsds/sgx-lkl.git || true 9 | cd sgx-lkl && git checkout 2c0aa8a41178637ac8f4dabd8f7f02a5b47eed90 10 | cd sgx-lkl && $(MAKE) -j1 11 | cd sgx-lkl && $(MAKE) -j1 sgx-lkl-sign 12 | 13 | SRC=../wolfssl-ra-attester.c \ 14 | ../wolfssl-ra.c \ 15 | ../ias_sign_ca_cert.c \ 16 | ../ias-ra.c \ 17 | ../nonsdk-ra-attester.c \ 18 | ../messages.pb-c.c \ 19 | ../sgx_report.S \ 20 | ../ra_tls_options.c 21 | 22 | INCLUDES=-I.. -Ilocal/include -I/opt/intel/sgxsdk/include \ 23 | -I../deps/linux-sgx/common/inc \ 24 | -I../deps/linux-sgx/common/inc/internal \ 25 | -I../deps/linux-sgx/external/epid-sdk 26 | 27 | ### Dependencies 28 | 29 | MUSLCC=$(abspath sgx-lkl/build/host-musl/bin/musl-gcc) 30 | 31 | .PHONY: deps 32 | deps: deps/zlib deps/curl deps/protobuf-c deps/wolfssl 33 | 34 | deps/zlib: | sgx-lkl 35 | mkdir -p deps && cd deps && git clone https://github.com/madler/zlib.git 36 | cd $@ && CFLAGS=-fPIC CC=$(MUSLCC) ./configure --prefix=$(abspath local) --static 37 | cd $@ && $(MAKE) install 38 | 39 | # curl version 7_47_0 seems to work in combination with Intel's HTTPS proxy ... 40 | deps/curl: deps/wolfssl | sgx-lkl 41 | mkdir -p deps && cd deps && git clone https://github.com/curl/curl.git 42 | cd $@ && git checkout curl-7_47_0 43 | cd $@ && ./buildconf 44 | cd $@ && CC=$(MUSLCC) ./configure --prefix=$(abspath local) --without-libidn --without-librtmp --without-libssh2 --without-libmetalink --without-libpsl --without-ssl --with-cyassl=$(abspath local) --disable-shared --with-pic 45 | cd $@ && $(MAKE) install 46 | 47 | deps/protobuf-c: | sgx-lkl 48 | mkdir -p deps && cd deps && git clone https://github.com/protobuf-c/protobuf-c.git 49 | cd $@ && ./autogen.sh 50 | cd $@ && CC=$(MUSLCC) ./configure --prefix=$(abspath local) --disable-shared --with-pic 51 | cd $@ && $(MAKE) protobuf-c/libprotobuf-c.la 52 | cd $@ && mkdir -p ../../local/lib ../../local/include/protobuf-c 53 | cd $@ && cp protobuf-c/.libs/libprotobuf-c.a ../../local/lib 54 | cd $@ && cp protobuf-c/protobuf-c.h ../../local/include/protobuf-c 55 | 56 | deps/wolfssl: | sgx-lkl 57 | mkdir -p deps && cd deps && git clone https://github.com/wolfSSL/wolfssl 58 | cd $@ && git checkout 57e5648a5dd734d1c219d385705498ad12941dd0 59 | cd $@ && patch -p1 < ../../../wolfssl.patch 60 | cd $@ && ./autogen.sh 61 | cd $@ && CC=$(MUSLCC) CFLAGS="-fPIC -DWOLFSSL_SGX_ATTESTATION -DWOLFSSL_ALWAYS_VERIFY_CB -DKEEP_PEER_CERT" ./configure --prefix=$(abspath local) --enable-writedup --enable-static --disable-shared --enable-keygen --enable-certgen --enable-certext --enable-tlsv10 # --enable-debug 62 | cd $@ && $(MAKE) install 63 | 64 | ldpreload.so: CFLAGS+=-DUSE_WOLFSSL 65 | ldpreload.so: ldpreload.c $(SRC) | sgx-lkl deps 66 | sgx-lkl/build/host-musl/bin/musl-gcc -o $@ $^ $(CFLAGS) $(INCLUDES) $(CFLAGSERRORS) -shared -fPIC -Llocal/lib -l:libcurl.a -l:libwolfssl.a -l:libprotobuf-c.a -l:libm.a -l:libz.a -ldl 67 | 68 | sgx-lkl/apps/ratls/Makefile: | sgx-lkl 69 | cp -a ratls sgx-lkl/apps 70 | 71 | sgx-lkl/apps/https-server/Makefile: | sgx-lkl 72 | cp -a https-server/ sgx-lkl/apps 73 | 74 | sgx-lkl/apps/ratls/sgxlkl-miniroot-fs.img: ../sgxlkl-wolfssl-ssl-server sgx-lkl/apps/ratls/Makefile 75 | ( cd sgx-lkl/apps/ratls && USER=`whoami` make ) 76 | 77 | sgx-lkl/apps/https-server/sgxlkl-miniroot-fs.img: ldpreload.so sgx-lkl/apps/https-server/Makefile 78 | ( cd sgx-lkl/apps/https-server && USER=`whoami` make ) 79 | 80 | ../sgxlkl-wolfssl-ssl-server: | sgx-lkl deps 81 | $(MAKE) -C .. sgxlkl-wolfssl-ssl-server 82 | 83 | .PHONY: clean 84 | clean: 85 | $(MAKE) -C sgx-lkl 86 | 87 | .PHONY: distclean 88 | distclean: 89 | $(RM) ldpreload.so 90 | $(RM) -r sgx-lkl deps/zlib deps/curl deps/protobuf-c deps/wolfssl local 91 | 92 | EXTERNAL_IFACE ?= eth0 93 | .PHONY: up-sgxlkl-network 94 | up-sgxlkl-network: 95 | sudo ip tuntap add dev sgxlkl_tap0 mode tap user `whoami` 96 | sudo ip link set dev sgxlkl_tap0 up 97 | sudo ip addr add dev sgxlkl_tap0 10.0.1.254/24 98 | sudo iptables -I FORWARD -i sgxlkl_tap0 -o $(EXTERNAL_IFACE) -s 10.0.1.0/24 -m conntrack --ctstate NEW -j ACCEPT 99 | sudo iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 100 | sudo iptables -t nat -I POSTROUTING -o $(EXTERNAL_IFACE) -j MASQUERADE 101 | socat -t10 TCP-LISTEN:1234,bind=10.0.1.254,reuseaddr,fork,range=10.0.1.0/8 UNIX-CLIENT:/var/run/aesmd/aesm.socket & 102 | 103 | .PHONY: down-sgxlkl-network 104 | down-sgxlkl-network: 105 | sudo iptables -t nat -D POSTROUTING -o $(EXTERNAL_IFACE) -j MASQUERADE 106 | sudo iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 107 | sudo iptables -D FORWARD -s 10.0.1.0/24 -i sgxlkl_tap0 -o $(EXTERNAL_IFACE) -m conntrack --ctstate NEW -j ACCEPT 108 | sudo ip tuntap del dev sgxlkl_tap0 mode tap 109 | pkill -f TCP-LISTEN:1234 110 | 111 | .PHONY: run-https-server 112 | run-https-server: sgx-lkl/apps/https-server/sgxlkl-miniroot-fs.img 113 | LD_PRELOAD=/ldpreload.so SGXLKL_TAP=sgxlkl_tap0 RATLS_AESMD_IP=10.0.1.254 SGXLKL_HEAP=268435456 SGXLKL_KEY=$(abspath sgx-lkl/build/config/enclave_debug.key ) sgx-lkl/build/sgx-lkl-run sgx-lkl/apps/https-server/sgxlkl-miniroot-fs.img /usr/bin/python /https-server.py 114 | 115 | .PHONY: run-wolfssl-server 116 | run-wolfssl-server: sgx-lkl/apps/ratls/sgxlkl-miniroot-fs.img 117 | SGXLKL_TAP=sgxlkl_tap0 SGXLKL_VERBOSE=1 RATLS_AESMD_IP=10.0.1.254 sgx-lkl/build/sgx-lkl-run sgx-lkl/apps/ratls/sgxlkl-miniroot-fs.img /sgxlkl-wolfssl-ssl-server 118 | -------------------------------------------------------------------------------- /README-ECDSA.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

ECDSA-based Attestation

12 |

ECDSA-based attestation is an alternative to the EPID-based attestation model for environments where platform privacy is less of a concern and/or the specific deployment precludes interaction with external services (e.g., Intel Attestation Service) during the attestation process. The ECDSA attestation white paper provides additional information. In particular Section 3.1 describes the chain of trust from the platform-local attestation key to Intel.

13 |

For RA-TLS, the main impact of ECDSA-based attestation is the different attestation evidence embedded in the RA-TLS certificate. The RA-TLS whitepaper has more details on this.

14 |

Prerequisites

15 |

Follow the official installation instructions to prepare the system to compile the RA-TLS library and its sample programs. Ensure you can successfully run the quote generation and quote verification sample programs from the DCAP software distribution. Most notably, ECDSA attestation currently requires a different SGX kernel driver. Keep this in mind when switching between EPID and ECDSA.

16 |

In particular, the Intel SGX Data Center Attestation Primitives (DCAP) come with their own SGX driver and require the SGX SDK v2.4.

17 |

The Dockerfile Dockerfile.template documents the software dependencies that must be installed on the system to successfully compile the RA-TLS library and its sample programs.

18 |

To use ECDSA-based attestation an API token must be acquired. The registration process will provide a subscription key for the ECDSA-related API endpoints. The script ra_tls_options.c.sh generates a C source file with these values. Either define the environment variables before building or invoke the script manually before building, i.e., ECDSA_SUBSCRIPTION_KEY=... bash ra_tls_options.c.sh. See ra_tls_options.c.sh for the specific variable format.

19 |

Build

20 |

We provide a Dockerfile template to build everything in a container. To create the Docker image issue make docker-image. Because Graphene by default builds its kernel module, kernel headers are required. The make target specializes the template Dockerfile (Dockerfile-ecdsa.template) to include headers for the host's kernel version.

21 |

If the platform meets all the requirements for ECDSA-based attestation, EPID attestation should continue to work as expected. However, when switching between EPID and ECDSA, run "make mrproper" to reset the state before rebuilding the stack.

22 |
ECDSA=1 ./build.sh graphene && \
23 | ECDSA=1 make wolfssl-ra-attester && \
24 | ECDSA=1 make wolfssl-ra-challenger && \
25 | make -C deps/SGXDataCenterAttestationPrimitives/SampleCode/QuoteServiceSample
26 |

Go get a coffee. It will take a while.

27 |

Kernel Modules

28 |

Two Linux kernel modules must be loaded for SGX and Graphene.

29 |

The sources for the Intel SGX Linux driver for DCAP are located in deps/SGXDataCenterAttestationPrimitives/driver/linux/. Build and load as usual: cd deps/SGXDataCenterAttestationPrimitives/driver/linux && make && sudo insmod intel_sgx.ko

30 |

The Graphene driver sources are in deps/graphene/Pal/src/host/Linux-SGX/sgx-driver. It is built automatically with the rest of Graphene. Load as usual: sudo insmod deps/graphene/Pal/src/host/Linux-SGX/sgx-driver/graphene-sgx.ko

31 |

Run

32 |

First, start the background service that connects application enclaves to the quoting enclave. The original DCAP library assumes a quoting enclave runs alongside each and every application enclave. To enable applications developed independently of the Intel SGX SDK to use the quoting enclave a service akin to AESMD is required for now.

33 |
deps/SGXDataCenterAttestationPrimitives/SampleCode/QuoteServiceSample/app &
34 |

We provide two sample programs to demonstrate ECDSA-based attestation within RA-TLS: An attester to generate an RA-TLS certificate and key; a challenger to verify the ECDSA-based RA-TLS certificate.

35 |

To run the attester execute

36 |
deps/graphene/Runtime/pal-Linux-SGX ./wolfssl-ra-attester ecdsa
37 |

This program outputs an ECDSA-based RA-TLS certificate and the corresponding private key in crt.der and key.der, respectively.

38 |

To verify the RA-TLS certificate run

39 |
LD_LIBRARY_PATH=deps/local/lib ./wolfssl-ra-challenger crt.der
40 | 41 | 42 | -------------------------------------------------------------------------------- /openssl-ra-attester.c: -------------------------------------------------------------------------------- 1 | /* Code to create an extended X.509 certificate with OpenSSL. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include "ra-attester.h" 14 | #include "ra.h" 15 | #include "ra_private.h" 16 | #include "ra-challenger_private.h" 17 | 18 | static const uint32_t SHA256_DIGEST_SIZE = 256 / 8; 19 | 20 | /** 21 | * Caller must allocate memory for certificate. 22 | * 23 | * @param der_crt_len On entry contains the size of der_crt buffer. On return holds actual size of certificate in bytes. 24 | */ 25 | static 26 | void generate_x509 27 | ( 28 | EVP_PKEY* key, /* in */ 29 | uint8_t* der_crt, /* out */ 30 | int* der_crt_len, /* in/out */ 31 | attestation_verification_report_t* attn_report 32 | ) 33 | { 34 | X509* crt; 35 | crt = X509_new(); 36 | 37 | X509_set_version(crt, 2); 38 | X509_gmtime_adj(X509_get_notBefore(crt), 0); 39 | X509_gmtime_adj(X509_get_notAfter(crt), 31536000L); 40 | 41 | X509_set_pubkey(crt, key); 42 | 43 | X509_NAME* name; 44 | name = X509_get_subject_name(crt); 45 | 46 | X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, 47 | (unsigned char *)"US", -1, -1, 0); 48 | X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, 49 | (unsigned char *)"OR", -1, -1, 0); 50 | X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, 51 | (unsigned char *)"Hillsboro", -1, -1, 0); 52 | X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, 53 | (unsigned char *)"Intel Inc.", -1, -1, 0); 54 | X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, 55 | (unsigned char *)"Intel Labs", -1, -1, 0); 56 | X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, 57 | (unsigned char *)"SGX rocks!", -1, -1, 0); 58 | 59 | X509_set_issuer_name(crt, name); 60 | 61 | ASN1_OBJECT obj = { .data = ias_response_body_oid + 2, 62 | .length = ias_oid_len - 2 }; 63 | ASN1_OCTET_STRING val = { .data = attn_report->ias_report, 64 | .length = attn_report->ias_report_len}; 65 | X509_EXTENSION ex = { &obj, 0, &val }; 66 | X509_add_ext(crt, &ex, -1); 67 | 68 | obj.data = ias_root_cert_oid + 2; 69 | val.data = attn_report->ias_sign_ca_cert; 70 | val.length = attn_report->ias_sign_ca_cert_len; 71 | X509_add_ext(crt, &ex, -1); 72 | 73 | obj.data = ias_leaf_cert_oid + 2; 74 | val.data = attn_report->ias_sign_cert; 75 | val.length = attn_report->ias_sign_cert_len; 76 | X509_add_ext(crt, &ex, -1); 77 | 78 | obj.data = ias_report_signature_oid + 2; 79 | val.data = attn_report->ias_report_signature; 80 | val.length = attn_report->ias_report_signature_len; 81 | X509_add_ext(crt, &ex, -1); 82 | 83 | X509_sign(crt, key, EVP_sha256()); 84 | 85 | /* Encode X509 as DER. */ 86 | int len = i2d_X509(crt, NULL); 87 | assert(len <= *der_crt_len); 88 | i2d_X509(crt, &der_crt); 89 | *der_crt_len = len; 90 | 91 | X509_free(crt); 92 | crt = NULL; 93 | } 94 | 95 | void sha256_rsa_pubkey 96 | ( 97 | unsigned char hash[SHA256_DIGEST_SIZE], 98 | RSA* key 99 | ) 100 | { 101 | int len = i2d_RSAPublicKey(key, NULL); 102 | assert(len > 0); 103 | assert(len == rsa_pub_3072_raw_der_len); 104 | 105 | unsigned char buf[len]; 106 | unsigned char* p = buf; 107 | len = i2d_RSAPublicKey(key, &p); 108 | 109 | unsigned char md_value[EVP_MAX_MD_SIZE]; 110 | uint32_t md_len; 111 | 112 | EVP_MD_CTX* mdctx = EVP_MD_CTX_create(); 113 | const EVP_MD* md = EVP_sha256(); 114 | EVP_DigestInit_ex(mdctx, md, NULL); 115 | EVP_DigestUpdate(mdctx, buf, len); 116 | EVP_DigestFinal_ex(mdctx, md_value, &md_len); 117 | assert(md_len == SHA256_DIGEST_SIZE); 118 | EVP_MD_CTX_destroy(mdctx); 119 | memcpy(hash, md_value, SHA256_DIGEST_SIZE); 120 | } 121 | 122 | static void 123 | openssl_create_key_and_x509 124 | ( 125 | uint8_t* der_key, 126 | int* der_key_len, 127 | uint8_t* der_cert, 128 | int* der_cert_len, 129 | const struct ra_tls_options* opts 130 | ) 131 | { 132 | /* Generate key. */ 133 | RSA* key; 134 | 135 | static const int nr_bits = 3072; 136 | key = RSA_generate_key(nr_bits, RSA_F4, NULL, NULL); 137 | assert(NULL != key); 138 | 139 | uint8_t der[4096]; 140 | int derSz = i2d_RSAPrivateKey(key, NULL); 141 | assert(derSz >= 0); 142 | assert(derSz <= (int) *der_key_len); 143 | unsigned char* p = der; 144 | i2d_RSAPrivateKey(key, &p); 145 | 146 | *der_key_len = derSz; 147 | memcpy(der_key, der, derSz); 148 | 149 | /* Generate certificate */ 150 | sgx_report_data_t report_data = {0, }; 151 | sha256_rsa_pubkey(report_data.d, key); 152 | attestation_verification_report_t attestation_report; 153 | 154 | do_remote_attestation(&report_data, opts, &attestation_report); 155 | 156 | EVP_PKEY* evp_key = EVP_PKEY_new(); 157 | EVP_PKEY_assign_RSA(evp_key, key); 158 | generate_x509(evp_key, der_cert, der_cert_len, 159 | &attestation_report); 160 | EVP_PKEY_free(evp_key); 161 | evp_key = NULL; 162 | } 163 | 164 | void create_key_and_x509 165 | ( 166 | uint8_t* der_key, /* out */ 167 | int* der_key_len, /* in/out */ 168 | uint8_t* der_cert, /* out */ 169 | int* der_cert_len, /* in/out */ 170 | const struct ra_tls_options* opts /* in */ 171 | ) 172 | { 173 | openssl_create_key_and_x509(der_key, der_key_len, 174 | der_cert, der_cert_len, 175 | opts); 176 | } 177 | -------------------------------------------------------------------------------- /00-graphene-flexible-launch-control.patch: -------------------------------------------------------------------------------- 1 | diff --git a/LibOS/shim/test/native/manifest.template b/LibOS/shim/test/native/manifest.template 2 | index 6714c1c..021304e 100644 3 | --- a/LibOS/shim/test/native/manifest.template 4 | +++ b/LibOS/shim/test/native/manifest.template 5 | @@ -27,3 +27,4 @@ sgx.trusted_files.libm = file:$(LIBCDIR)/libm.so.6 6 | sgx.trusted_files.libpthread = file:$(LIBCDIR)/libpthread.so.0 7 | 8 | sgx.trusted_files.unix_pipe = file:unix.c 9 | +sgx.disable_avx = 1 10 | \ No newline at end of file 11 | diff --git a/LibOS/shim/test/native/static.manifest.template b/LibOS/shim/test/native/static.manifest.template 12 | index 832b733..44cfab3 100644 13 | --- a/LibOS/shim/test/native/static.manifest.template 14 | +++ b/LibOS/shim/test/native/static.manifest.template 15 | @@ -5,3 +5,5 @@ loader.debug_type = inline 16 | fs.mount.lib.type = chroot 17 | fs.mount.lib.path = /lib 18 | fs.mount.lib.uri = file:$(LIBCDIR) 19 | + 20 | +sgx.disable_avx = 1 21 | \ No newline at end of file 22 | diff --git a/Pal/src/host/Linux-SGX/sgx_framework.c b/Pal/src/host/Linux-SGX/sgx_framework.c 23 | index 7a63a0e..794b6bd 100644 24 | --- a/Pal/src/host/Linux-SGX/sgx_framework.c 25 | +++ b/Pal/src/host/Linux-SGX/sgx_framework.c 26 | @@ -12,7 +12,7 @@ 27 | 28 | int gsgx_device = -1; 29 | int isgx_device = -1; 30 | -#define ISGX_FILE "/dev/isgx" 31 | +#define ISGX_FILE "/dev/sgx" 32 | 33 | void * zero_page; 34 | 35 | @@ -125,7 +125,7 @@ bool is_wrfsbase_supported (void) 36 | int create_enclave(sgx_arch_secs_t * secs, 37 | unsigned long baseaddr, 38 | unsigned long size, 39 | - sgx_arch_token_t * token) 40 | + sgx_arch_sigstruct_t * sigstruct) 41 | { 42 | int flags = MAP_SHARED; 43 | 44 | @@ -142,9 +142,9 @@ int create_enclave(sgx_arch_secs_t * secs, 45 | secs->size = pagesize; 46 | while (secs->size < size) 47 | secs->size <<= 1; 48 | - secs->ssaframesize = get_ssaframesize(token->attributes.xfrm) / pagesize; 49 | - secs->miscselect = token->miscselect_mask; 50 | - memcpy(&secs->attributes, &token->attributes, 51 | + secs->ssaframesize = get_ssaframesize(sigstruct->attributes.xfrm) / pagesize; 52 | + secs->miscselect = sigstruct->miscselect_mask; 53 | + memcpy(&secs->attributes, &sigstruct->attributes, 54 | sizeof(sgx_arch_attributes_t)); 55 | /* Do not initialize secs->mrsigner and secs->mrenclave here as they are 56 | * not used by ECREATE to populate the internal SECS. SECS's mrenclave is 57 | @@ -323,7 +323,14 @@ int init_enclave(sgx_arch_secs_t * secs, 58 | SGX_DBG(DBG_I, " %02x", sigstruct->enclave_hash[i]); 59 | SGX_DBG(DBG_I, "\n"); 60 | 61 | -#if SDK_DRIVER_VERSION >= KERNEL_VERSION(1, 8, 0) 62 | +#if SDK_DRIVER_VERSION >= KERNEL_VERSION(2, 4, 0) 63 | + struct sgx_enclave_init param = { 64 | + .addr = enclave_valid_addr, 65 | + .sigstruct = (uint64_t) sigstruct 66 | + }; 67 | + int ret = INLINE_SYSCALL(ioctl, 3, isgx_device, SGX_IOC_ENCLAVE_INIT, 68 | + ¶m); 69 | +#elif SDK_DRIVER_VERSION >= KERNEL_VERSION(1, 8, 0) 70 | struct sgx_enclave_init param = { 71 | .addr = enclave_valid_addr, 72 | .sigstruct = (uint64_t) sigstruct, 73 | diff --git a/Pal/src/host/Linux-SGX/sgx_internal.h b/Pal/src/host/Linux-SGX/sgx_internal.h 74 | index 4f39167..deac00b 100644 75 | --- a/Pal/src/host/Linux-SGX/sgx_internal.h 76 | +++ b/Pal/src/host/Linux-SGX/sgx_internal.h 77 | @@ -91,7 +91,7 @@ int read_enclave_sigstruct (int sigfile, sgx_arch_sigstruct_t * sig); 78 | int create_enclave(sgx_arch_secs_t * secs, 79 | unsigned long base, 80 | unsigned long size, 81 | - sgx_arch_token_t * token); 82 | + sgx_arch_sigstruct_t * sigstruct); 83 | 84 | enum sgx_page_type { SGX_PAGE_SECS, SGX_PAGE_TCS, SGX_PAGE_REG }; 85 | int add_pages_to_enclave(sgx_arch_secs_t * secs, 86 | diff --git a/Pal/src/host/Linux-SGX/sgx_main.c b/Pal/src/host/Linux-SGX/sgx_main.c 87 | index 9a5a573..4210a1f 100644 88 | --- a/Pal/src/host/Linux-SGX/sgx_main.c 89 | +++ b/Pal/src/host/Linux-SGX/sgx_main.c 90 | @@ -290,11 +290,11 @@ int initialize_enclave (struct pal_enclave * enclave) 91 | else 92 | enclave->baseaddr = heap_min = 0; 93 | 94 | - TRY(read_enclave_token, enclave->token, &enclave_token); 95 | + //TRY(read_enclave_token, enclave->token, &enclave_token); 96 | TRY(read_enclave_sigstruct, enclave->sigfile, &enclave_sigstruct); 97 | 98 | TRY(create_enclave, 99 | - &enclave_secs, enclave->baseaddr, enclave->size, &enclave_token); 100 | + &enclave_secs, enclave->baseaddr, enclave->size, &enclave_sigstruct); 101 | 102 | enclave->baseaddr = enclave_secs.baseaddr; 103 | enclave->size = enclave_secs.size; 104 | @@ -762,15 +762,16 @@ static int load_enclave (struct pal_enclave * enclave, 105 | } 106 | 107 | uri = alloc_concat(uri, strlen(uri) - 4, ".token", -1); 108 | - enclave->token = INLINE_SYSCALL(open, 3, uri + 5, O_RDONLY|O_CLOEXEC, 0); 109 | - if (IS_ERR(enclave->token)) { 110 | - SGX_DBG(DBG_E, "cannot open token \'%s\'. Use \'" 111 | - PAL_FILE("pal-sgx-get-token") 112 | - "\' on the runtime host, or run \'make SGX_RUN=1\' " 113 | - "in the Graphene source, to create the token file.\n", 114 | - uri); 115 | - return -EINVAL; 116 | - } 117 | + /* enclave->token = INLINE_SYSCALL(open, 3, uri + 5, O_RDONLY|O_CLOEXEC, 0); */ 118 | + /* if (IS_ERR(enclave->token)) { */ 119 | + /* SGX_DBG(DBG_E, "cannot open token \'%s\'. Use \'" */ 120 | + /* PAL_FILE("pal-sgx-get-token") */ 121 | + /* "\' on the runtime host, or run \'make SGX_RUN=1\' " */ 122 | + /* "in the Graphene source, to create the token file.\n", */ 123 | + /* uri); */ 124 | + /* return -EINVAL; */ 125 | + /* } */ 126 | + enclave->token = 0; 127 | 128 | /* Initialize the enclave */ 129 | ret = initialize_enclave(enclave); 130 | -------------------------------------------------------------------------------- /apps/secret-provisioning-example/show-secrets-grab-secret.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "mbedtls/config.h" 9 | #include "mbedtls/net_sockets.h" 10 | #include "mbedtls/debug.h" 11 | #include "mbedtls/ssl.h" 12 | #include "mbedtls/entropy.h" 13 | #include "mbedtls/ctr_drbg.h" 14 | #include "mbedtls/error.h" 15 | #include "mbedtls/certs.h" 16 | 17 | #include "mbedtls-ra-attester.h" 18 | 19 | unsigned char secret[1024]; 20 | 21 | extern struct ra_tls_options my_ra_tls_options; 22 | 23 | static 24 | void ssl_read_exactly_n_bytes(mbedtls_ssl_context* ssl, unsigned char* p, int len) { 25 | int bytes_read = 0; 26 | int ret; 27 | do { 28 | ret = mbedtls_ssl_read(ssl, p + bytes_read, len - bytes_read); 29 | if (ret == MBEDTLS_ERR_SSL_WANT_READ || 30 | ret == MBEDTLS_ERR_SSL_WANT_WRITE) { 31 | continue; 32 | } 33 | 34 | assert(ret >= 0); 35 | if (ret == 0) break; 36 | bytes_read += ret; 37 | if (bytes_read == len) break; 38 | } while (1); 39 | assert(bytes_read == len); 40 | } 41 | 42 | int grab_secret_from_provisioning_service(int argc, char **argv, char **env) { 43 | (void)env; 44 | 45 | asm("int3"); 46 | 47 | /* Connect to verifier / secret provisioning service. */ 48 | mbedtls_net_context srv_fd; 49 | const char *personalize = __FILE__; 50 | mbedtls_entropy_context entropy; 51 | mbedtls_ctr_drbg_context ctr_drbg; 52 | mbedtls_ssl_context ssl; 53 | mbedtls_ssl_config conf; 54 | mbedtls_x509_crt srvcert; 55 | 56 | mbedtls_x509_crt crt; 57 | mbedtls_pk_context key; 58 | 59 | mbedtls_net_init(&srv_fd); 60 | mbedtls_ssl_init(&ssl); 61 | mbedtls_ssl_config_init(&conf); 62 | mbedtls_ctr_drbg_init(&ctr_drbg); 63 | mbedtls_x509_crt_init(&srvcert); 64 | 65 | /* Generate RA-TLS certificate and key. */ 66 | mbedtls_x509_crt_init(&crt); 67 | mbedtls_pk_init(&key); 68 | mbedtls_create_key_and_x509(&key, &crt, &my_ra_tls_options); 69 | 70 | mbedtls_entropy_init(&entropy); 71 | assert(0 == mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, 72 | &entropy, 73 | (const unsigned char*) personalize, 74 | strlen(personalize))); 75 | 76 | 77 | assert(0 == mbedtls_net_connect(&srv_fd, "127.0.0.1", 78 | "12345", MBEDTLS_NET_PROTO_TCP)); 79 | 80 | assert(0 == mbedtls_ssl_config_defaults(&conf, 81 | MBEDTLS_SSL_IS_CLIENT, 82 | MBEDTLS_SSL_TRANSPORT_STREAM, 83 | MBEDTLS_SSL_PRESET_DEFAULT)); 84 | 85 | mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); 86 | mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); 87 | /* mbedtls_ssl_conf_dbg(&conf, my_debug, stdout); */ 88 | assert(0 == mbedtls_x509_crt_parse_file(&srvcert, "secret-provisioning-service-crt.pem")); 89 | 90 | mbedtls_ssl_conf_ca_chain(&conf, &srvcert, NULL); 91 | assert(0 == mbedtls_ssl_conf_own_cert(&conf, &crt, &key)); 92 | 93 | assert(0 == mbedtls_ssl_setup(&ssl, &conf)); 94 | mbedtls_ssl_set_bio(&ssl, &srv_fd, mbedtls_net_send, 95 | mbedtls_net_recv, NULL); 96 | 97 | int ret; 98 | while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { 99 | assert(ret == MBEDTLS_ERR_SSL_WANT_READ || 100 | ret == MBEDTLS_ERR_SSL_WANT_WRITE); 101 | } 102 | 103 | /* Grab secret from secret provisioning service. */ 104 | int32_t secret_size; 105 | ssl_read_exactly_n_bytes(&ssl, (unsigned char*) &secret_size, sizeof(secret_size)); 106 | assert(secret_size <= (int) sizeof(secret)); 107 | ssl_read_exactly_n_bytes(&ssl, (unsigned char*) secret, secret_size); 108 | 109 | printf(" > Provisioning successful. Secret is: %s\n", (char*)secret); 110 | 111 | /* Patch --requirepass command-line argument to point to obtained secret. */ 112 | printf("Provisioning a secret to a command-line argument.\n"); 113 | const char* requirepass = "--requirepass"; 114 | for (int i = 0; i < argc; i++) { 115 | if ((strncmp(requirepass, argv[i], strlen(requirepass)) == 0) && (i + 1 < argc)) { 116 | printf(" > Found `%s `. Overwriting as `%s %s`\n", 117 | requirepass, requirepass, (char*)secret); 118 | argv[i + 1] = (char*) secret; 119 | } 120 | } 121 | 122 | printf("Provisioning a secret to an environmental variable.\n"); 123 | 124 | /* Technically, = is not part of the name, but hey. */ 125 | const char* env_var_name = "SECRET="; 126 | 127 | int index = 0; 128 | while (env[index]) { 129 | char *env_var = env[index]; 130 | 131 | if (strncmp(env_var_name, env_var, strlen(env_var_name)) == 0) { 132 | if (strlen(env_var) < strlen(env_var_name) + secret_size) { 133 | printf("> Cannot patch env var %.*s since secret is too big (%d bytes).\n", 134 | (int) strlen(env_var_name) - 1, env_var_name, secret_size); 135 | break; 136 | } 137 | 138 | printf(" > Found target env variable. Overwriting as %s%s\n", 139 | env_var_name, (char*)secret); 140 | /* Overwrite in-place. Could also allocate a new 141 | buffer. Undediced whether one solution is better than 142 | the other. */ 143 | snprintf(env_var, strlen(env_var) + 1, "%s%s", 144 | env_var_name, (char*) secret); 145 | break; 146 | } 147 | ++index; 148 | } 149 | 150 | return 0; 151 | } 152 | 153 | /* Passing argc, argv and envp to constructor functions is 154 | * glibc-specific behavior. This allows to intercept argc, argv, and 155 | * envp, and modify argv/enpv for our secret-provisioning purpose. */ 156 | __attribute__((section(".init_array"))) 157 | void *grab_secret_from_provisioning_service_constructor = &grab_secret_from_provisioning_service; 158 | -------------------------------------------------------------------------------- /mbedtls-client.patch: -------------------------------------------------------------------------------- 1 | diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c 2 | index fa70431..a580d22 100644 3 | --- a/programs/ssl/ssl_client1.c 4 | +++ b/programs/ssl/ssl_client1.c 5 | @@ -62,11 +62,16 @@ int main( void ) 6 | 7 | #include 8 | 9 | -#define SERVER_PORT "4433" 10 | +#include 11 | + 12 | +#include "ra.h" 13 | +#include "ra-challenger.h" 14 | + 15 | +#define SERVER_PORT "11111" 16 | #define SERVER_NAME "localhost" 17 | #define GET_REQUEST "GET / HTTP/1.0\r\n\r\n" 18 | 19 | -#define DEBUG_LEVEL 1 20 | +#define DEBUG_LEVEL 0 21 | 22 | static void my_debug( void *ctx, int level, 23 | const char *file, int line, 24 | @@ -78,11 +83,22 @@ static void my_debug( void *ctx, int level, 25 | fflush( (FILE *) ctx ); 26 | } 27 | 28 | +/* The callback is supposed to return 0 on success. Otherwise, the 29 | + verification failed. */ 30 | +static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { 31 | + 32 | + if (depth != 0) return 0; 33 | + 34 | + (void) data; 35 | + (void) flags; 36 | + 37 | + return verify_sgx_cert_extensions(crt->raw.p, crt->raw.len); 38 | +} 39 | + 40 | int main( void ) 41 | { 42 | int ret, len; 43 | mbedtls_net_context server_fd; 44 | - uint32_t flags; 45 | unsigned char buf[1024]; 46 | const char *pers = "ssl_client1"; 47 | 48 | @@ -90,7 +106,6 @@ int main( void ) 49 | mbedtls_ctr_drbg_context ctr_drbg; 50 | mbedtls_ssl_context ssl; 51 | mbedtls_ssl_config conf; 52 | - mbedtls_x509_crt cacert; 53 | 54 | #if defined(MBEDTLS_DEBUG_C) 55 | mbedtls_debug_set_threshold( DEBUG_LEVEL ); 56 | @@ -102,7 +117,6 @@ int main( void ) 57 | mbedtls_net_init( &server_fd ); 58 | mbedtls_ssl_init( &ssl ); 59 | mbedtls_ssl_config_init( &conf ); 60 | - mbedtls_x509_crt_init( &cacert ); 61 | mbedtls_ctr_drbg_init( &ctr_drbg ); 62 | 63 | mbedtls_printf( "\n . Seeding the random number generator..." ); 64 | @@ -120,22 +134,6 @@ int main( void ) 65 | mbedtls_printf( " ok\n" ); 66 | 67 | /* 68 | - * 0. Initialize certificates 69 | - */ 70 | - mbedtls_printf( " . Loading the CA root certificate ..." ); 71 | - fflush( stdout ); 72 | - 73 | - ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, 74 | - mbedtls_test_cas_pem_len ); 75 | - if( ret < 0 ) 76 | - { 77 | - mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret ); 78 | - goto exit; 79 | - } 80 | - 81 | - mbedtls_printf( " ok (%d skipped)\n", ret ); 82 | - 83 | - /* 84 | * 1. Start the connection 85 | */ 86 | mbedtls_printf( " . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT ); 87 | @@ -170,7 +168,7 @@ int main( void ) 88 | /* OPTIONAL is not optimal for security, 89 | * but makes interop easier in this simplified example */ 90 | mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); 91 | - mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); 92 | + mbedtls_ssl_conf_verify(&conf, my_verify, NULL); 93 | mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); 94 | mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); 95 | 96 | @@ -180,18 +178,18 @@ int main( void ) 97 | goto exit; 98 | } 99 | 100 | - if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 ) 101 | - { 102 | - mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); 103 | - goto exit; 104 | - } 105 | + /* if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 ) */ 106 | + /* { */ 107 | + /* mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); */ 108 | + /* goto exit; */ 109 | + /* } */ 110 | 111 | mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); 112 | 113 | /* 114 | * 4. Handshake 115 | */ 116 | - mbedtls_printf( " . Performing the SSL/TLS handshake..." ); 117 | + mbedtls_printf( " . Performing the SSL/TLS handshake...\n" ); 118 | fflush( stdout ); 119 | 120 | while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) 121 | @@ -203,26 +201,25 @@ int main( void ) 122 | } 123 | } 124 | 125 | - mbedtls_printf( " ok\n" ); 126 | + mbedtls_printf( "... handshake ok\n" ); 127 | 128 | - /* 129 | - * 5. Verify the server certificate 130 | - */ 131 | - mbedtls_printf( " . Verifying peer X.509 certificate..." ); 132 | - 133 | - /* In real life, we probably want to bail out when ret != 0 */ 134 | - if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) 135 | - { 136 | - char vrfy_buf[512]; 137 | - 138 | - mbedtls_printf( " failed\n" ); 139 | + /* This demonstrates how to extract SGX-related fields from the 140 | + certificate. */ 141 | + const mbedtls_x509_crt* peercrt = mbedtls_ssl_get_peer_cert( &ssl ); 142 | + sgx_quote_t quote; 143 | + 144 | + get_quote_from_cert(peercrt->raw.p, peercrt->raw.len, "e); 145 | 146 | - mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); 147 | + sgx_report_body_t* body = "e.report_body; 148 | 149 | - mbedtls_printf( "%s\n", vrfy_buf ); 150 | - } 151 | - else 152 | - mbedtls_printf( " ok\n" ); 153 | + printf("Certificate's SGX information:\n"); 154 | + printf(" . MRENCLAVE = "); 155 | + for (int i=0; i < SGX_HASH_SIZE; ++i) printf("%02x", body->mr_enclave.m[i]); 156 | + printf("\n"); 157 | + 158 | + printf(" . MRSIGNER = "); 159 | + for (int i=0; i < SGX_HASH_SIZE; ++i) printf("%02x", body->mr_signer.m[i]); 160 | + printf("\n"); 161 | 162 | /* 163 | * 3. Write the GET request 164 | @@ -294,7 +291,6 @@ exit: 165 | 166 | mbedtls_net_free( &server_fd ); 167 | 168 | - mbedtls_x509_crt_free( &cacert ); 169 | mbedtls_ssl_free( &ssl ); 170 | mbedtls_ssl_config_free( &conf ); 171 | mbedtls_ctr_drbg_free( &ctr_drbg ); 172 | @@ -305,6 +301,8 @@ exit: 173 | fflush( stdout ); getchar(); 174 | #endif 175 | 176 | + if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ret = 0; 177 | + 178 | return( ret ); 179 | } 180 | #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && 181 | -------------------------------------------------------------------------------- /apps/secret-provisioning-example/Makefile: -------------------------------------------------------------------------------- 1 | SGX_SDK?=/opt/intel/sgxsdk 2 | 3 | CFLAGS+=-std=gnu99 4 | CFLAGSERRORS=-Wall -Wextra -Wwrite-strings -Wlogical-op -Wshadow -Werror 5 | CFLAGS+=$(CFLAGSERRORS) 6 | 7 | GRAPHENEDIR=../../deps/graphene 8 | 9 | CFLAGS+= \ 10 | -I../../deps/local/include \ 11 | -I$(SGX_SDK)/include \ 12 | -I../../ 13 | 14 | ifeq ($(DEBUG),1) 15 | CFLAGS+=-g -ggdb -O0 16 | else 17 | CFLAGS+=-O2 18 | endif 19 | 20 | .PHONY: default 21 | default: secret-provisioning-service 22 | 23 | secret-provisioning-service-crt.pem: 24 | openssl req -x509 -nodes -newkey rsa:3072 -keyout secret-provisioning-service-key.pem -out $@ -days 365 -subj '/CN=localhost' 25 | 26 | LDLIBS=\ 27 | ../../mbedtls/libra-challenger.a \ 28 | ../../deps/local/lib/libmbedtls.a \ 29 | ../../deps/local/lib/libmbedcrypto.a \ 30 | ../../deps/local/lib/libmbedx509.a 31 | 32 | # The $(subst -,_,$*) gymnastics turns - (dash) into _ (underscore) 33 | # because - (dash) is not valid within a C variable name. 34 | %_sgx_identity.c: %.token 35 | MRSIGNER=`python -c 'print open("$^").read()[128:128+32]' | xxd -i`; \ 36 | MRENCLAVE=`python -c 'print open("$*.sig").read()[960:960+32]' | xxd -i` ; \ 37 | echo "const char $(subst -,_,$*)_mrenclave[] = { $$MRENCLAVE };" > $@ ; \ 38 | echo "const char $(subst -,_,$*)_mrsigner[] = { $$MRSIGNER };" >> $@ 39 | 40 | ../../deps/local/lib/libmbedtls.a: 41 | cd ../.. && $(MAKE) deps/local/lib/libmbedtls.a 42 | 43 | ../../mbedtls/libra-challenger.a: ../../deps/local/lib/libmbedtls.a 44 | cd ../.. && $(MAKE) mbedtls/libra-challenger.a 45 | 46 | secret-provisioning-service: ../../mbedtls/libra-challenger.a redis-server_sgx_identity.c show-secrets_sgx_identity.c 47 | 48 | RATLS_GIT_URI?=https://github.com/cloud-security-research/sgx-ra-tls.git 49 | RATLS_COMMIT?=master 50 | ../../Makefile: 51 | cd deps && git clone $(RATLS_GIT_URI) 52 | cd ../.. && git checkout $(RATLS_COMMIT) 53 | 54 | redis/Makefile: 55 | wget https://github.com/antirez/redis/archive/5.0.0.zip -O redis-5.0.0.zip 56 | unzip redis-5.0.0.zip 57 | ln -s redis-5.0.0 redis 58 | 59 | # If REDIS_SERVER_BINARY is set, do not install from source. 60 | ifneq ($(REDIS_SERVER_BINARY),) 61 | redis/src/redis-server: 62 | mkdir -p redis/src 63 | ln -s $(REDIS_SERVER_BINARY) $@ 64 | else 65 | redis/src/redis-server: redis/Makefile 66 | cd redis && $(MAKE) noopt 67 | endif 68 | 69 | %.token: %.sig 70 | $(GRAPHENEDIR)/Pal/src/host/Linux-SGX/signer/pal-sgx-get-token -output $@ -sig $< 71 | 72 | redis-server.sig: ../../deps/graphene/Runtime/redis-server-grab-secret.so secret-provisioning-service-crt.pem 73 | redis-server.sig: redis/src/redis-server redis-server.manifest ../../deps/graphene/Runtime/pal-Linux-SGX 74 | $(GRAPHENEDIR)/Pal/src/host/Linux-SGX/signer/pal-sgx-sign -libpal $(GRAPHENEDIR)/Runtime/libpal-Linux-SGX.so -key $(GRAPHENEDIR)/Pal/src/host/Linux-SGX/signer/enclave-key.pem -output redis-server.manifest.sgx -exec redis/src/redis-server -manifest redis-server.manifest 75 | 76 | show-secrets.sig: show-secrets secret-provisioning-service-crt.pem ../../deps/graphene/Runtime/show-secrets-grab-secret.so show-secrets 77 | $(GRAPHENEDIR)/Pal/src/host/Linux-SGX/signer/pal-sgx-sign -libpal $(GRAPHENEDIR)/Runtime/libpal-Linux-SGX.so -key $(GRAPHENEDIR)/Pal/src/host/Linux-SGX/signer/enclave-key.pem -output $(basename $@).manifest.sgx -exec $(basename $@) -manifest $(basename $@).manifest 78 | 79 | PROVISION_LDLIBS= \ 80 | ../../mbedtls/libnonsdk-ra-attester.a \ 81 | ../../deps/local/lib/libprotobuf-c.a \ 82 | ../../deps/local/lib/libcurl-mbedtls.a \ 83 | ../../deps/local/lib/libmbedtls.a \ 84 | ../../deps/local/lib/libmbedcrypto.a \ 85 | ../../deps/local/lib/libmbedx509.a 86 | 87 | PROVISION_LDFLAGS=-shared 88 | 89 | ../../mbedtls/libnonsdk-ra-attester.a: 90 | cd ../.. && $(MAKE) deps/linux-sgx 91 | cd ../.. && $(MAKE) deps/local/lib/libprotobuf-c.a 92 | cd ../.. && $(MAKE) deps/local/lib/libcurl-mbedtls.a 93 | cd ../.. && $(MAKE) mbedtls/libnonsdk-ra-attester.a 94 | 95 | ../../ra_tls_options.c: 96 | $(MAKE) -C $(dir $@) $(notdir $@) 97 | 98 | redis-server-grab-secret.so: ../../mbedtls/libnonsdk-ra-attester.a redis-server-grab-secret.c ../../ra_tls_options.c | secret-provisioning-service-crt.pem 99 | $(CC) $(CFLAGS) -Iredis/src $^ -o $@ $(PROVISION_LDFLAGS) -fPIC $(PROVISION_LDLIBS) 100 | 101 | ../../deps/graphene/Runtime/pal-Linux-SGX: ../../Makefile 102 | cd ../.. && $(MAKE) deps/graphene/Runtime/pal-Linux-SGX 103 | 104 | ../../deps/graphene/Runtime/redis-server-grab-secret.so: redis-server-grab-secret.so | ../../deps/graphene/Runtime/pal-Linux-SGX 105 | cp $^ $@ 106 | 107 | .PHONY: redis-server-run 108 | redis-server-run: redis-server.token 109 | $(GRAPHENEDIR)/Runtime/pal-Linux-SGX ./redis-server.manifest.sgx --save "" --protected-mode no --requirepass XXXXX 110 | 111 | .PHONY: redis-server-clean 112 | redis-server-clean: 113 | $(RM) redis-server.token redis-server.sig redis-server.manifest.sgx ../../deps/graphene/Runtime/redis-server-grab-secret.so redis-server-grab-secret.so 114 | $(RM) redis_server_sgx_identity.c 115 | 116 | .PHONY: clean 117 | clean: redis-server-clean show-secrets-clean 118 | $(RM) -rf secret-provisioning-service redis-server-grab-secret.so secret-provisioning-service-crt.pem secret-provisioning-service-key.pem 119 | 120 | .PHONY: distclean 121 | distclean: clean 122 | $(RM) -rf redis-5.0.0 redis redis-5.0.0.zip 123 | 124 | show-secrets-grab-secret.so: show-secrets-grab-secret.c ../../ra_tls_options.c 125 | $(CC) $(CFLAGS) $(PROVISION_LDFLAGS) $^ -o $@ $(PROVISION_LDLIBS) -fPIC 126 | 127 | ../../deps/graphene/Runtime/show-secrets-grab-secret.so: show-secrets-grab-secret.so | ../../deps/graphene/Runtime/pal-Linux-SGX 128 | cp $^ $@ 129 | 130 | .PHONY: show-secrets-run 131 | show-secrets-run: show-secrets.token 132 | SECRET=not-the-real-thing $(GRAPHENEDIR)/Runtime/pal-Linux-SGX ./show-secrets.manifest.sgx --requirepass XxxXXxxXX 133 | 134 | .PHONY: show-secrets-clean 135 | show-secrets-clean: 136 | $(RM) -rf show-secrets show-secrets-grab-secret.so ../../deps/graphene/Runtime/show-secrets-grab-secret.so show-secrets.token show-secrets.sig show-secrets.manifest.sgx show-secrets_sgx_identity.c 137 | 138 | %.html: %.md 139 | pandoc --from markdown_github --to html --standalone $< --output $@ 140 | 141 | html: README.html 142 | 143 | .PHONY: secret-provisioning-service-run 144 | secret-provisioning-service-run: secret-provisioning-service 145 | ifeq ($(DEBUG),1) 146 | gdb --args ./secret-provisioning-service 147 | else 148 | ./secret-provisioning-service 149 | endif 150 | 151 | .PHONY: check 152 | check: secret-provisioning-service 153 | cd ../.. && python3 tests/00_secrect_provisioning_example.py 154 | -------------------------------------------------------------------------------- /apps/secret-provisioning-example/README.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 46 | 47 | 48 |

Description

49 |

This project demonstrates how to provision an SGX application with secrets after remotely attesting it. We demonstrate this with two applications, one of which is Redis. Redis can be configured with a password which clients must provide before the server accepts commands from them. The password is usually provided either in a configuration file or as a command line argument. We demonstrate how to provision the password only after attesting the Redis server. We also have a second application to demonstrate how to provision secrets passed in environment variables.

50 |

The Redis server runs inside an SGX enclave with the help of Graphene. After instantiating the enclave, but before the Redis server runs, we execute additional code (captured in the redis-server-grab-secret.so helper library and LDPRELOADed in the Redis manifest) to remotely attest to a secret provisioning service. The secret provisioning service only releases the password to the Redis server after successfully verifying its SGX identity.

51 |

The Redis server is completely unmodified. This project assumes that Redis is called with --requirepass <placeholder>. After the helper library receives the password from the secret provisioning service, it overwrites this command-line argument with --requirepass <received-secret>.

52 |

The Redis server communicates securely with the secret provisioning service over mutually authenticated TLS. The provisioning service uses a standard (self-signed) X.509 certificate as its identity. The Redis server uses an RA-TLS certificate to authenticate to the provisioning service. The provisioning service has the Redis server's SGX identity backed at build time (cf. redis_server_sgx_identity.c). The provisioning service verifies the SGX identity information in the RA-TLS certificate before sending the secret to the remote party.

53 |
                   X.509     TLS    RA-TLS          plain text
54 | Secret Provisioning   <-------------->   Redis    <---------->  Client
55 | Service (verifier)
56 |

This demonstrator focuses on the remote provisioning of the password. The Redis server and client communicate in plain text, exposing the password to any man-in-the-middle attacker. To prevent this, the Redis server and client should also use an encrypted communication channel; either by enabling TLS in Redis itself or through Graphene's network shield.

57 |

Build

58 |

Prepare everything by executing make. To avoid building Redis from source, specify the path to an existing Redis binary as follows: export REDIS_SERVER_BINARY=/usr/bin/redis-server.

59 |

Run

60 |

Start the secret provisioning service with ./secret-provisioning-service. A single service delivers secrets to multiple applications based on their SGX identity.

61 |

Expose AESMD's domain socket via TCP such that it can be reached from within Graphene

62 |
socat -t10 TCP-LISTEN:1234,bind=127.0.0.1,reuseaddr,fork,range=127.0.0.0/8 UNIX-CLIENT:/var/run/aesmd/aesm.socket &
63 |

Start the Redis server with make redis-server-run.

64 |

Redis prints a couple of messages after the secret provisioning service released the password.

65 |

Test with [redis/src/]redis-cli -a intelsgxrocks! ping. Output should be PONG. A different password will result in Redis telling you that the authentication failed.

66 |

The show-secrets application demonstrates how to provision a secret to an environment variable (in addition to a secret command line argument). Run the application with make show-secrets-run. It will print some messages, that are hopefully self-explanatory.

67 |

Notes

68 |

On weak vs strong symbols, dlsym and LD_PRELOAD

69 |

For transparent provisioning of the secret password to Redis, we initially hoped to overload existing functions in Redis via LD_PRELOAD. However, LD_PRELOAD of course only works if the symbol you are trying to override is resolved dynamically which Redis' internal functions are not. LD_PRELOAD is only able to overwrite functions residing in shared libraries.

70 |

Patching command-line arguments of Redis

71 |

The current implementation patches command-line argument --requirepass <placeholder> to Redis to inject the secret password. It relies on a clever trick to modify argv through a constructor in the shared library (cf. https://sourceware.org/ml/libc-help/2009-11/msg00006.html). Alternatively, one could create or modify the Redis configuration file (redis.conf) with the password. Note that the passing of argc, argv and envp to library constructors is glibc-specific behavior.

72 | 73 | 74 | -------------------------------------------------------------------------------- /mbedtls-ra-challenger.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "mbedtls/ctr_drbg.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include "ra.h" 19 | #include "ra-challenger.h" 20 | 21 | #include "ra-challenger_private.h" 22 | 23 | extern unsigned char ias_sign_ca_cert_der[]; 24 | extern unsigned int ias_sign_ca_cert_der_len; 25 | 26 | void get_quote_from_report(const uint8_t* report /* in */, 27 | const int report_len /* in */, 28 | sgx_quote_t* quote) 29 | { 30 | (void) report_len; 31 | 32 | const char* json_string = "\"isvEnclaveQuoteBody\":\""; 33 | char* p_begin = strstr((const char*) report, json_string); 34 | assert(p_begin != NULL); 35 | p_begin += strlen(json_string); 36 | const char* p_end = strchr(p_begin, '"'); 37 | assert(p_end != NULL); 38 | 39 | const int quote_base64_len = p_end - p_begin; 40 | uint8_t* quote_bin = malloc(quote_base64_len); 41 | size_t quote_bin_len = quote_base64_len; 42 | 43 | mbedtls_base64_decode(quote_bin, quote_base64_len, 44 | "e_bin_len, 45 | (unsigned char*) p_begin, quote_base64_len); 46 | 47 | assert(quote_bin_len <= sizeof(sgx_quote_t)); 48 | memset(quote, 0, sizeof(sgx_quote_t)); 49 | memcpy(quote, quote_bin, quote_bin_len); 50 | free(quote_bin); 51 | } 52 | 53 | void get_quote_from_cert 54 | ( 55 | const uint8_t* der_crt, 56 | uint32_t der_crt_len, 57 | sgx_quote_t* q 58 | ) 59 | { 60 | mbedtls_x509_crt crt; 61 | mbedtls_x509_crt_init(&crt); 62 | mbedtls_x509_crt_parse(&crt, der_crt, der_crt_len); 63 | get_quote_from_extension(crt.v3_ext.p, crt.v3_ext.len, q); 64 | mbedtls_x509_crt_free(&crt); 65 | } 66 | 67 | static 68 | int verify_report_data_against_server_cert 69 | ( 70 | mbedtls_x509_crt* crt, 71 | sgx_quote_t* quote 72 | ) 73 | { 74 | static const int pk_der_size_max = 512; 75 | uint8_t pk_der[pk_der_size_max]; 76 | memset(pk_der, 0, pk_der_size_max); 77 | /* From the mbedtls documentation: Write a public key to a 78 | SubjectPublicKeyInfo DER structure Note: data is written at the 79 | end of the buffer! Use the return value to determine where you 80 | should start using the buffer. */ 81 | int pk_der_size_byte = mbedtls_pk_write_pubkey_der(&crt->pk, pk_der, pk_der_size_max); 82 | 83 | // Assume 3072 bit RSA keys for now. 84 | assert(pk_der_size_byte == rsa_pub_3072_pcks_der_len); 85 | 86 | /* Move the data to the beginning of the buffer, to avoid pointer 87 | arithmetic from this point forward. */ 88 | memmove(pk_der, pk_der + pk_der_size_max - pk_der_size_byte, pk_der_size_byte); 89 | 90 | static const size_t SHA256_DIGEST_SIZE = 32; 91 | uint8_t shaSum[SHA256_DIGEST_SIZE]; 92 | 93 | memset(shaSum, 0, SHA256_DIGEST_SIZE); 94 | mbedtls_sha256(pk_der + rsa_pub_3072_pcks_header_len, 95 | pk_der_size_byte - rsa_pub_3072_pcks_header_len, 96 | shaSum, 0 /* is224 */); 97 | 98 | #if 0 99 | printf_sgx("sha256 of server's public key:\n"); 100 | for (unsigned int i=0; i < SHA256_DIGEST_SIZE; ++i) mbedtls_printf("%02x", shaSum[i]); 101 | mbedtls_printf("\n"); 102 | 103 | mbedtls_printf("quote report data:\n"); 104 | for (int i=0; i < SGX_REPORT_DATA_SIZE; ++i) mbedtls_printf("%02x", quote->report_body.report_data.d[i]); 105 | mbedtls_printf("\n"); 106 | #endif 107 | 108 | int ret; 109 | ret = memcmp(quote->report_body.report_data.d, 110 | shaSum, SHA256_DIGEST_SIZE); 111 | assert(ret == 0); 112 | 113 | #if 0 114 | if (ret == 0) mbedtls_printf("hash of server's public key matches matches report data\n"); 115 | #endif 116 | 117 | return ret; 118 | } 119 | 120 | static 121 | int verify_ias_report_signature 122 | ( 123 | attestation_verification_report_t* attn_report 124 | ) 125 | { 126 | // Create certificate structure 127 | mbedtls_x509_crt cert; 128 | mbedtls_x509_crt_init(&cert); 129 | int ret; 130 | /* mbedtls_x509_crt_parse requires PEM-encoded certificates to be 131 | zero terminated (How braindead is this?). */ 132 | assert(attn_report->ias_sign_cert_len < sizeof(attn_report->ias_sign_cert)); 133 | attn_report->ias_sign_cert[attn_report->ias_sign_cert_len] = '\0'; 134 | ret = mbedtls_x509_crt_parse(&cert, 135 | attn_report->ias_sign_cert, 136 | attn_report->ias_sign_cert_len + 1); /* +1 for the zero byte */ 137 | assert(ret == 0); 138 | 139 | // Extract RSA public key 140 | assert(cert.pk.pk_info->type == MBEDTLS_PK_RSA); 141 | mbedtls_rsa_context* rsa = (mbedtls_rsa_context*) cert.pk.pk_ctx; 142 | 143 | // Compute signature 144 | uint8_t sha256[32]; 145 | ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 146 | attn_report->ias_report, 147 | attn_report->ias_report_len, 148 | sha256); 149 | assert(ret == 0); 150 | 151 | // Verify signature 152 | ret = mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, 153 | MBEDTLS_MD_SHA256, 0, 154 | sha256, 155 | attn_report->ias_report_signature); 156 | return ret; 157 | } 158 | 159 | static 160 | int verify_ias_certificate_chain(attestation_verification_report_t* attn_report) { 161 | 162 | mbedtls_x509_crt cacert; 163 | mbedtls_x509_crt_init(&cacert); 164 | int ret; 165 | 166 | ret = mbedtls_x509_crt_parse(&cacert, 167 | ias_sign_ca_cert_der, 168 | ias_sign_ca_cert_der_len); 169 | assert(ret == 0); 170 | 171 | mbedtls_x509_crt cert; 172 | mbedtls_x509_crt_init(&cert); 173 | /* mbedtls_x509_crt_parse requires PEM-encoded certificates to be 174 | zero terminated (How brainded is this?). */ 175 | assert(attn_report->ias_sign_cert_len < sizeof(attn_report->ias_sign_cert)); 176 | attn_report->ias_sign_cert[attn_report->ias_sign_cert_len] = '\0'; 177 | ret = mbedtls_x509_crt_parse(&cert, 178 | attn_report->ias_sign_cert, 179 | attn_report->ias_sign_cert_len + 1); /* +1 for the zero byte. */ 180 | assert(ret == 0); 181 | 182 | uint32_t flags; 183 | ret = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &flags, NULL, NULL); 184 | assert(ret == 0); 185 | 186 | return ret; 187 | } 188 | 189 | /** 190 | * @return 0 if verified successfully, 1 otherwise. 191 | */ 192 | int verify_sgx_cert_extensions 193 | ( 194 | uint8_t* der_crt, 195 | uint32_t der_crt_len 196 | ) 197 | { 198 | attestation_verification_report_t attn_report; 199 | 200 | mbedtls_x509_crt crt; 201 | mbedtls_x509_crt_init(&crt); 202 | 203 | int ret; 204 | ret = mbedtls_x509_crt_parse(&crt, der_crt, der_crt_len); 205 | 206 | extract_x509_extensions(crt.v3_ext.p, 207 | crt.v3_ext.len, 208 | &attn_report); 209 | 210 | uint8_t base64[sizeof(attn_report.ias_report_signature)]; 211 | memcpy(base64, attn_report.ias_report_signature, attn_report.ias_report_signature_len); 212 | 213 | size_t decoded_len; 214 | ret = mbedtls_base64_decode(attn_report.ias_report_signature, 215 | sizeof(attn_report.ias_report_signature), 216 | &decoded_len, base64, attn_report.ias_report_signature_len); 217 | assert(0 == ret); 218 | assert(decoded_len <= UINT32_MAX); 219 | attn_report.ias_report_signature_len = (uint32_t) decoded_len; 220 | 221 | ret = verify_ias_certificate_chain(&attn_report); 222 | assert(ret == 0); 223 | 224 | ret = verify_ias_report_signature(&attn_report); 225 | assert(ret == 0); 226 | 227 | sgx_quote_t quote = {0, }; 228 | get_quote_from_report(attn_report.ias_report, 229 | attn_report.ias_report_len, 230 | "e); 231 | ret = verify_report_data_against_server_cert(&crt, "e); 232 | assert(ret == 0); 233 | 234 | mbedtls_x509_crt_free(&crt); 235 | 236 | return 0; 237 | } 238 | -------------------------------------------------------------------------------- /ias_sign_ca_cert.c: -------------------------------------------------------------------------------- 1 | unsigned char ias_sign_ca_cert_der[] = { 2 | 0x30, 0x82, 0x05, 0x4b, 0x30, 0x82, 0x03, 0xb3, 0xa0, 0x03, 0x02, 0x01, 3 | 0x02, 0x02, 0x09, 0x00, 0xd1, 0x07, 0x76, 0x5d, 0x32, 0xa3, 0xb0, 0x94, 4 | 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 5 | 0x0b, 0x05, 0x00, 0x30, 0x7e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 6 | 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 7 | 0x55, 0x04, 0x08, 0x0c, 0x02, 0x43, 0x41, 0x31, 0x14, 0x30, 0x12, 0x06, 8 | 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0b, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x20, 9 | 0x43, 0x6c, 0x61, 0x72, 0x61, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 10 | 0x04, 0x0a, 0x0c, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x43, 0x6f, 11 | 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x30, 0x30, 12 | 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x27, 0x49, 0x6e, 0x74, 0x65, 13 | 0x6c, 0x20, 0x53, 0x47, 0x58, 0x20, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 14 | 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 15 | 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x41, 0x30, 16 | 0x20, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x31, 0x31, 0x34, 0x31, 0x35, 0x33, 17 | 0x37, 0x33, 0x31, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x34, 0x39, 0x31, 0x32, 18 | 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x7e, 0x31, 19 | 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 20 | 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x43, 21 | 0x41, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0b, 22 | 0x53, 0x61, 0x6e, 0x74, 0x61, 0x20, 0x43, 0x6c, 0x61, 0x72, 0x61, 0x31, 23 | 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x11, 0x49, 0x6e, 24 | 0x74, 0x65, 0x6c, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 25 | 0x69, 0x6f, 0x6e, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 26 | 0x0c, 0x27, 0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x53, 0x47, 0x58, 0x20, 27 | 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 28 | 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 29 | 0x6e, 0x67, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0xa2, 0x30, 0x0d, 0x06, 30 | 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 31 | 0x03, 0x82, 0x01, 0x8f, 0x00, 0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, 32 | 0x81, 0x00, 0x9f, 0x3c, 0x64, 0x7e, 0xb5, 0x77, 0x3c, 0xbb, 0x51, 0x2d, 33 | 0x27, 0x32, 0xc0, 0xd7, 0x41, 0x5e, 0xbb, 0x55, 0xa0, 0xfa, 0x9e, 0xde, 34 | 0x2e, 0x64, 0x91, 0x99, 0xe6, 0x82, 0x1d, 0xb9, 0x10, 0xd5, 0x31, 0x77, 35 | 0x37, 0x09, 0x77, 0x46, 0x6a, 0x6a, 0x5e, 0x47, 0x86, 0xcc, 0xd2, 0xdd, 36 | 0xeb, 0xd4, 0x14, 0x9d, 0x6a, 0x2f, 0x63, 0x25, 0x52, 0x9d, 0xd1, 0x0c, 37 | 0xc9, 0x87, 0x37, 0xb0, 0x77, 0x9c, 0x1a, 0x07, 0xe2, 0x9c, 0x47, 0xa1, 38 | 0xae, 0x00, 0x49, 0x48, 0x47, 0x6c, 0x48, 0x9f, 0x45, 0xa5, 0xa1, 0x5d, 39 | 0x7a, 0xc8, 0xec, 0xc6, 0xac, 0xc6, 0x45, 0xad, 0xb4, 0x3d, 0x87, 0x67, 40 | 0x9d, 0xf5, 0x9c, 0x09, 0x3b, 0xc5, 0xa2, 0xe9, 0x69, 0x6c, 0x54, 0x78, 41 | 0x54, 0x1b, 0x97, 0x9e, 0x75, 0x4b, 0x57, 0x39, 0x14, 0xbe, 0x55, 0xd3, 42 | 0x2f, 0xf4, 0xc0, 0x9d, 0xdf, 0x27, 0x21, 0x99, 0x34, 0xcd, 0x99, 0x05, 43 | 0x27, 0xb3, 0xf9, 0x2e, 0xd7, 0x8f, 0xbf, 0x29, 0x24, 0x6a, 0xbe, 0xcb, 44 | 0x71, 0x24, 0x0e, 0xf3, 0x9c, 0x2d, 0x71, 0x07, 0xb4, 0x47, 0x54, 0x5a, 45 | 0x7f, 0xfb, 0x10, 0xeb, 0x06, 0x0a, 0x68, 0xa9, 0x85, 0x80, 0x21, 0x9e, 46 | 0x36, 0x91, 0x09, 0x52, 0x68, 0x38, 0x92, 0xd6, 0xa5, 0xe2, 0xa8, 0x08, 47 | 0x03, 0x19, 0x3e, 0x40, 0x75, 0x31, 0x40, 0x4e, 0x36, 0xb3, 0x15, 0x62, 48 | 0x37, 0x99, 0xaa, 0x82, 0x50, 0x74, 0x40, 0x97, 0x54, 0xa2, 0xdf, 0xe8, 49 | 0xf5, 0xaf, 0xd5, 0xfe, 0x63, 0x1e, 0x1f, 0xc2, 0xaf, 0x38, 0x08, 0x90, 50 | 0x6f, 0x28, 0xa7, 0x90, 0xd9, 0xdd, 0x9f, 0xe0, 0x60, 0x93, 0x9b, 0x12, 51 | 0x57, 0x90, 0xc5, 0x80, 0x5d, 0x03, 0x7d, 0xf5, 0x6a, 0x99, 0x53, 0x1b, 52 | 0x96, 0xde, 0x69, 0xde, 0x33, 0xed, 0x22, 0x6c, 0xc1, 0x20, 0x7d, 0x10, 53 | 0x42, 0xb5, 0xc9, 0xab, 0x7f, 0x40, 0x4f, 0xc7, 0x11, 0xc0, 0xfe, 0x47, 54 | 0x69, 0xfb, 0x95, 0x78, 0xb1, 0xdc, 0x0e, 0xc4, 0x69, 0xea, 0x1a, 0x25, 55 | 0xe0, 0xff, 0x99, 0x14, 0x88, 0x6e, 0xf2, 0x69, 0x9b, 0x23, 0x5b, 0xb4, 56 | 0x84, 0x7d, 0xd6, 0xff, 0x40, 0xb6, 0x06, 0xe6, 0x17, 0x07, 0x93, 0xc2, 57 | 0xfb, 0x98, 0xb3, 0x14, 0x58, 0x7f, 0x9c, 0xfd, 0x25, 0x73, 0x62, 0xdf, 58 | 0xea, 0xb1, 0x0b, 0x3b, 0xd2, 0xd9, 0x76, 0x73, 0xa1, 0xa4, 0xbd, 0x44, 59 | 0xc4, 0x53, 0xaa, 0xf4, 0x7f, 0xc1, 0xf2, 0xd3, 0xd0, 0xf3, 0x84, 0xf7, 60 | 0x4a, 0x06, 0xf8, 0x9c, 0x08, 0x9f, 0x0d, 0xa6, 0xcd, 0xb7, 0xfc, 0xee, 61 | 0xe8, 0xc9, 0x82, 0x1a, 0x8e, 0x54, 0xf2, 0x5c, 0x04, 0x16, 0xd1, 0x8c, 62 | 0x46, 0x83, 0x9a, 0x5f, 0x80, 0x12, 0xfb, 0xdd, 0x3d, 0xc7, 0x4d, 0x25, 63 | 0x62, 0x79, 0xad, 0xc2, 0xc0, 0xd5, 0x5a, 0xff, 0x6f, 0x06, 0x22, 0x42, 64 | 0x5d, 0x1b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xc9, 0x30, 0x81, 65 | 0xc6, 0x30, 0x60, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x59, 0x30, 0x57, 66 | 0x30, 0x55, 0xa0, 0x53, 0xa0, 0x51, 0x86, 0x4f, 0x68, 0x74, 0x74, 0x70, 67 | 0x3a, 0x2f, 0x2f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x73, 0x65, 68 | 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x6c, 69 | 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 70 | 0x2f, 0x43, 0x52, 0x4c, 0x2f, 0x53, 0x47, 0x58, 0x2f, 0x41, 0x74, 0x74, 71 | 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6f, 72 | 0x72, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x41, 0x2e, 73 | 0x63, 0x72, 0x6c, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 74 | 0x04, 0x14, 0x78, 0x43, 0x7b, 0x76, 0xa6, 0x7e, 0xbc, 0xd0, 0xaf, 0x7e, 75 | 0x42, 0x37, 0xeb, 0x35, 0x7c, 0x3b, 0x87, 0x01, 0x51, 0x3c, 0x30, 0x1f, 76 | 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x78, 77 | 0x43, 0x7b, 0x76, 0xa6, 0x7e, 0xbc, 0xd0, 0xaf, 0x7e, 0x42, 0x37, 0xeb, 78 | 0x35, 0x7c, 0x3b, 0x87, 0x01, 0x51, 0x3c, 0x30, 0x0e, 0x06, 0x03, 0x55, 79 | 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 80 | 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 81 | 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 82 | 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 83 | 0x01, 0x81, 0x00, 0x78, 0x5f, 0x2d, 0x60, 0xc5, 0xc8, 0x0a, 0xf4, 0x2a, 84 | 0x79, 0x76, 0x10, 0x21, 0x39, 0x15, 0xda, 0x82, 0xc9, 0xb2, 0x9e, 0x89, 85 | 0xe0, 0x90, 0x2a, 0x25, 0xa6, 0xc7, 0x5b, 0x16, 0x09, 0x1c, 0x68, 0xab, 86 | 0x20, 0x4a, 0xae, 0x71, 0x18, 0x89, 0x49, 0x2c, 0x7e, 0x1e, 0x32, 0x09, 87 | 0x11, 0x45, 0x5a, 0x8f, 0xc1, 0x34, 0x42, 0x31, 0x2e, 0x77, 0xa6, 0x39, 88 | 0x94, 0xd9, 0x97, 0x95, 0xc8, 0xea, 0x45, 0x76, 0x82, 0x3c, 0xea, 0x8a, 89 | 0xd1, 0xe1, 0x91, 0xcf, 0xa8, 0x62, 0xfa, 0xb8, 0xa9, 0x32, 0xd3, 0xd9, 90 | 0xb0, 0x53, 0x5a, 0x07, 0x02, 0xd0, 0x55, 0x5f, 0x74, 0xe5, 0x20, 0xe3, 91 | 0x03, 0x30, 0xf3, 0x34, 0x80, 0xe7, 0xad, 0xc9, 0xd7, 0xc8, 0x1e, 0x20, 92 | 0x70, 0x31, 0x42, 0xbf, 0x00, 0xc5, 0x28, 0xa8, 0x0b, 0x46, 0x33, 0x81, 93 | 0xfd, 0x60, 0x2a, 0x82, 0xc7, 0x03, 0x52, 0x81, 0xaa, 0xe5, 0x95, 0x62, 94 | 0xcc, 0xb5, 0x33, 0x4e, 0xa8, 0x90, 0x3e, 0x65, 0x0b, 0x01, 0x06, 0x81, 95 | 0xf5, 0xce, 0x8e, 0xb6, 0x2e, 0xac, 0x9c, 0x41, 0x49, 0x88, 0x24, 0x3a, 96 | 0xec, 0x92, 0xf2, 0x5b, 0xf1, 0x3c, 0xdf, 0xf7, 0xeb, 0xcc, 0x29, 0x8e, 97 | 0xe5, 0x1b, 0xba, 0x5a, 0x35, 0x38, 0xb6, 0x6b, 0x26, 0xcb, 0xc4, 0x5a, 98 | 0x51, 0xde, 0x00, 0x3c, 0xad, 0x30, 0x65, 0x31, 0xad, 0x7c, 0xf5, 0xd4, 99 | 0xef, 0x0f, 0x88, 0x05, 0xd1, 0xb9, 0x13, 0x3d, 0x24, 0x13, 0x5a, 0xb3, 100 | 0xc4, 0x64, 0x1a, 0x2f, 0x88, 0x08, 0x34, 0x9d, 0x73, 0x33, 0x29, 0x5e, 101 | 0x0e, 0x76, 0xee, 0x4b, 0xc5, 0x22, 0x72, 0x32, 0x62, 0x8e, 0xfa, 0x80, 102 | 0xd7, 0x9d, 0x92, 0xab, 0x4e, 0x3d, 0x11, 0x20, 0xf3, 0xfb, 0x5a, 0xd1, 103 | 0x19, 0xcd, 0x8d, 0x54, 0x4a, 0xa1, 0xd4, 0xa6, 0x86, 0x5e, 0x6b, 0x57, 104 | 0xbe, 0xac, 0x57, 0x71, 0x30, 0x7e, 0x2e, 0x3c, 0xb9, 0x07, 0x0d, 0xa4, 105 | 0x7b, 0x4b, 0xfc, 0x88, 0x69, 0xe0, 0x14, 0x13, 0xea, 0x09, 0x35, 0x41, 106 | 0xde, 0x8a, 0x79, 0x28, 0x11, 0xb7, 0x46, 0x36, 0xc5, 0xe9, 0x14, 0x52, 107 | 0xcf, 0x0c, 0xee, 0x59, 0xf2, 0xfb, 0x40, 0x4a, 0xcd, 0x0b, 0xc5, 0x84, 108 | 0xcb, 0x9c, 0x83, 0x54, 0x04, 0x73, 0x4c, 0x0e, 0x7e, 0xc6, 0x60, 0x5c, 109 | 0xdf, 0xcf, 0x2f, 0xf4, 0x39, 0xb6, 0xd4, 0x71, 0x9f, 0x70, 0x2f, 0x0e, 110 | 0x0c, 0x3f, 0xa0, 0x4f, 0xdb, 0x12, 0xa6, 0xcb, 0x2a, 0xd1, 0xab, 0x1c, 111 | 0x9a, 0xf1, 0xf8, 0xf4, 0xc3, 0xa0, 0x8e, 0xdd, 0x72, 0xa3, 0x2b, 0x0b, 112 | 0xb5, 0xd0, 0xad, 0x25, 0x6f, 0xfd, 0x15, 0x9a, 0x68, 0x3b, 0x2a, 0x5a, 113 | 0x1f, 0x1d, 0x11, 0xfa, 0x62, 0x53, 0x2f, 0x03, 0xd7, 0x54, 0xca, 0xef, 114 | 0x0d, 0xa5, 0x73, 0x5a, 0x1e, 0x5a, 0x88, 0x4c, 0x7e, 0x89, 0xd9, 0x12, 115 | 0x18, 0xc9, 0xd7 116 | }; 117 | unsigned int ias_sign_ca_cert_der_len = 1359; 118 | -------------------------------------------------------------------------------- /ra-challenger.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Code common to all challenger implementations (i.e., independent of 3 | * the TLS library). 4 | */ 5 | 6 | #define _GNU_SOURCE 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "ra.h" 16 | #include "ra_private.h" 17 | 18 | #if SGX_SDK 19 | /* SGX SDK does not have this. */ 20 | void *memmem(const void *h0, size_t k, const void *n0, size_t l); 21 | #endif 22 | 23 | #include "ra-challenger_private.h" 24 | #include "ra-challenger.h" 25 | 26 | void get_quote_from_extension 27 | ( 28 | uint8_t* exts, 29 | size_t exts_len, 30 | sgx_quote_t* q 31 | ) 32 | { 33 | uint8_t report[2048]; 34 | uint32_t report_len; 35 | 36 | int rc = extract_x509_extension(exts, exts_len, 37 | ias_response_body_oid, ias_oid_len, 38 | report, &report_len, sizeof(report)); 39 | 40 | if (rc == 1) { 41 | get_quote_from_report(report, report_len, q); 42 | return; 43 | } 44 | 45 | rc = extract_x509_extension(exts, exts_len, 46 | quote_oid, ias_oid_len, 47 | report, &report_len, sizeof(report)); 48 | assert(rc == 1); 49 | memcpy(q, report, sizeof(*q)); 50 | } 51 | 52 | /** 53 | * @return Returns -1 if OID not found. Otherwise, returns 1; 54 | */ 55 | int find_oid 56 | ( 57 | const unsigned char* ext, size_t ext_len, 58 | const unsigned char* oid, size_t oid_len, 59 | unsigned char** val, size_t* len 60 | ) 61 | { 62 | uint8_t* p = memmem(ext, ext_len, oid, oid_len); 63 | if (p == NULL) { 64 | return -1; 65 | } 66 | 67 | p += oid_len; 68 | 69 | int i = 0; 70 | 71 | // Some TLS libraries generate a BOOLEAN for the criticality of the extension. 72 | if (p[i] == 0x01) { 73 | assert(p[i++] == 0x01); // tag, 0x01 is ASN1 Boolean 74 | assert(p[i++] == 0x01); // length 75 | assert(p[i++] == 0x00); // value (0 is non-critical, non-zero is critical) 76 | } 77 | 78 | // Now comes the octet string 79 | assert(p[i++] == 0x04); // tag for octet string 80 | assert(p[i++] == 0x82); // length encoded in two bytes 81 | *len = p[i++] << 8; 82 | *len += p[i++]; 83 | *val = &p[i++]; 84 | 85 | return 1; 86 | } 87 | 88 | /** 89 | * @return Returns -1 if OID was not found. Otherwise, returns 1; 90 | */ 91 | int extract_x509_extension 92 | ( 93 | uint8_t* ext, 94 | int ext_len, 95 | const uint8_t* oid, 96 | size_t oid_len, 97 | uint8_t* data, 98 | uint32_t* data_len, 99 | uint32_t data_max_len 100 | ) 101 | { 102 | uint8_t* ext_data; 103 | size_t ext_data_len; 104 | 105 | int rc = find_oid(ext, ext_len, oid, oid_len, &ext_data, &ext_data_len); 106 | if (rc == -1) return -1; 107 | 108 | assert(ext_data != NULL); 109 | assert(ext_data_len <= data_max_len); 110 | memcpy(data, ext_data, ext_data_len); 111 | *data_len = ext_data_len; 112 | 113 | return 1; 114 | } 115 | 116 | /** 117 | * Extract all extensions. 118 | */ 119 | void extract_x509_extensions 120 | ( 121 | uint8_t* ext, 122 | int ext_len, 123 | attestation_verification_report_t* attn_report 124 | ) 125 | { 126 | extract_x509_extension(ext, ext_len, 127 | ias_response_body_oid, ias_oid_len, 128 | attn_report->ias_report, 129 | &attn_report->ias_report_len, 130 | sizeof(attn_report->ias_report)); 131 | 132 | extract_x509_extension(ext, ext_len, 133 | ias_root_cert_oid, ias_oid_len, 134 | attn_report->ias_sign_ca_cert, 135 | &attn_report->ias_sign_ca_cert_len, 136 | sizeof(attn_report->ias_sign_ca_cert)); 137 | 138 | extract_x509_extension(ext, ext_len, 139 | ias_leaf_cert_oid, ias_oid_len, 140 | attn_report->ias_sign_cert, 141 | &attn_report->ias_sign_cert_len, 142 | sizeof(attn_report->ias_sign_cert)); 143 | 144 | extract_x509_extension(ext, ext_len, 145 | ias_report_signature_oid, ias_oid_len, 146 | attn_report->ias_report_signature, 147 | &attn_report->ias_report_signature_len, 148 | sizeof(attn_report->ias_report_signature)); 149 | } 150 | 151 | /** 152 | * Extract ECDSA related extensions from X509. 153 | */ 154 | void ecdsa_extract_x509_extensions 155 | ( 156 | uint8_t* ext, 157 | int ext_len, 158 | ecdsa_attestation_evidence_t* evidence 159 | ) 160 | { 161 | extract_x509_extension(ext, ext_len, quote_oid, ias_oid_len, 162 | evidence->quote, &evidence->quote_len, 163 | sizeof(evidence->quote)); 164 | 165 | extract_x509_extension(ext, ext_len, pck_crt_oid, ias_oid_len, 166 | evidence->pck_crt, &evidence->pck_crt_len, 167 | sizeof(evidence->pck_crt)); 168 | 169 | extract_x509_extension(ext, ext_len, pck_sign_chain_oid, ias_oid_len, 170 | evidence->pck_sign_chain, &evidence->pck_sign_chain_len, 171 | sizeof(evidence->pck_sign_chain)); 172 | 173 | extract_x509_extension(ext, ext_len, tcb_info_oid, ias_oid_len, 174 | evidence->tcb_info, &evidence->tcb_info_len, 175 | sizeof(evidence->tcb_info)); 176 | 177 | extract_x509_extension(ext, ext_len, tcb_sign_chain_oid, ias_oid_len, 178 | evidence->tcb_sign_chain, &evidence->tcb_sign_chain_len, 179 | sizeof(evidence->tcb_sign_chain)); 180 | 181 | extract_x509_extension(ext, ext_len, qe_identity_oid, ias_oid_len, 182 | evidence->qe_identity, &evidence->qe_identity_len, 183 | sizeof(evidence->qe_identity)); 184 | 185 | extract_x509_extension(ext, ext_len, root_ca_crl_oid, ias_oid_len, 186 | evidence->root_ca_crl, &evidence->root_ca_crl_len, 187 | sizeof(evidence->root_ca_crl)); 188 | 189 | extract_x509_extension(ext, ext_len, pck_crl_oid, ias_oid_len, 190 | evidence->pck_crl, &evidence->pck_crl_len, 191 | sizeof(evidence->pck_crl)); 192 | } 193 | 194 | /** 195 | * @return 1 if it is an EPID-based attestation RA-TLS 196 | * certificate. Otherwise, 0. 197 | */ 198 | int is_epid_ratls_cert 199 | ( 200 | const uint8_t* der_crt, 201 | uint32_t der_crt_len 202 | ) 203 | { 204 | uint8_t* ext_data; 205 | size_t ext_data_len; 206 | int rc; 207 | 208 | rc = find_oid(der_crt, der_crt_len, 209 | ias_response_body_oid, ias_oid_len, 210 | &ext_data, &ext_data_len); 211 | if (1 == rc) return 1; 212 | 213 | rc = find_oid(der_crt, der_crt_len, 214 | quote_oid, ias_oid_len, 215 | &ext_data, &ext_data_len); 216 | if (1 == rc) return 0; 217 | 218 | /* Something is fishy. Neither EPID nor ECDSA RA-TLC cert?! */ 219 | assert(0); 220 | // Avoid compiler error: control reaches end of non-void function 221 | // [-Werror=return-type] 222 | return -1; 223 | } 224 | 225 | /** 226 | * Pretty-print information of EPID-based RA-TLS certificate to file descriptor. 227 | */ 228 | static 229 | void dprintf_epid_ratls_cert 230 | ( 231 | int fd, 232 | uint8_t* der_crt, 233 | uint32_t der_crt_len 234 | ) 235 | { 236 | attestation_verification_report_t report; 237 | extract_x509_extensions(der_crt, der_crt_len, &report); 238 | dprintf(fd, "\nIntel Attestation Service Report\n"); 239 | dprintf(fd, "%.*s\n", report.ias_report_len, report.ias_report); 240 | } 241 | 242 | /** 243 | * Pretty-print information of ECDSA-based RA-TLS certificate to file descriptor. 244 | */ 245 | static 246 | void dprintf_ecdsa_ratls_cert 247 | ( 248 | int fd, 249 | uint8_t* der_crt, 250 | uint32_t der_crt_len 251 | ) 252 | { 253 | ecdsa_attestation_evidence_t evidence; 254 | ecdsa_extract_x509_extensions(der_crt, der_crt_len, &evidence); 255 | 256 | dprintf(fd, "\nTCB info: "); 257 | dprintf(fd, "%.*s\n", evidence.tcb_info_len, evidence.tcb_info); 258 | dprintf(fd, "\nPCK Certificate:\n"); 259 | dprintf(fd, "%.*s\n", evidence.pck_crt_len, evidence.pck_crt); 260 | } 261 | 262 | void dprintf_ratls_cert 263 | ( 264 | int fd, 265 | uint8_t* der_crt, 266 | uint32_t der_crt_len 267 | ) 268 | { 269 | if (is_epid_ratls_cert(der_crt, der_crt_len)) { 270 | dprintf_epid_ratls_cert(fd, der_crt, der_crt_len); 271 | } else { 272 | dprintf_ecdsa_ratls_cert(fd, der_crt, der_crt_len); 273 | } 274 | 275 | sgx_quote_t quote; 276 | get_quote_from_cert(der_crt, der_crt_len, "e); 277 | sgx_report_body_t* body = "e.report_body; 278 | 279 | dprintf(fd, "MRENCLAVE = "); 280 | for (int i=0; i < SGX_HASH_SIZE; ++i) dprintf(fd, "%02x", body->mr_enclave.m[i]); 281 | dprintf(fd, "\n"); 282 | 283 | dprintf(fd, "MRSIGNER = "); 284 | for (int i=0; i < SGX_HASH_SIZE; ++i) dprintf(fd, "%02x", body->mr_signer.m[i]); 285 | dprintf(fd, "\n"); 286 | } 287 | -------------------------------------------------------------------------------- /ias-ra.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // for memmem() 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #if defined(USE_OPENSSL) 10 | #include // for base64 encode/decode 11 | #elif defined(USE_WOLFSSL) 12 | #include 13 | #include 14 | #elif defined(USE_MBEDTLS) 15 | #include 16 | #else 17 | #error Must use one of OpenSSL/wolfSSL/mbedtls 18 | #endif 19 | 20 | #include 21 | 22 | #include 23 | 24 | #include "ra.h" 25 | #include "ra-attester.h" 26 | #include "ias-ra.h" 27 | #include "curl_helper.h" 28 | 29 | static 30 | size_t accumulate_function(void *ptr, size_t size, size_t nmemb, void *userdata) { 31 | struct buffer_and_size* s = (struct buffer_and_size*) userdata; 32 | s->data = (char*) realloc(s->data, s->len + size * nmemb); 33 | assert(s->data != NULL); 34 | memcpy(s->data + s->len, ptr, size * nmemb); 35 | s->len += size * nmemb; 36 | 37 | return size * nmemb; 38 | } 39 | 40 | void http_get 41 | ( 42 | CURL* curl, 43 | const char* url, 44 | struct buffer_and_size* header, 45 | struct buffer_and_size* body, 46 | struct curl_slist* request_headers, 47 | char* request_body 48 | ) 49 | { 50 | curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); 51 | curl_easy_setopt(curl, CURLOPT_URL, url); 52 | curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1L); 53 | 54 | curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, accumulate_function); 55 | curl_easy_setopt(curl, CURLOPT_HEADERDATA, header); 56 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, accumulate_function); 57 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, body); 58 | 59 | if (request_headers) { 60 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, request_headers); 61 | } 62 | if (request_body) { 63 | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request_body); 64 | } 65 | 66 | CURLcode res = curl_easy_perform(curl); 67 | assert(res == CURLE_OK); 68 | } 69 | 70 | static const char pem_marker_begin[] = "-----BEGIN CERTIFICATE-----"; 71 | static const char pem_marker_end[] = "-----END CERTIFICATE-----"; 72 | 73 | static 74 | void extract_certificates_from_response_header 75 | ( 76 | CURL* curl, 77 | const char* header, 78 | size_t header_len, 79 | attestation_verification_report_t* attn_report 80 | ) 81 | { 82 | // Locate x-iasreport-signature HTTP header field in the response. 83 | const char response_header_name[] = "X-IASReport-Signing-Certificate: "; 84 | char *field_begin = memmem(header, 85 | header_len, 86 | response_header_name, 87 | strlen(response_header_name)); 88 | assert(field_begin != NULL); 89 | field_begin += strlen(response_header_name); 90 | const char http_line_break[] = "\r\n"; 91 | char *field_end = memmem(field_begin, 92 | header_len - (field_begin - header), 93 | http_line_break, 94 | strlen(http_line_break)); 95 | size_t field_len = field_end - field_begin; 96 | 97 | // Remove urlencoding from x-iasreport-signing-certificate field. 98 | int unescaped_len = 0; 99 | char* unescaped = curl_easy_unescape(curl, 100 | field_begin, 101 | field_len, 102 | &unescaped_len); 103 | 104 | char* cert_begin = memmem(unescaped, 105 | unescaped_len, 106 | pem_marker_begin, 107 | strlen(pem_marker_begin)); 108 | assert(cert_begin != NULL); 109 | char* cert_end = memmem(unescaped, unescaped_len, 110 | pem_marker_end, strlen(pem_marker_end)); 111 | assert(cert_end != NULL); 112 | uint32_t cert_len = cert_end - cert_begin + strlen(pem_marker_end); 113 | 114 | assert(cert_len <= sizeof(attn_report->ias_sign_cert)); 115 | memcpy(attn_report->ias_sign_cert, cert_begin, cert_len); 116 | attn_report->ias_sign_cert_len = cert_len; 117 | 118 | cert_begin = memmem(cert_end, 119 | unescaped_len - (cert_end - unescaped), 120 | pem_marker_begin, 121 | strlen(pem_marker_begin)); 122 | assert(cert_begin != NULL); 123 | cert_end = memmem(cert_begin, 124 | unescaped_len - (cert_begin - unescaped), 125 | pem_marker_end, 126 | strlen(pem_marker_end)); 127 | assert(cert_end != NULL); 128 | cert_len = cert_end - cert_begin + strlen(pem_marker_end); 129 | 130 | assert(cert_len <= sizeof(attn_report->ias_sign_ca_cert)); 131 | memcpy((char*) attn_report->ias_sign_ca_cert, cert_begin, cert_len); 132 | attn_report->ias_sign_ca_cert_len = cert_len; 133 | 134 | curl_free(unescaped); 135 | unescaped = NULL; 136 | } 137 | 138 | /* The header has the certificates and report signature. */ 139 | void parse_response_header 140 | ( 141 | const char* header, 142 | size_t header_len, 143 | unsigned char* signature, 144 | const size_t signature_max_size, 145 | uint32_t* signature_size 146 | ) 147 | { 148 | const char sig_tag[] = "X-IASReport-Signature: "; 149 | char* sig_begin = memmem((const char*) header, 150 | header_len, 151 | sig_tag, 152 | strlen(sig_tag)); 153 | assert(sig_begin != NULL); 154 | sig_begin += strlen(sig_tag); 155 | char* sig_end = memmem(sig_begin, 156 | header_len - (sig_begin - header), 157 | "\r\n", 158 | strlen("\r\n")); 159 | assert(sig_end); 160 | 161 | assert((size_t) (sig_end - sig_begin) <= signature_max_size); 162 | memcpy(signature, sig_begin, sig_end - sig_begin); 163 | *signature_size = sig_end - sig_begin; 164 | } 165 | 166 | /** 167 | * @return Length of base64 encoded data including terminating NUL-byte. 168 | */ 169 | static void base64_encode 170 | ( 171 | uint8_t *in, 172 | uint32_t in_len, 173 | uint8_t* out, 174 | uint32_t* out_len /* in/out */ 175 | ) 176 | { 177 | // + 1 to account for the terminating \0. 178 | assert(*out_len >= (in_len + 3 - 1) / 3 * 4 + 1); 179 | bzero(out, *out_len); 180 | 181 | #if defined(USE_OPENSSL) 182 | int ret = EVP_EncodeBlock(out, in, in_len); 183 | // + 1 since EVP_EncodeBlock() returns length excluding the terminating \0. 184 | assert((size_t) ret + 1 <= *out_len); 185 | *out_len = ret + 1; 186 | #elif defined(USE_WOLFSSL) 187 | int ret = Base64_Encode_NoNl(in, in_len, out, out_len); 188 | assert(ret == 0); 189 | // No need append terminating \0 since we memset() the whole 190 | // buffer in the beginning. 191 | *out_len += 1; 192 | #elif defined(USE_MBEDTLS) 193 | size_t olen; 194 | int ret = mbedtls_base64_encode(out, *out_len, &olen, in, in_len); 195 | assert(ret == 0); 196 | assert(olen <= UINT32_MAX); 197 | *out_len = (uint32_t) olen; 198 | #endif 199 | } 200 | 201 | /** Turns a binary quote into an attestation verification report. 202 | 203 | Communicates with Intel Attestation Service via its HTTP REST interface. 204 | */ 205 | void obtain_attestation_verification_report 206 | ( 207 | const sgx_quote_t* quote, 208 | const uint32_t quote_size, 209 | const struct ra_tls_options* opts, 210 | attestation_verification_report_t* attn_report 211 | ) 212 | { 213 | int ret; 214 | 215 | char url[512]; 216 | ret = snprintf(url, sizeof(url), "https://%s/attestation/v3/report", 217 | opts->ias_server); 218 | assert(ret < (int) sizeof(url)); 219 | 220 | char buf[128]; 221 | int rc = snprintf(buf, sizeof(buf), "Ocp-Apim-Subscription-Key: %.32s", 222 | opts->subscription_key); 223 | assert(rc < (int) sizeof(buf)); 224 | 225 | struct curl_slist *request_headers = 226 | curl_slist_append(NULL, "Content-Type: application/json"); 227 | request_headers = curl_slist_append(request_headers, buf); 228 | 229 | const char json_template[] = "{\"isvEnclaveQuote\":\"%s\"}"; 230 | unsigned char quote_base64[quote_size * 2]; 231 | uint32_t quote_base64_len = sizeof(quote_base64); 232 | char json[quote_size * 2]; 233 | 234 | base64_encode((uint8_t*) quote, quote_size, 235 | quote_base64, "e_base64_len); 236 | 237 | snprintf(json, sizeof(json), json_template, quote_base64); 238 | 239 | CURL *curl = curl_easy_init(); 240 | assert(curl != NULL); 241 | struct buffer_and_size header = {(char*) malloc(1), 0}; 242 | struct buffer_and_size body = {(char*) malloc(1), 0}; 243 | http_get(curl, url, &header, &body, request_headers, json); 244 | 245 | parse_response_header(header.data, header.len, 246 | attn_report->ias_report_signature, 247 | sizeof(attn_report->ias_report_signature), 248 | &attn_report->ias_report_signature_len); 249 | 250 | assert(sizeof(attn_report->ias_report) >= body.len); 251 | memcpy(attn_report->ias_report, body.data, body.len); 252 | attn_report->ias_report_len = body.len; 253 | 254 | extract_certificates_from_response_header(curl, 255 | header.data, header.len, 256 | attn_report); 257 | 258 | curl_easy_cleanup(curl); 259 | free(header.data); 260 | free(body.data); 261 | curl_slist_free_all(request_headers); 262 | } 263 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | > :warning: **DISCONTINUATION OF PROJECT** - *This project will no longer be maintained by Intel. Intel has ceased development and contributions including, but not limited to, maintenance, bug fixes, new releases, or updates, to this project.* **Intel no longer accepts patches to this project.** 4 | 5 | This project provides a proof-of-concept implementation on how to integrate Intel SGX remote attestation into the TLS connection setup. Conceptually, we extend the standard X.509 certificate with SGX-related information. The additional information allows the receiver of the certificate to verify that it is indeed communicating with an SGX enclave. The accompanying [white paper](whitepaper.pdf) "Integrating Remote Attestation with Transport Layer Security" provides more details. RA-TLS supports [EPID](https://software.intel.com/sites/default/files/managed/57/0e/ww10-2016-sgx-provisioning-and-attestation-final.pdf) and [ECDSA](https://software.intel.com/sites/default/files/managed/f1/b8/intel-sgx-support-for-third-party-attestation.pdf)-based attestation. 6 | 7 | Documentation on ECDSA-based attestation is [split out into a separate document](README-ECDSA.html). 8 | 9 | ## Repository Structure 10 | 11 | The repository root directory contains code to generate and parse extended X.509 certificates. The build system creates the following executables: 12 | 13 | - Sample server (attester) 14 | 15 | * using the SGX SDK based on [wolfSSL](deps/wolfssl-examples/SGX_Linux) 16 | * using [Graphene](https://github.com/oscarlab/graphene), [SCONE](https://sconedocs.github.io) or [SGX-LKL](https://github.com/lsds/sgx-lkl) based on [wolfSSL](deps/wolfssl-examples/tls/server-tls.c) 17 | * using [Graphene](https://github.com/oscarlab/graphene) based on [mbedtls](deps/mbedtls/programs/ssl/ssl_server.c) 18 | * [Python-based HTTPS web server](sgxlkl/https-server/https-server.py) running on SGX-LKL 19 | 20 | - Non-SGX clients (challengers) based on different TLS libraries 21 | 22 | * [mbedtls](deps/mbedtls/programs/ssl/ssl_client1.c) 23 | * [wolfSSL](deps/wolfssl-examples/tls/client-tls.c) 24 | * [OpenSSL](openssl-client.c) 25 | 26 | - Graphene client and server doing mutual attestation 27 | 28 | * [server-tls.c](deps/wolfssl-examples/tls/server-tls.c) 29 | * [client-tls.c](deps/wolfssl-examples/tls/client-tls.c) 30 | 31 | Some files may only exist after building the sources. 32 | 33 | ## Code Structure 34 | 35 | The code is split into two parts: the attester and the challenger. The challenger parses certificates, computes signatures and hashsums. The attester generates keys, certificates and interfaces with SGX. The challenger and attester are implemented with three different TLS libraries: wolfSSL ([challenger](wolfssl-ra-challenger.c), [attester](wolfssl-ra-attester.c)), mbedtls ([challenger](mbedtls-ra-challenger.c), [attester](mbedtls-ra-attester.c)) and OpenSSL ([challenger](openssl-ra-challenger.c), [attester](openssl-ra-attester.c)). 36 | 37 | The attester's code consists of [trusted](sgxsdk-ra-attester_t.c) and [untrusted](sgxsdk-ra-attester_u.c) SGX-SDK specific code to produce a quote using the SGX SDK. If the SGX SDK is not used, e.g., when using Graphene, there is code to [obtain the SGX quote](nonsdk-ra-attester.c) by directly communicating with the platform's architectural enclave. 38 | 39 | Given a quote, there is [code to obtain an attestation verification report](ias-ra.c) from the Intel Attestation Service. This code depends on libcurl. 40 | 41 | [An SGX SDK-based server](deps/wolfssl-examples/SGX_Linux) based on wolfSSL demonstrates how to use the [public attester API](ra-attester.h). 42 | 43 | We provide three non-SGX clients ([mbedtls](deps/mbedtls/programs/ssl/ssl_client1.c), [wolfSSL](deps/wolfssl-examples/tls/client-tls.c), [OpenSSL](openssl-client.c)) to show how seamless remote attestation works with different TLS libraries. They use the public [challenger's API](ra-challenger.h). There is one SGX client demonstrating mutual authentication (code: [client-tls.c](deps/wolfssl-examples/tls/client-tls.c), binary: wolfssl-client-mutual). 44 | 45 | # Build 46 | 47 | We have tested the code with enclaves created using the Intel SGX SDK, Graphene, SCONE and SGX-LKL. 48 | 49 | ## Prerequisites 50 | 51 | The code is tested with the [Intel SGX Linux 2.4 Release](https://01.org/intel-softwareguard-extensions/downloads/intel-sgx-linux-2.4-release) installed on the host. Results may vary with different versions. Follow the official instructions to install the components and ensure they are working as intended. For Graphene, follow [their instructions](https://github.com/oscarlab/graphene/wiki/SGX-Quick-Start) to build and load the Graphene kernel module. Only the Graphene kernel module is required as a prerequisite. Graphene itself is built by the scripts. 52 | 53 | To use the Intel Attestation Service for EPID-based attestation an [account must be created](https://api.portal.trustedservices.intel.com/EPID-attestation). The registration process will provide a subscription key and a software provider ID (SPID). The script [ra_tls_options.c.sh](ra_tls_options.c.sh) generates a C source file with these values. Either define the environment variables before building or invoke the script manually, i.e., `SPID=... EPID_SUBSCRIPTION_KEY=... ECDSA_SUBSCRIPTION_KEY=... QUOTE_TYPE=... bash ra_tls_options.c.sh`. See [ra_tls_options.c.sh](ra_tls_options.c.sh) for the specific format of each variable. ECDSA-based attestation [requires a separate registration.](https://api.portal.trustedservices.intel.com/provisioning-certification) 54 | 55 | We support building the code in a Docker container. We provide a [Dockerfile](Dockerfile) to install all the required packages. If you prefer to build on your host system, the Dockerfile documents which packages and additional software to install. You can create an image based on the Dockerfile as such 56 | 57 | docker build -t ratls . 58 | 59 | If you want to use SCONE and have access to their Docker images, edit the Dockerfile to use their image as the base instead of the default Ubuntu 16.04 (see first two lines of Dockerfile) 60 | 61 | docker build -t ratls-scone . 62 | 63 | ## Build Instructions 64 | 65 | The [build script](build.sh) creates executables based on either the Intel SGX SDK, Graphene, SCONE or SGX-LKL, depending on the first parameter 66 | 67 | ./build.sh sgxsdk|graphene|scone|sgxlkl 68 | 69 | To build in a container using the Docker image created earlier, execute the following command in the project's root directory 70 | 71 | docker run --device=/dev/isgx --device=/dev/gsgx \ 72 | --privileged=true \ 73 | -v /var/run/aesmd:/var/run/aesmd \ 74 | -v$(pwd):/project -it [Docker image] bash 75 | 76 | where [Docker image] is the name of the Docker image created earlier, i.e., either ratls or ratls-scone. The parameter --privileged=true is only needed for SGX-LKL to be able to mount loopback devices and change iptables. 77 | 78 | In the running container, change the directory and kick-off the build process 79 | 80 | cd /project 81 | ./build.sh sgxsdk|graphene|scone|sgxlkl 82 | 83 | # Run 84 | 85 | ## Intel SGX SDK 86 | 87 | To start the Intel SGX SDK based wolfSSL server execute 88 | 89 | ( cd deps/wolfssl-examples/SGX_Linux ; ./App -s ) 90 | 91 | With the server up and running, execute any of the [clients](#the-clients). If you are running in a container, you can get a 2nd console as follows (or run the server in the background by appending & at the end of the above command). 92 | 93 | docker ps 94 | 95 | Use the container's ID with the following command for a 2nd console. 96 | 97 | docker exec -ti --user root [container id] bash 98 | 99 | ## Graphene 100 | 101 | First, start a socat instance to make AESM's named Unix socket accessible over TCP/IP. 102 | 103 | socat -t10 TCP-LISTEN:1234,bind=127.0.0.1,reuseaddr,fork,range=127.0.0.0/8 UNIX-CLIENT:/var/run/aesmd/aesm.socket & 104 | 105 | Next, start the server application on Graphene 106 | 107 | SGX=1 ./deps/graphene/Runtime/pal_loader ./[binary] 108 | 109 | where [binary] can be mbedtls-ssl-server, wolfssl-ssl-server or wolfssl-ssl-server-mutual. 110 | 111 | ## SCONE 112 | 113 | Similar to Graphene, we use socat to make AESM accessible over TCP/IP. SCONE can in principle to talk to AESM's named Unix socket directly, but support for this is currently not implemented. 114 | 115 | socat -t10 TCP-LISTEN:1234,bind=127.0.0.1,reuseaddr,fork,range=127.0.0.0/8 UNIX-CLIENT:/var/run/aesmd/aesm.socket & 116 | 117 | Next, execute the SCONE binary as such 118 | 119 | ./scone-wolfssl-ssl-server 120 | 121 | ## SGX-LKL 122 | 123 | To set up the TAP device (used by SGX-LKL for networking), iptables (required for SGX-LKL to be able to reach the internet) and starts an socat daemon (to talk to the host's AESMD). EXTERNAL_INTERFACE specifies your "external" interface (typically eth0), i.e., the one which connects you to the internet. 124 | 125 | EXTERNAL_IFACE=eth0 make -C sgxlkl up-sgxlkl-network 126 | 127 | We provide two applications for SGX-LKL. First, a simple server based on wolfssl. This is similar to the examples provided for the other systems. Use Ctrl-C to stop the server. 128 | 129 | make -C sgxlkl run-wolfssl-server 130 | 131 | Use the openssl-client to connect to the server and print its SGX identity 132 | 133 | echo -n hello | ./openssl-client -p 11111 -h 10.0.1.1 134 | 135 | Second, there is a [Python-based HTTPS server](sgxlkl/https-server/https-server.py). We preload (LD_PRELOAD) a library with the server. The [preloaded library's](sgxlkl/ldpreload.c) initialization routine writes the key and certificate to /tmp/key and /tmp/crt, respectively. The server reads the RA-TLS key and certificate from the file system instead of calling the library directly. 136 | 137 | make -C sgxlkl run-https-server 138 | 139 | Warnings about LD_PRELOAD not being able to find /ldpreload.so can be ignored. LD_PRELOAD is also applied to the sgx-lkl-run binary, but ldpreload.so only exists within the LKL environment. The server listens on 10.0.1.1:4443. Using the RA-TLS-aware openssl-client you can connect to it as such 140 | 141 | ./openssl-client -p 4443 -h 10.0.1.1 142 | 143 | To stop socat, remove iptable rules and the TAP interface issue 144 | 145 | EXTERNAL_IFACE=eth0 make -C sgxlkl down-sgxlkl-network 146 | 147 | ## The clients 148 | 149 | ### Non-SGX clients 150 | 151 | Execute any one of the non-SGX binaries wolfssl-client, mbedtls-client or openssl-client in the project's root directory. 152 | The openssl-client is most versatile as it allows to specify the IP and port to connect to via command line parameters. 153 | Each client outputs a bunch of connection-related information, such as the server's SGX identity (MRENCLAVE, MRSIGNER). You can cross-check this with what the server reports in its output. 154 | 155 | ### SGX client 156 | 157 | The Graphene client wolfssl-client-mutual only works in combination with wolfssl-ssl-server-mutual. 158 | 159 | SGX=1 ./deps/graphene/Runtime/pal_loader ./wolfssl-client-mutual 160 | -------------------------------------------------------------------------------- /mbedtls-ra-attester.c: -------------------------------------------------------------------------------- 1 | /* Code to create an extended X.509 certificate using the mbedtls 2 | library. */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "ra.h" 21 | #include "ra-attester.h" 22 | #include "ra_private.h" 23 | 24 | static const size_t SHA256_DIGEST_SIZE = 32; 25 | 26 | static 27 | void sha256_rsa_pubkey(unsigned char hash[SHA256_DIGEST_SIZE], 28 | const mbedtls_pk_context* pk) { 29 | 30 | static const int pk_der_size_max = 512; 31 | uint8_t pk_der[pk_der_size_max]; 32 | memset(pk_der, 0, pk_der_size_max); 33 | 34 | /* From the mbedtls documentation: Write a public key to a 35 | SubjectPublicKeyInfo DER structure Note: data is written at the 36 | end of the buffer! Use the return value to determine where you 37 | should start using the buffer. */ 38 | int pk_der_size_byte = mbedtls_pk_write_pubkey_der((mbedtls_pk_context*) pk, 39 | pk_der, pk_der_size_max); 40 | // Assume 3072 bit RSA keys for now. 41 | assert(pk_der_size_byte == rsa_pub_3072_pcks_der_len); 42 | 43 | /* Move the data to the beginning of the buffer, to avoid pointer 44 | arithmetic from this point forward. */ 45 | memmove(pk_der, pk_der + pk_der_size_max - pk_der_size_byte, pk_der_size_byte); 46 | 47 | /* Exclude PCKS#1 header (rsa_pub_3072_pcks_header_len) from 48 | checksum. */ 49 | memset(hash, 0, SHA256_DIGEST_SIZE); 50 | mbedtls_sha256(pk_der + rsa_pub_3072_pcks_header_len, 51 | pk_der_size_byte - rsa_pub_3072_pcks_header_len, 52 | hash, 0 /* is224 */); 53 | } 54 | 55 | static 56 | void generate_x509 57 | ( 58 | mbedtls_x509write_cert* writecrt /* out */, 59 | mbedtls_pk_context* subject_key /* in */, 60 | const attestation_verification_report_t* attn_report 61 | ) 62 | { 63 | /* mbedtls_pk_context subject_key; */ 64 | 65 | int ret; 66 | mbedtls_x509write_crt_init(writecrt); 67 | mbedtls_x509write_crt_set_md_alg(writecrt, MBEDTLS_MD_SHA256); 68 | 69 | mbedtls_x509write_crt_set_subject_key(writecrt, subject_key); 70 | mbedtls_x509write_crt_set_issuer_key(writecrt, subject_key); 71 | 72 | ret = mbedtls_x509write_crt_set_subject_name(writecrt, 73 | "CN=127.0.0.1,O=mbed TLS,C=UK"); 74 | assert(ret == 0); 75 | ret = mbedtls_x509write_crt_set_issuer_name(writecrt, 76 | "CN=127.0.0.1,O=mbed TLS,C=UK"); 77 | assert(ret == 0); 78 | 79 | mbedtls_mpi serial; 80 | mbedtls_mpi_init(&serial); 81 | ret = mbedtls_mpi_read_string(&serial, 10, "1"); 82 | assert(ret == 0); 83 | 84 | ret = mbedtls_x509write_crt_set_serial(writecrt, &serial); 85 | assert(ret == 0); 86 | ret = mbedtls_x509write_crt_set_validity(writecrt, 87 | "20010101000000", "20301231235959"); 88 | assert(ret == 0); 89 | ret = mbedtls_x509write_crt_set_basic_constraints(writecrt, 0, -1); 90 | assert(ret == 0); 91 | ret = mbedtls_x509write_crt_set_subject_key_identifier(writecrt); 92 | assert(ret == 0); 93 | ret = mbedtls_x509write_crt_set_authority_key_identifier(writecrt); 94 | assert(ret == 0); 95 | 96 | // 1.2.840.113741.1337.2 97 | unsigned char oid_ias_report[] = {0x2A, 0x86, 0x48, 0x86, 0xF8, 0x4D, 0x8A, 0x39, 0x02}; 98 | // 1.2.840.113741.1337.3 99 | unsigned char oid_ias_sign_ca_cert[] = {0x2A, 0x86, 0x48, 0x86, 0xF8, 0x4D, 0x8A, 0x39, 0x03}; 100 | // 1.2.840.113741.1337.4 101 | unsigned char oid_ias_sign_cert[] = {0x2A, 0x86, 0x48, 0x86, 0xF8, 0x4D, 0x8A, 0x39, 0x04}; 102 | // 1.2.840.113741.1337.5 103 | unsigned char oid_ias_report_signature[] = {0x2A, 0x86, 0x48, 0x86, 0xF8, 0x4D, 0x8A, 0x39, 0x05}; 104 | 105 | ret = mbedtls_x509write_crt_set_extension(writecrt, 106 | (char*) oid_ias_report, 107 | sizeof(oid_ias_report), 108 | 0 /* criticial */, 109 | (const uint8_t*) attn_report->ias_report, 110 | attn_report->ias_report_len); 111 | assert(ret == 0); 112 | 113 | ret = mbedtls_x509write_crt_set_extension(writecrt, 114 | (char*) oid_ias_sign_ca_cert, 115 | sizeof(oid_ias_sign_ca_cert), 116 | 0 /* criticial */, 117 | (const uint8_t*) attn_report->ias_sign_ca_cert, 118 | attn_report->ias_sign_ca_cert_len); 119 | assert(ret == 0); 120 | 121 | ret = mbedtls_x509write_crt_set_extension(writecrt, 122 | (char*) oid_ias_sign_cert, 123 | sizeof(oid_ias_sign_cert), 124 | 0 /* criticial */, 125 | (const uint8_t*) attn_report->ias_sign_cert, 126 | attn_report->ias_sign_cert_len); 127 | assert(ret == 0); 128 | 129 | ret = mbedtls_x509write_crt_set_extension(writecrt, 130 | (char*) oid_ias_report_signature, 131 | sizeof(oid_ias_report_signature), 132 | 0 /* criticial */, 133 | (const uint8_t*) attn_report->ias_report_signature, 134 | attn_report->ias_report_signature_len); 135 | assert(ret == 0); 136 | 137 | mbedtls_mpi_free( &serial ); 138 | } 139 | 140 | /* Given a key, generate a certificate for it. */ 141 | static 142 | void create_x509 143 | ( 144 | mbedtls_pk_context* key, 145 | mbedtls_x509write_cert* writecrt, 146 | const struct ra_tls_options* opts 147 | ) 148 | { 149 | sgx_report_data_t report_data = {0, }; 150 | sha256_rsa_pubkey(report_data.d, key); 151 | attestation_verification_report_t attestation_report; 152 | 153 | do_remote_attestation(&report_data, opts, &attestation_report); 154 | 155 | generate_x509(writecrt, key, &attestation_report); 156 | 157 | /* printf_sgx("attestation_report.ias_report=\n"); */ 158 | /* printf_sgx("%.s", attestation_report.ias_report_len, attestation_report.ias_report); */ 159 | } 160 | 161 | /* Generate a key and write certificate. */ 162 | static 163 | void __mbedtls_create_key_and_x509 164 | ( 165 | mbedtls_pk_context* key, 166 | mbedtls_x509_crt* cert, 167 | uint8_t* der_cert, 168 | int* der_cert_len, 169 | uint8_t* pem_cert, 170 | int* pem_cert_len, 171 | const struct ra_tls_options* opts 172 | ) 173 | { 174 | int ret; 175 | int len; 176 | unsigned char output_buf[16 * 1024] = {0, }; 177 | 178 | mbedtls_x509write_cert writecrt; 179 | mbedtls_x509write_crt_init(&writecrt); 180 | 181 | mbedtls_ctr_drbg_context ctr_drbg; 182 | mbedtls_ctr_drbg_init( &ctr_drbg ); 183 | 184 | mbedtls_entropy_context entropy; 185 | mbedtls_entropy_init( &entropy ); 186 | 187 | const char* pers = "deadbeef"; 188 | ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, 189 | (const unsigned char *) pers, 190 | strlen(pers)); 191 | assert(ret == 0); 192 | 193 | mbedtls_pk_setup(key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)); 194 | 195 | mbedtls_rsa_init((mbedtls_rsa_context*)key->pk_ctx, 196 | MBEDTLS_RSA_PKCS_V15, 0); 197 | 198 | ret = mbedtls_rsa_gen_key((mbedtls_rsa_context*)key->pk_ctx, 199 | mbedtls_ctr_drbg_random, &ctr_drbg, 3072, 65537); 200 | assert(ret == 0); 201 | 202 | create_x509(key, &writecrt, opts); 203 | 204 | if (cert) { 205 | len = mbedtls_x509write_crt_der(&writecrt, output_buf, sizeof(output_buf), 206 | mbedtls_ctr_drbg_random, &ctr_drbg); 207 | assert(len > 0); 208 | mbedtls_x509_crt_parse_der(cert, output_buf + sizeof(output_buf) - len, len); 209 | } 210 | 211 | if (der_cert) { 212 | len = mbedtls_x509write_crt_der(&writecrt, output_buf, sizeof(output_buf), 213 | mbedtls_ctr_drbg_random, &ctr_drbg); 214 | assert(len > 0); 215 | assert(len <= *der_cert_len); 216 | memcpy(der_cert, output_buf + sizeof(output_buf) - len, len); 217 | *der_cert_len = len; 218 | } 219 | 220 | if (pem_cert) { 221 | len = mbedtls_x509write_crt_pem(&writecrt, output_buf, sizeof(output_buf), 222 | mbedtls_ctr_drbg_random, &ctr_drbg); 223 | assert(len == 0); 224 | len = strlen((char*) output_buf); 225 | assert(len <= *pem_cert_len); 226 | memcpy(pem_cert, output_buf, len); 227 | *pem_cert_len = len; 228 | } 229 | 230 | mbedtls_x509write_crt_free(&writecrt); 231 | mbedtls_ctr_drbg_free(&ctr_drbg); 232 | mbedtls_entropy_free(&entropy); 233 | } 234 | 235 | void mbedtls_create_key_and_x509 236 | ( 237 | mbedtls_pk_context* key, 238 | mbedtls_x509_crt* cert, 239 | const struct ra_tls_options* opts 240 | ) 241 | { 242 | __mbedtls_create_key_and_x509(key, cert, NULL, NULL, NULL, NULL, opts); 243 | } 244 | 245 | void create_key_and_x509 246 | ( 247 | uint8_t* der_key, /* out */ 248 | int* der_key_len, /* in/out */ 249 | uint8_t* der_cert, /* out */ 250 | int* der_cert_len, /* in/out */ 251 | const struct ra_tls_options* opts 252 | ) 253 | { 254 | unsigned char output_buf[16 * 1024] = {0, }; 255 | int len; 256 | 257 | mbedtls_pk_context key; 258 | mbedtls_pk_init(&key); 259 | 260 | __mbedtls_create_key_and_x509(&key, NULL, der_cert, der_cert_len, NULL, NULL, opts); 261 | 262 | len = mbedtls_pk_write_key_der(&key, output_buf, sizeof(output_buf)); 263 | assert(len > 0); 264 | memcpy(der_key, output_buf + sizeof(output_buf) - len, len); 265 | *der_key_len = len; 266 | } 267 | 268 | void create_key_and_x509_pem 269 | ( 270 | uint8_t* pem_key, /* out */ 271 | int* pem_key_len, /* in/out */ 272 | uint8_t* pem_cert, /* out */ 273 | int* pem_cert_len, /* in/out */ 274 | const struct ra_tls_options* opts 275 | ) 276 | { 277 | int ret; 278 | 279 | mbedtls_pk_context key; 280 | mbedtls_pk_init(&key); 281 | 282 | __mbedtls_create_key_and_x509(&key, NULL, NULL, NULL, pem_cert, pem_cert_len, opts); 283 | 284 | ret = mbedtls_pk_write_key_pem(&key, pem_key, *pem_key_len); 285 | assert(ret == 0); 286 | 287 | mbedtls_pk_free(&key); 288 | } 289 | --------------------------------------------------------------------------------