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: