From eb0e72662516b05c19adaf3c032b723cf2a5ea14 Mon Sep 17 00:00:00 2001 From: Dmitrii Kuvaiskii Date: Mon, 26 Oct 2020 05:32:50 -0700 Subject: [PATCH] [Pal/Linux-SGX] Allow EPID attestation even with DCAP SGX driver Previously, Graphene assumed that if it was built with the DCAP SGX driver or in-kernel SGX driver, then it should use DCAP/ECDSA based attestation. In fact, the SGX driver has nothing to do with the attestation scheme. This commit allows to use EPID based attestation even when Graphene is built with the DCAP SGX driver. --- Documentation/manifest-syntax.rst | 11 +- Examples/ra-tls-mbedtls/Makefile | 6 +- Examples/ra-tls-secret-prov/Makefile | 6 +- Jenkinsfiles/Linux-SGX | 9 +- Jenkinsfiles/Linux-SGX-18.04 | 9 +- LibOS/shim/test/regression/Makefile | 2 +- Pal/regression/Makefile | 5 - Pal/src/host/Linux-SGX/db_misc.c | 56 ++-- Pal/src/host/Linux-SGX/enclave_ocalls.c | 9 +- Pal/src/host/Linux-SGX/enclave_ocalls.h | 7 +- Pal/src/host/Linux-SGX/ocall_types.h | 1 + Pal/src/host/Linux-SGX/sgx_attest.h | 7 +- Pal/src/host/Linux-SGX/sgx_enclave.c | 4 +- Pal/src/host/Linux-SGX/sgx_internal.h | 10 +- Pal/src/host/Linux-SGX/sgx_main.c | 5 +- Pal/src/host/Linux-SGX/sgx_platform.c | 276 ++++++++++-------- Pal/src/host/Linux-SGX/signer/pal_sgx_sign.py | 9 + Pal/src/host/Linux-SGX/tools/README.rst | 4 +- 18 files changed, 240 insertions(+), 196 deletions(-) diff --git a/Documentation/manifest-syntax.rst b/Documentation/manifest-syntax.rst index 2dd6e9e2..9e33501c 100644 --- a/Documentation/manifest-syntax.rst +++ b/Documentation/manifest-syntax.rst @@ -397,10 +397,13 @@ Attestation and quotes This syntax specifies the parameters for remote attestation. To enable it, ``remote_attestation`` must be set to ``1``. -For ECDSA/DCAP based attestation, no additional parameters are required. For -EPID based attestation, ``ra_client_linkable`` and ``ra_client_spid`` must -be additionally specified (linkable/unlinkable mode and SPID of the client -respectively). +For EPID based attestation, ``ra_client_linkable`` and ``ra_client_spid`` must +be filled with your registered Intel SGX EPID Attestation Service credentials +(linkable/unlinkable mode and SPID of the client respectively). + +For DCAP/ECDSA based attestation, ``ra_client_spid`` must be an empty string +(this is a hint to Graphene to use DCAP instead of EPID) and +``ra_client_linkable`` is ignored. Enabling per-thread and process-wide SGX stats ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Examples/ra-tls-mbedtls/Makefile b/Examples/ra-tls-mbedtls/Makefile index 765d0a23..b62f3417 100644 --- a/Examples/ra-tls-mbedtls/Makefile +++ b/Examples/ra-tls-mbedtls/Makefile @@ -16,9 +16,9 @@ GRAPHENEKEY ?= $(GRAPHENEDIR)/Pal/src/host/Linux-SGX/signer/enclave-key.pem ARCH_LIBDIR ?= /lib/x86_64-linux-gnu -# Specify your SPID and linkable/unlinkable attestation policy (only for EPID); -# these variables will not be used if this example is built for ECDSA/DCAP -RA_CLIENT_SPID ?= AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +# for EPID attestation, specify your SPID and linkable/unlinkable attestation policy; +# for DCAP/ECDSA attestation, specify SPID as empty string (linkable value is ignored) +RA_CLIENT_SPID ?= RA_CLIENT_LINKABLE ?= 0 ifeq ($(DEBUG),1) diff --git a/Examples/ra-tls-secret-prov/Makefile b/Examples/ra-tls-secret-prov/Makefile index 2e3b6089..4e4cbc62 100644 --- a/Examples/ra-tls-secret-prov/Makefile +++ b/Examples/ra-tls-secret-prov/Makefile @@ -14,9 +14,9 @@ GRAPHENEDIR ?= ../.. GRAPHENEKEY ?= $(GRAPHENEDIR)/Pal/src/host/Linux-SGX/signer/enclave-key.pem -# Specify your SPID and linkable/unlinkable attestation policy (only for EPID); -# these variables will not be used if this example is built for ECDSA/DCAP -RA_CLIENT_SPID ?= AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +# for EPID attestation, specify your SPID and linkable/unlinkable attestation policy; +# for DCAP/ECDSA attestation, specify SPID as empty string (linkable value is ignored) +RA_CLIENT_SPID ?= RA_CLIENT_LINKABLE ?= 0 ifeq ($(DEBUG),1) diff --git a/Jenkinsfiles/Linux-SGX b/Jenkinsfiles/Linux-SGX index e9ea21dd..4d19c2d1 100644 --- a/Jenkinsfiles/Linux-SGX +++ b/Jenkinsfiles/Linux-SGX @@ -50,12 +50,6 @@ pipeline { timeout(time: 15, unit: 'MINUTES') { sh ''' cd Pal/regression - if [ "${ra_client_spid}" != "" ]; then \ - make clean SGX=1; \ - make -j8 SGX=1 RA_CLIENT_SPID=${ra_client_spid}; \ - else \ - make -j8 SGX=1; \ - fi make -j8 SGX=1 all sgx-tokens make SGX=1 KEEP_LOG=1 regression ''' @@ -63,7 +57,8 @@ pipeline { timeout(time: 15, unit: 'MINUTES') { sh ''' cd LibOS/shim/test/regression - make -j8 SGX=1 all sgx-tokens + make clean SGX=1 # re-build with ra_client_spid set + make -j8 SGX=1 RA_CLIENT_SPID=${ra_client_spid} all sgx-tokens make SGX=1 regression ''' } diff --git a/Jenkinsfiles/Linux-SGX-18.04 b/Jenkinsfiles/Linux-SGX-18.04 index 1df27b35..d8b11ef5 100644 --- a/Jenkinsfiles/Linux-SGX-18.04 +++ b/Jenkinsfiles/Linux-SGX-18.04 @@ -69,12 +69,6 @@ pipeline { timeout(time: 15, unit: 'MINUTES') { sh ''' cd Pal/regression - if [ "${ra_client_spid}" != "" ]; then \ - make clean SGX=1; \ - make -j8 SGX=1 RA_CLIENT_SPID=${ra_client_spid}; \ - else \ - make -j8 SGX=1; \ - fi make -j8 SGX=1 all sgx-tokens make SGX=1 KEEP_LOG=1 regression ''' @@ -82,7 +76,8 @@ pipeline { timeout(time: 15, unit: 'MINUTES') { sh ''' cd LibOS/shim/test/regression - make -j8 SGX=1 all sgx-tokens + make clean SGX=1 # re-build with ra_client_spid set + make -j8 SGX=1 RA_CLIENT_SPID=${ra_client_spid} all sgx-tokens make SGX=1 regression ''' } diff --git a/LibOS/shim/test/regression/Makefile b/LibOS/shim/test/regression/Makefile index b6cd3068..a75d68b7 100644 --- a/LibOS/shim/test/regression/Makefile +++ b/LibOS/shim/test/regression/Makefile @@ -136,7 +136,7 @@ target = \ clean-extra += clean-tmp extra_rules = \ - -e 's:\$$(RA_CLIENT_SPID):$(if $(RA_CLIENT_SPID),$(RA_CLIENT_SPID),AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA):g' \ + -e 's:\$$(RA_CLIENT_SPID):$(if $(RA_CLIENT_SPID),$(RA_CLIENT_SPID),):g' \ -e 's:\$$(RA_CLIENT_LINKABLE):$(if $(RA_CLIENT_LINKABLE),$(RA_CLIENT_LINKABLE),0):g' include ../../../../Scripts/Makefile.manifest diff --git a/Pal/regression/Makefile b/Pal/regression/Makefile index a7839a93..96f99920 100644 --- a/Pal/regression/Makefile +++ b/Pal/regression/Makefile @@ -92,11 +92,6 @@ all: $(target) $(call expand_target_to_sig,$(target)) $(call expand_target_to_sg .PHONY: sgx-tokens sgx-tokens: $(call expand_target_to_token,$(target)) -manifest_rules = \ - -e 's:\$$(PWD):$(shell pwd)/:g' \ - -e 's:\$$(RA_CLIENT_SPID):$(RA_CLIENT_SPID):g' \ - -e 's:\$$(RA_CLIENT_LINKABLE):$(if $(RA_CLIENT_LINKABLE),$(RA_CLIENT_LINKABLE),0):g' - .PHONY: crt_init-recurse crt_init-recurse: $(MAKE) -C ../crt_init all diff --git a/Pal/src/host/Linux-SGX/db_misc.c b/Pal/src/host/Linux-SGX/db_misc.c index fb8db17b..55217be2 100644 --- a/Pal/src/host/Linux-SGX/db_misc.c +++ b/Pal/src/host/Linux-SGX/db_misc.c @@ -381,39 +381,42 @@ int _DkAttestationQuote(const PAL_PTR user_report_data, PAL_NUM user_report_data if (user_report_data_size != sizeof(sgx_report_data_t)) return -PAL_ERROR_INVAL; -#ifdef SGX_DCAP - /* for DCAP attestation, spid and linkable arguments are ignored */ - sgx_spid_t spid = {0}; - bool linkable = false; -#else - char spid_hex[sizeof(sgx_spid_t) * 2 + 1]; + bool is_epid; + sgx_spid_t spid; + bool linkable; + + char spid_hex[sizeof(spid) * 2 + 1]; ssize_t len = get_config(g_pal_state.root_config, "sgx.ra_client_spid", spid_hex, sizeof(spid_hex)); if (len <= 0) { - SGX_DBG(DBG_E, "No Software Provider ID (sgx.ra_client_spid) specified in the manifest. " - "Graphene can not perform SGX quote retrieval.\n"); - return -PAL_ERROR_INVAL; - } + /* No Software Provider ID (SPID) specified in the manifest, it is DCAP attestation -- + * for DCAP, spid and linkable arguments are ignored (we unset them for sanity) */ + is_epid = false; + memset(&spid, 0, sizeof(spid)); + linkable = false; + } else { + /* SPID specified in the manifest, it is EPID attestation -- read spid and linkable */ + is_epid = true; - if (len != sizeof(sgx_spid_t) * 2) { - SGX_DBG(DBG_E, "Malformed sgx.ra_client_spid value in the manifest: %s\n", spid_hex); - return -PAL_ERROR_INVAL; - } - - sgx_spid_t spid; - for (ssize_t i = 0; i < len; i++) { - int8_t val = hex2dec(spid_hex[i]); - if (val < 0) { + if (len != sizeof(spid) * 2) { SGX_DBG(DBG_E, "Malformed sgx.ra_client_spid value in the manifest: %s\n", spid_hex); return -PAL_ERROR_INVAL; } - spid[i / 2] = spid[i / 2] * 16 + (uint8_t)val; - } - char buf[2]; - len = get_config(g_pal_state.root_config, "sgx.ra_client_linkable", buf, sizeof(buf)); - bool linkable = (len == 1 && buf[0] == '1'); -#endif + for (ssize_t i = 0; i < len; i++) { + int8_t val = hex2dec(spid_hex[i]); + if (val < 0) { + SGX_DBG(DBG_E, "Malformed sgx.ra_client_spid value in the manifest: %s\n", + spid_hex); + return -PAL_ERROR_INVAL; + } + spid[i / 2] = spid[i / 2] * 16 + (uint8_t)val; + } + + char buf[2]; + len = get_config(g_pal_state.root_config, "sgx.ra_client_linkable", buf, sizeof(buf)); + linkable = (len == 1 && buf[0] == '1'); + } sgx_quote_nonce_t nonce; int ret = _DkRandomBitsRead(&nonce, sizeof(nonce)); @@ -423,7 +426,8 @@ int _DkAttestationQuote(const PAL_PTR user_report_data, PAL_NUM user_report_data char* pal_quote = NULL; size_t pal_quote_size = 0; - ret = sgx_get_quote(&spid, &nonce, user_report_data, linkable, &pal_quote, &pal_quote_size); + ret = sgx_get_quote(is_epid ? &spid : NULL, &nonce, user_report_data, linkable, &pal_quote, + &pal_quote_size); if (ret < 0) return ret; diff --git a/Pal/src/host/Linux-SGX/enclave_ocalls.c b/Pal/src/host/Linux-SGX/enclave_ocalls.c index 9526180f..4960c93e 100644 --- a/Pal/src/host/Linux-SGX/enclave_ocalls.c +++ b/Pal/src/host/Linux-SGX/enclave_ocalls.c @@ -1405,7 +1405,14 @@ int ocall_get_quote(const sgx_spid_t* spid, bool linkable, const sgx_report_t* r goto out; } - memcpy(&ms->ms_spid, spid, sizeof(*spid)); + if (spid) { + WRITE_ONCE(ms->ms_is_epid, true); + memcpy(&ms->ms_spid, spid, sizeof(*spid)); + } else { + WRITE_ONCE(ms->ms_is_epid, false); + memset(&ms->ms_spid, 0, sizeof(ms->ms_spid)); /* for sanity */ + } + memcpy(&ms->ms_report, report, sizeof(*report)); memcpy(&ms->ms_nonce, nonce, sizeof(*nonce)); WRITE_ONCE(ms->ms_linkable, linkable); diff --git a/Pal/src/host/Linux-SGX/enclave_ocalls.h b/Pal/src/host/Linux-SGX/enclave_ocalls.h index 9ab87ef4..c63e64fe 100644 --- a/Pal/src/host/Linux-SGX/enclave_ocalls.h +++ b/Pal/src/host/Linux-SGX/enclave_ocalls.h @@ -98,10 +98,11 @@ int ocall_eventfd(unsigned int initval, int flags); * The obtained quote is not validated in any way (i.e., this function does not check whether the * returned quote corresponds to this enclave or whether its contents make sense). * - * \param[in] spid Software provider ID (SPID). - * \param[in] linkable Quote type (linkable vs unlinkable). + * \param[in] spid Software provider ID (SPID); if NULL then DCAP/ECDSA is used. + * \param[in] linkable Quote type (linkable vs unlinkable); ignored if DCAP/ECDSA is used. * \param[in] report Enclave report to be sent to the Quoting Enclave. - * \param[in] nonce 16B nonce to be included in the quote for freshness. + * \param[in] nonce 16B nonce to be included in the quote for freshness; ignored if + * DCAP/ECDSA is used. * \param[out] quote Quote returned by the Quoting Enclave (allocated via malloc() in this * function; the caller gets the ownership of the quote). * \param[out] quote_len Length of the quote returned by the Quoting Enclave. diff --git a/Pal/src/host/Linux-SGX/ocall_types.h b/Pal/src/host/Linux-SGX/ocall_types.h index f240f389..8fdc6edc 100644 --- a/Pal/src/host/Linux-SGX/ocall_types.h +++ b/Pal/src/host/Linux-SGX/ocall_types.h @@ -277,6 +277,7 @@ typedef struct { } ms_ocall_eventfd_t; typedef struct { + bool ms_is_epid; sgx_spid_t ms_spid; bool ms_linkable; sgx_report_t ms_report; diff --git a/Pal/src/host/Linux-SGX/sgx_attest.h b/Pal/src/host/Linux-SGX/sgx_attest.h index 2919cb7c..16813c47 100644 --- a/Pal/src/host/Linux-SGX/sgx_attest.h +++ b/Pal/src/host/Linux-SGX/sgx_attest.h @@ -77,10 +77,11 @@ enum { * then call out of the enclave to request the corresponding Quote from the Quoting Enclave. * Communication is done via AESM service, in the form of protobuf request/response messages. * - * \param[in] spid Software provider ID (SPID). - * \param[in] nonce 16B nonce to be included in the quote for freshness. + * \param[in] spid Software provider ID (SPID); if NULL then DCAP/ECDSA is used. + * \param[in] nonce 16B nonce to be included in the quote for freshness; ignored if + * DCAP/ECDSA is used. * \param[in] report_data 64B bytestring to be included in the report and the quote. - * \param[in] linkable Quote type (linkable vs unlinkable). + * \param[in] linkable Quote type (linkable vs unlinkable); ignored if DCAP/ECDSA is used. * \param[out] quote Quote returned by the Quoting Enclave (allocated via malloc() in this * function; the caller gets the ownership of the quote). * \param[out] quote_len Length of the quote returned by the Quoting Enclave. diff --git a/Pal/src/host/Linux-SGX/sgx_enclave.c b/Pal/src/host/Linux-SGX/sgx_enclave.c index 5c4532dc..c9e62361 100644 --- a/Pal/src/host/Linux-SGX/sgx_enclave.c +++ b/Pal/src/host/Linux-SGX/sgx_enclave.c @@ -645,8 +645,8 @@ static long sgx_ocall_update_debugger(void* pms) { static long sgx_ocall_get_quote(void* pms) { ms_ocall_get_quote_t* ms = (ms_ocall_get_quote_t*)pms; ODEBUG(OCALL_GET_QUOTE, ms); - return retrieve_quote(&ms->ms_spid, ms->ms_linkable, &ms->ms_report, &ms->ms_nonce, - &ms->ms_quote, &ms->ms_quote_len); + return retrieve_quote(ms->ms_is_epid ? &ms->ms_spid : NULL, ms->ms_linkable, &ms->ms_report, + &ms->ms_nonce, &ms->ms_quote, &ms->ms_quote_len); } sgx_ocall_fn_t ocall_table[OCALL_NR] = { diff --git a/Pal/src/host/Linux-SGX/sgx_internal.h b/Pal/src/host/Linux-SGX/sgx_internal.h index 655ec36b..6665fb64 100644 --- a/Pal/src/host/Linux-SGX/sgx_internal.h +++ b/Pal/src/host/Linux-SGX/sgx_internal.h @@ -92,18 +92,20 @@ int add_pages_to_enclave(sgx_arch_secs_t* secs, void* addr, void* user_addr, uns /*! * \brief Retrieve Quoting Enclave's sgx_target_info_t by talking to AESMD. * + * \param[in] is_epid Use EPID attestation if true, DCAP/ECDSA if false. * \param[out] qe_targetinfo Retrieved Quoting Enclave's target info. * \return 0 on success, negative error code otherwise. */ -int init_quoting_enclave_targetinfo(sgx_target_info_t* qe_targetinfo); +int init_quoting_enclave_targetinfo(bool is_epid, sgx_target_info_t* qe_targetinfo); /*! * \brief Obtain SGX Quote from the Quoting Enclave (communicate via AESM). * - * \param[in] spid Software provider ID (SPID). - * \param[in] linkable Quote type (linkable vs unlinkable). + * \param[in] spid Software provider ID (SPID); if NULL then DCAP/ECDSA is used. + * \param[in] linkable Quote type (linkable vs unlinkable); ignored if DCAP/ECDSA is used. * \param[in] report Enclave report to convert into a quote. - * \param[in] nonce 16B nonce to be included in the quote for freshness. + * \param[in] nonce 16B nonce to be included in the quote for freshness; ignored if + * DCAP/ECDSA is used. * \param[out] quote Quote returned by the Quoting Enclave (allocated via mmap() in this * function; the caller gets the ownership of the quote). * \param[out] quote_len Length of the quote returned by the Quoting Enclave. diff --git a/Pal/src/host/Linux-SGX/sgx_main.c b/Pal/src/host/Linux-SGX/sgx_main.c index 7b8d050a..c2f5e538 100644 --- a/Pal/src/host/Linux-SGX/sgx_main.c +++ b/Pal/src/host/Linux-SGX/sgx_main.c @@ -862,7 +862,10 @@ static int load_enclave(struct pal_enclave* enclave, int manifest_fd, char* mani if (get_config(enclave->config, "sgx.remote_attestation", cfgbuf, sizeof(cfgbuf)) > 0) { /* initialize communication with Quoting Enclave only if app requests attestation */ - ret = init_quoting_enclave_targetinfo(&pal_sec->qe_targetinfo); + bool is_epid; /* EPID is used if SPID is specified in manifest, otherwise DCAP/ECDSA */ + is_epid = get_config(enclave->config, "sgx.ra_client_spid", cfgbuf, sizeof(cfgbuf)) > 0; + SGX_DBG(DBG_I, "Using SGX %s attestation\n", is_epid ? "EPID" : "DCAP/ECDSA"); + ret = init_quoting_enclave_targetinfo(is_epid, &pal_sec->qe_targetinfo); if (ret < 0) return ret; } diff --git a/Pal/src/host/Linux-SGX/sgx_platform.c b/Pal/src/host/Linux-SGX/sgx_platform.c index 7c446026..495669fd 100644 --- a/Pal/src/host/Linux-SGX/sgx_platform.c +++ b/Pal/src/host/Linux-SGX/sgx_platform.c @@ -15,7 +15,6 @@ #define AESM_SOCKET_NAME_LEGACY "sgx_aesm_socket_base" #define AESM_SOCKET_NAME_NEW "/var/run/aesmd/aesm.socket" -#ifdef SGX_DCAP /* hard-coded production attestation key of Intel reference QE (the only supported one) */ /* FIXME: should allow other attestation keys from non-Intel QEs */ static const sgx_ql_att_key_id_t g_default_ecdsa_p256_att_key_id = { @@ -43,7 +42,6 @@ static const sgx_ql_att_key_id_t g_default_ecdsa_p256_att_key_id = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, .algorithm_id = SGX_QL_ALG_ECDSA_P256, }; -#endif /* * Connect to the AESM service to interact with the architectural enclave. Must reconnect @@ -124,67 +122,77 @@ out: return -ERRNO(ret); } -int init_quoting_enclave_targetinfo(sgx_target_info_t* qe_target_info) { - Request req = REQUEST__INIT; - -#ifdef SGX_DCAP - sgx_att_key_id_t default_att_key_id; - memset(&default_att_key_id, 0, sizeof(default_att_key_id)); - memcpy(&default_att_key_id, &g_default_ecdsa_p256_att_key_id, - sizeof(g_default_ecdsa_p256_att_key_id)); - - Request__InitQuoteExRequest initexreq = REQUEST__INIT_QUOTE_EX_REQUEST__INIT; - initexreq.has_att_key_id = true; - initexreq.att_key_id.data = (uint8_t*)&default_att_key_id; - initexreq.att_key_id.len = sizeof(default_att_key_id); - initexreq.b_pub_key_id = true; - initexreq.has_buf_size = true; - initexreq.buf_size = SGX_HASH_SIZE; - req.initquoteexreq = &initexreq; -#else - Request__InitQuoteRequest initreq = REQUEST__INIT_QUOTE_REQUEST__INIT; - req.initquotereq = &initreq; -#endif +int init_quoting_enclave_targetinfo(bool is_epid, sgx_target_info_t* qe_targetinfo) { + int ret; + Request req = REQUEST__INIT; Response* res = NULL; - int ret = request_aesm_service(&req, &res); - if (ret < 0) - return ret; - ret = -EPERM; -#ifdef SGX_DCAP - if (!res->initquoteexres) { -#else - if (!res->initquoteres) { -#endif - SGX_DBG(DBG_E, "aesm_service returned wrong message\n"); - goto failed; + if (is_epid) { + Request__InitQuoteRequest initreq = REQUEST__INIT_QUOTE_REQUEST__INIT; + req.initquotereq = &initreq; + + ret = request_aesm_service(&req, &res); + if (ret < 0) + return ret; + + ret = -EPERM; + if (!res->initquoteres) { + SGX_DBG(DBG_E, "aesm_service returned wrong message\n"); + goto failed; + } + + Response__InitQuoteResponse* r = res->initquoteres; + if (r->errorcode != 0) { + SGX_DBG(DBG_E, "aesm_service returned error: %d\n", r->errorcode); + goto failed; + } + + if (r->targetinfo.len != sizeof(*qe_targetinfo)) { + SGX_DBG(DBG_E, "Quoting Enclave returned invalid target info\n"); + goto failed; + } + + memcpy(qe_targetinfo, r->targetinfo.data, sizeof(*qe_targetinfo)); + } else { + sgx_att_key_id_t default_att_key_id; + memset(&default_att_key_id, 0, sizeof(default_att_key_id)); + memcpy(&default_att_key_id, &g_default_ecdsa_p256_att_key_id, + sizeof(g_default_ecdsa_p256_att_key_id)); + + Request__InitQuoteExRequest initexreq = REQUEST__INIT_QUOTE_EX_REQUEST__INIT; + initexreq.has_att_key_id = true; + initexreq.att_key_id.data = (uint8_t*)&default_att_key_id; + initexreq.att_key_id.len = sizeof(default_att_key_id); + initexreq.b_pub_key_id = true; + initexreq.has_buf_size = true; + initexreq.buf_size = SGX_HASH_SIZE; + req.initquoteexreq = &initexreq; + + ret = request_aesm_service(&req, &res); + if (ret < 0) + return ret; + + ret = -EPERM; + if (!res->initquoteexres) { + SGX_DBG(DBG_E, "aesm_service returned wrong message\n"); + goto failed; + } + + Response__InitQuoteExResponse* r = res->initquoteexres; + if (r->errorcode != 0) { + SGX_DBG(DBG_E, "aesm_service returned error: %d\n", r->errorcode); + goto failed; + } + + if (r->target_info.len != sizeof(*qe_targetinfo)) { + SGX_DBG(DBG_E, "Quoting Enclave returned invalid target info\n"); + goto failed; + } + + memcpy(qe_targetinfo, r->target_info.data, sizeof(*qe_targetinfo)); } -#ifdef SGX_DCAP - Response__InitQuoteExResponse* r = res->initquoteexres; -#else - Response__InitQuoteResponse* r = res->initquoteres; -#endif - if (r->errorcode != 0) { - SGX_DBG(DBG_E, "aesm_service returned error: %d\n", r->errorcode); - goto failed; - } - -#ifdef SGX_DCAP - if (r->target_info.len != sizeof(*qe_target_info)) { -#else - if (r->targetinfo.len != sizeof(*qe_target_info)) { -#endif - SGX_DBG(DBG_E, "Quoting Enclave returned invalid target info\n"); - goto failed; - } - -#ifdef SGX_DCAP - memcpy(qe_target_info, r->target_info.data, sizeof(*qe_target_info)); -#else - memcpy(qe_target_info, r->targetinfo.data, sizeof(*qe_target_info)); -#endif ret = 0; failed: response__free_unpacked(res, NULL); @@ -193,85 +201,103 @@ failed: int retrieve_quote(const sgx_spid_t* spid, bool linkable, const sgx_report_t* report, const sgx_quote_nonce_t* nonce, char** quote, size_t* quote_len) { -#ifdef SGX_DCAP - __UNUSED(spid); - __UNUSED(linkable); - __UNUSED(nonce); -#endif - int ret = connect_aesm_service(); if (ret < 0) return ret; - Request req = REQUEST__INIT; - -#ifdef SGX_DCAP - sgx_att_key_id_t default_att_key_id; - memset(&default_att_key_id, 0, sizeof(default_att_key_id)); - memcpy(&default_att_key_id, &g_default_ecdsa_p256_att_key_id, - sizeof(g_default_ecdsa_p256_att_key_id)); - - Request__GetQuoteExRequest getreq = REQUEST__GET_QUOTE_EX_REQUEST__INIT; - getreq.report.data = (uint8_t*)report; - getreq.report.len = SGX_REPORT_ACTUAL_SIZE; - getreq.has_att_key_id = true; - getreq.att_key_id.data = (uint8_t*)&default_att_key_id; - getreq.att_key_id.len = sizeof(default_att_key_id); - getreq.has_qe_report_info = false; /* used to detect early that QE was spoofed; ignore now */ - getreq.qe_report_info.data = NULL; - getreq.qe_report_info.len = 0; - getreq.buf_size = SGX_QUOTE_MAX_SIZE; - req.getquoteexreq = &getreq; -#else - Request__GetQuoteRequest getreq = REQUEST__GET_QUOTE_REQUEST__INIT; - getreq.report.data = (uint8_t*)report; - getreq.report.len = SGX_REPORT_ACTUAL_SIZE; - getreq.quote_type = linkable ? SGX_LINKABLE_SIGNATURE : SGX_UNLINKABLE_SIGNATURE; - getreq.spid.data = (uint8_t*)spid; - getreq.spid.len = sizeof(*spid); - getreq.has_nonce = true; - getreq.nonce.data = (uint8_t*)nonce; - getreq.nonce.len = sizeof(*nonce); - getreq.buf_size = SGX_QUOTE_MAX_SIZE; - getreq.has_qe_report = true; - getreq.qe_report = true; - req.getquotereq = &getreq; -#endif - + Request req = REQUEST__INIT; Response* res = NULL; - ret = request_aesm_service(&req, &res); - if (ret < 0) - return ret; - ret = -EPERM; -#ifdef SGX_DCAP - if (!res->getquoteexres) { -#else - if (!res->getquoteres) { -#endif - SGX_DBG(DBG_E, "aesm_service returned wrong message\n"); - goto out; - } + sgx_quote_t* actual_quote = NULL; -#ifdef SGX_DCAP - Response__GetQuoteExResponse* r = res->getquoteexres; -#else - Response__GetQuoteResponse* r = res->getquoteres; -#endif - if (r->errorcode != 0) { - SGX_DBG(DBG_E, "aesm_service returned error: %d\n", r->errorcode); - goto out; - } + if (!spid) { + /* No Software Provider ID (SPID) specified, it is DCAP attestation */ + __UNUSED(linkable); + __UNUSED(nonce); - if (!r->has_quote || r->quote.len < sizeof(sgx_quote_t)) { - SGX_DBG(DBG_E, "aesm_service returned invalid quote\n"); - goto out; + sgx_att_key_id_t default_att_key_id; + memset(&default_att_key_id, 0, sizeof(default_att_key_id)); + memcpy(&default_att_key_id, &g_default_ecdsa_p256_att_key_id, + sizeof(g_default_ecdsa_p256_att_key_id)); + + Request__GetQuoteExRequest getreq = REQUEST__GET_QUOTE_EX_REQUEST__INIT; + getreq.report.data = (uint8_t*)report; + getreq.report.len = SGX_REPORT_ACTUAL_SIZE; + getreq.has_att_key_id = true; + getreq.att_key_id.data = (uint8_t*)&default_att_key_id; + getreq.att_key_id.len = sizeof(default_att_key_id); + getreq.has_qe_report_info = false; /* used to detect early that QE was spoofed; ignore now */ + getreq.qe_report_info.data = NULL; + getreq.qe_report_info.len = 0; + getreq.buf_size = SGX_QUOTE_MAX_SIZE; + req.getquoteexreq = &getreq; + + ret = request_aesm_service(&req, &res); + if (ret < 0) + return ret; + + ret = -EPERM; + if (!res->getquoteexres) { + SGX_DBG(DBG_E, "aesm_service returned wrong message\n"); + goto out; + } + + Response__GetQuoteExResponse* r = res->getquoteexres; + if (r->errorcode != 0) { + SGX_DBG(DBG_E, "aesm_service returned error: %d\n", r->errorcode); + goto out; + } + + if (!r->has_quote || r->quote.len < sizeof(sgx_quote_t)) { + SGX_DBG(DBG_E, "aesm_service returned invalid quote\n"); + goto out; + } + + actual_quote = (sgx_quote_t*)r->quote.data; + } else { + /* SPID specified, it is EPID attestation */ + Request__GetQuoteRequest getreq = REQUEST__GET_QUOTE_REQUEST__INIT; + getreq.report.data = (uint8_t*)report; + getreq.report.len = SGX_REPORT_ACTUAL_SIZE; + getreq.quote_type = linkable ? SGX_LINKABLE_SIGNATURE : SGX_UNLINKABLE_SIGNATURE; + getreq.spid.data = (uint8_t*)spid; + getreq.spid.len = sizeof(*spid); + getreq.has_nonce = true; + getreq.nonce.data = (uint8_t*)nonce; + getreq.nonce.len = sizeof(*nonce); + getreq.buf_size = SGX_QUOTE_MAX_SIZE; + getreq.has_qe_report = true; + getreq.qe_report = true; + req.getquotereq = &getreq; + + ret = request_aesm_service(&req, &res); + if (ret < 0) + return ret; + + ret = -EPERM; + if (!res->getquoteres) { + SGX_DBG(DBG_E, "aesm_service returned wrong message\n"); + goto out; + } + + Response__GetQuoteResponse* r = res->getquoteres; + if (r->errorcode != 0) { + SGX_DBG(DBG_E, "aesm_service returned error: %d\n", r->errorcode); + goto out; + } + + if (!r->has_quote || r->quote.len < sizeof(sgx_quote_t)) { + SGX_DBG(DBG_E, "aesm_service returned invalid quote\n"); + goto out; + } + + actual_quote = (sgx_quote_t*)r->quote.data; } /* Intel SGX SDK implementation of the Quoting Enclave always sets `quote.len` to user-provided * `getreq.buf_size` (see above) instead of the actual size. We calculate the actual size here * by peeking into the quote and determining the size of the signature. */ - size_t actual_quote_size = sizeof(sgx_quote_t) + ((sgx_quote_t*)r->quote.data)->signature_len; + size_t actual_quote_size = sizeof(sgx_quote_t) + actual_quote->signature_len; if (actual_quote_size > SGX_QUOTE_MAX_SIZE) { SGX_DBG(DBG_E, "Size of the obtained SGX quote exceeds %d\n", SGX_QUOTE_MAX_SIZE); goto out; @@ -285,7 +311,7 @@ int retrieve_quote(const sgx_spid_t* spid, bool linkable, const sgx_report_t* re goto out; } - memcpy(mmapped, r->quote.data, actual_quote_size); + memcpy(mmapped, actual_quote, actual_quote_size); *quote = mmapped; *quote_len = actual_quote_size; diff --git a/Pal/src/host/Linux-SGX/signer/pal_sgx_sign.py b/Pal/src/host/Linux-SGX/signer/pal_sgx_sign.py index 755fb092..e0987ce0 100644 --- a/Pal/src/host/Linux-SGX/signer/pal_sgx_sign.py +++ b/Pal/src/host/Linux-SGX/signer/pal_sgx_sign.py @@ -810,6 +810,15 @@ def main_sign(args): print(" misc_select: %08x" % int.from_bytes(attr['misc_select'], byteorder='big')) print(" date: %d-%02d-%02d" % (attr['year'], attr['month'], attr['day'])) + if manifest.get('sgx.remote_attestation', '0') == '1': + spid = manifest.get('sgx.ra_client_spid', '') + linkable = manifest.get('sgx.ra_client_linkable', '0') + print("SGX remote attestation:") + if not spid: + print(" DCAP/ECDSA") + else: + print(" EPID (spid = %s, linkable = %s)" % (spid, linkable)) + # Get trusted checksums and measurements print("Trusted files:") for key, val in get_trusted_files(manifest, args).items(): diff --git a/Pal/src/host/Linux-SGX/tools/README.rst b/Pal/src/host/Linux-SGX/tools/README.rst index 4925f33c..8a8b3c02 100644 --- a/Pal/src/host/Linux-SGX/tools/README.rst +++ b/Pal/src/host/Linux-SGX/tools/README.rst @@ -178,12 +178,14 @@ into the RA-TLS certificate. Typically linked into server applications. Not thre The library expects the following information in the manifest for EPID-based attestation: +- ``sgx.remote_attestation = 1`` -- remote attestation is enabled. - ``sgx.ra_client_spid`` -- client SPID for EPID remote attestation. - ``sgx.ra_client_linkable`` -- client linkable/unlinkable attestation policy. For ECDSA-based (DCAP) attestation, the library expects instead: -- ``sgx.attestation = 1`` -- DCAP remote attestation is enabled. +- ``sgx.remote_attestation = 1`` -- remote attestation is enabled. +- ``sgx.ra_client_spid = `` -- it is DCAP attestation, *not* EPID attestation. The library uses the following environment variables if available: