[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.
This commit is contained in:
Dmitrii Kuvaiskii
2020-10-26 05:32:50 -07:00
parent 892bf70d58
commit eb0e726625
18 changed files with 240 additions and 196 deletions
+7 -4
View File
@@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3 -3
View File
@@ -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)
+3 -3
View File
@@ -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)
+2 -7
View File
@@ -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
'''
}
+2 -7
View File
@@ -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
'''
}
+1 -1
View File
@@ -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
-5
View File
@@ -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
+30 -26
View File
@@ -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;
+8 -1
View File
@@ -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);
+4 -3
View File
@@ -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.
+1
View File
@@ -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;
+4 -3
View File
@@ -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.
+2 -2
View File
@@ -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] = {
+6 -4
View File
@@ -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.
+4 -1
View File
@@ -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;
}
+151 -125
View File
@@ -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;
@@ -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():
+3 -1
View File
@@ -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 = <empty string>`` -- it is DCAP attestation, *not* EPID attestation.
The library uses the following environment variables if available: