123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176 |
- /*
- * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #ifndef __linux__
- #include "targetver.h"
- #endif
- // Exclude rarely-used stuff from Windows headers
- //#define WIN32_LEAN_AND_MEAN
- // Windows Header Files:
- //#include <windows.h>
- #include "se_types.h"
- #include "sgx_quote.h"
- #include "aeerror.h"
- #include "sgx_tseal.h"
- #include "sgx_lfence.h"
- #include "epid_pve_type.h"
- #include "sgx_utils.h"
- #include "ipp_wrapper.h"
- #include "epid/common/errors.h"
- #include "ae_ipp.h"
- #include "epid/member/api.h"
- #include "quoting_enclave_t.c"
- #include "sgx_tcrypto.h"
- #include "se_sig_rl.h"
- #include "se_ecdsa_verify_internal.h"
- #include "se_quote_internal.h"
- #include "pve_qe_common.h"
- #include "byte_order.h"
- #include "util.h"
- #include "qsdk_pub.hh"
- #include "isk_pub.hh"
- #if !defined(SWAP_4BYTES)
- #define SWAP_4BYTES(u32) \
- ((uint32_t)(((((unsigned char*)&(u32))[0]) << 24) \
- + ((((unsigned char*)&(u32))[1]) << 16) \
- + ((((unsigned char*)&(u32))[2]) << 8) \
- + (((unsigned char*)&(u32))[3])))
- #endif
- // Start from 1, and it's little endian.
- #define QE_QUOTE_VERSION 2
- #define QE_AES_IV_SIZE 12
- #define QE_AES_KEY_SIZE 16
- #define QE_OAEP_SEED_SIZE 32
- /* One field in sgx_quote_t(signature_len) is not part of the quote_body need
- to be signed by EPID. So we need to minus sizeof(uint32_t). */
- #define QE_QUOTE_BODY_SIZE (sizeof(sgx_quote_t) - sizeof(uint32_t))
- /*
- * An internal function used to verify EPID Blob, get EPID Group Cert
- * and get EPID context, at the same time, you can check whether EPID blob has
- * been resealed.
- *
- * @param p_blob[in, out] Pointer to EPID Blob.
- * @param p_is_resealed[out] Whether the EPID Blob has been resealed.
- * @param create_context[in] Flag indicates create EPID context or not.
- * @param plaintext_epid_data[out] Used to get the plaintext part of epid blob
- * @param pp_epid_context[out] Used to get the pointer of the EPID context.
- * @return ae_error_t AE_SUCCESS or other error cases.
- */
- static ae_error_t verify_blob_internal(
- uint8_t *p_blob,
- uint32_t blob_size,
- uint8_t *p_is_resealed,
- uint32_t create_context,
- se_plaintext_epid_data_sdk_t& plaintext_epid_data,
- MemberCtx **pp_epid_context)
- {
- sgx_status_t se_ret = SGX_SUCCESS;
- uint8_t resealed= FALSE;
- se_secret_epid_data_sdk_t secret_epid_data;
- se_plaintext_epid_data_sik_t plaintext_old_format;
- uint32_t plaintext_length;
- int is_old_format = 0;
- uint32_t decryptedtext_length = sizeof(secret_epid_data);
- sgx_sealed_data_t *p_epid_blob = (sgx_sealed_data_t *)p_blob;
- uint8_t local_epid_blob[sizeof(*p_epid_blob)
- + sizeof(secret_epid_data)
- + sizeof(plaintext_epid_data)]
- = {0};
- // We will use plaintext_old_format as buffer to hold the output of sgx_unseal_data.
- // It can be se_plaintext_epid_data_sik_t or se_plaintext_epid_data_sdk_t.
- // We use the static assert to reassure plaintext_old_format is big enough.
- // If someone changed the definition of these 2 structures and break current assumption,
- // it will report error in compile time.
- se_static_assert(sizeof(plaintext_old_format)>=sizeof(plaintext_epid_data));
- if (sgx_get_encrypt_txt_len(p_epid_blob) != sizeof(se_secret_epid_data_sdk_t)&&
- sgx_get_encrypt_txt_len(p_epid_blob) != sizeof(se_secret_epid_data_sik_t)){
- return QE_EPIDBLOB_ERROR;
- }
- plaintext_length = sgx_get_add_mac_txt_len(p_epid_blob);
- if(plaintext_length != sizeof(se_plaintext_epid_data_sik_t)&&
- plaintext_length != sizeof(se_plaintext_epid_data_sdk_t))
- {
- return QE_EPIDBLOB_ERROR;
- }
- memset(&secret_epid_data, 0, sizeof(secret_epid_data));
- memset(&plaintext_epid_data, 0, sizeof(plaintext_epid_data));
- memset(&plaintext_old_format, 0, sizeof(plaintext_old_format));
- se_ret = sgx_unseal_data(p_epid_blob,
- (uint8_t *)&plaintext_old_format, // The unsealed plaintext can be old or new format, the buffer is defined as old format because it is bigger
- &plaintext_length,
- (uint8_t *)&secret_epid_data,
- &decryptedtext_length);
- if(SGX_SUCCESS != se_ret)
- {
- memset_s(&secret_epid_data, sizeof(secret_epid_data), 0,
- sizeof(secret_epid_data));
- return QE_EPIDBLOB_ERROR;
- }
- //QE will support both epid blob with/without member precomputation
- //If the epid blob without member precomputation is used, QE will generate member precomputation and reseal epid blob
- if((plaintext_old_format.seal_blob_type != PVE_SEAL_EPID_KEY_BLOB)
- || (plaintext_old_format.epid_key_version != EPID_KEY_BLOB_VERSION_SDK&&
- plaintext_old_format.epid_key_version != EPID_KEY_BLOB_VERSION_SIK )) //blob_type and key_version are always first two fields of plaintext in both format
- {
- memset_s(&secret_epid_data, sizeof(secret_epid_data), 0,
- sizeof(secret_epid_data));
- return QE_EPIDBLOB_ERROR;
- }
- // Only 2 combinations are legitimate for the tuple epid_key_version|decryptedtext_length|plaintext_length:
- // EPID_KEY_BLOB_VERSION_SIK|sizeof(se_secret_epid_data_sik_t)|sizeof(se_plaintext_epid_data_sik_t)
- // EPID_KEY_BLOB_VERSION_SDK|sizeof(se_secret_epid_data_sdk_t)|sizeof(se_plaintext_epid_data_sdk_t)
- if((plaintext_old_format.epid_key_version == EPID_KEY_BLOB_VERSION_SIK &&
- (decryptedtext_length!=sizeof(se_secret_epid_data_sik_t)||plaintext_length!=sizeof(se_plaintext_epid_data_sik_t)))||
- (plaintext_old_format.epid_key_version == EPID_KEY_BLOB_VERSION_SDK &&
- (decryptedtext_length!=sizeof(se_secret_epid_data_sdk_t)||plaintext_length!=sizeof(se_plaintext_epid_data_sdk_t)))){
- memset_s(&secret_epid_data, sizeof(secret_epid_data), 0,
- sizeof(secret_epid_data));
- return QE_EPIDBLOB_ERROR;
- }
- // If the input epid blob is in sik format, we will upgrade it to sdk version
- if(plaintext_old_format.epid_key_version == EPID_KEY_BLOB_VERSION_SIK){
- plaintext_epid_data.seal_blob_type = PVE_SEAL_EPID_KEY_BLOB;
- plaintext_epid_data.epid_key_version = EPID_KEY_BLOB_VERSION_SDK;
- memcpy(&plaintext_epid_data.equiv_cpu_svn, &plaintext_old_format.equiv_cpu_svn, sizeof(plaintext_old_format.equiv_cpu_svn));
- memcpy(&plaintext_epid_data.equiv_pve_isv_svn, &plaintext_old_format.equiv_pve_isv_svn, sizeof(plaintext_old_format.equiv_pve_isv_svn));
- memcpy(&plaintext_epid_data.epid_group_cert, &plaintext_old_format.epid_group_cert, sizeof(plaintext_old_format.epid_group_cert));
- memcpy(&plaintext_epid_data.qsdk_exp, &plaintext_old_format.qsdk_exp, sizeof(plaintext_old_format.qsdk_exp));
- memcpy(&plaintext_epid_data.qsdk_mod, &plaintext_old_format.qsdk_mod, sizeof(plaintext_old_format.qsdk_mod));
- memcpy(&plaintext_epid_data.epid_sk, &plaintext_old_format.epid_sk, sizeof(plaintext_old_format.epid_sk));
- plaintext_epid_data.xeid = plaintext_old_format.xeid;
- memset(&secret_epid_data.member_precomp_data, 0, sizeof(secret_epid_data.member_precomp_data));
- is_old_format = 1;
- //PrivKey of secret_epid_data are both in offset 0 so that we need not move it
- }
- else{//SDK version format
- memcpy(&plaintext_epid_data, &plaintext_old_format, sizeof(plaintext_epid_data));
- }
- /* Create report to get current cpu_svn and isv_svn. */
- sgx_report_t report;
- memset(&report, 0, sizeof(report));
- se_ret = sgx_create_report(NULL, NULL, &report);
- if(SGX_SUCCESS != se_ret)
- {
- memset_s(&secret_epid_data, sizeof(secret_epid_data), 0,
- sizeof(secret_epid_data));
- return QE_UNEXPECTED_ERROR;
- }
- /* Get the random function pointer. */
- BitSupplier rand_func = epid_random_func;
- /* Create EPID member context if required. PvE is responsible for verifying
- the Cert signature before storing them in the EPID blob. */
- if(create_context)
- {
- EpidStatus epid_ret = kEpidNoErr;
- epid_ret = EpidMemberCreate(
- &(plaintext_epid_data.epid_group_cert),
- (PrivKey*)&(secret_epid_data.epid_private_key),
- is_old_format?NULL:&secret_epid_data.member_precomp_data,
- rand_func,
- NULL,
- pp_epid_context);
- if(kEpidNoErr != epid_ret)
- {
- memset_s(&secret_epid_data, sizeof(secret_epid_data), 0,
- sizeof(secret_epid_data));
- // Make sure the pointer is not pointered to garbage. And according
- // to EPID SDK 2.0 API document of EpidMemberCreate, it will not return
- // error with memory allocated. So set the pointer to NULL will not
- // cause memory leak here.
- *pp_epid_context = NULL;
- return QE_UNEXPECTED_ERROR;
- }
- epid_ret = EpidMemberSetHashAlg(*pp_epid_context, kSha256);
- if(kEpidNoErr != epid_ret)
- {
- EpidMemberDelete(pp_epid_context);
- memset_s(&secret_epid_data, sizeof(secret_epid_data), 0 ,
- sizeof(secret_epid_data));
- *pp_epid_context = NULL;
- return QE_UNEXPECTED_ERROR;
- }
- if(is_old_format)
- {
- epid_ret = EpidMemberWritePrecomp(*pp_epid_context, &secret_epid_data.member_precomp_data);
- if(kEpidNoErr != epid_ret)
- {
- EpidMemberDelete(pp_epid_context);
- memset_s(&secret_epid_data, sizeof(secret_epid_data), 0,
- sizeof(secret_epid_data));
- *pp_epid_context = NULL;
- return QE_UNEXPECTED_ERROR;
- }
- }
- }
- /* Update the Key Blob using the SEAL Key for the current TCB if the TCB is
- upgraded after the Key Blob is generated. Here memcmp cpu_svns might be
- different even though they're actually same, but for defense in depth we
- will keep this comparison here. And we will also upgrade old format EPID
- blob to new format here. */
- if((memcmp(&report.body.cpu_svn, &p_epid_blob->key_request.cpu_svn,
- sizeof(report.body.cpu_svn)))
- || (report.body.isv_svn != p_epid_blob->key_request.isv_svn)
- || plaintext_old_format.epid_key_version == EPID_KEY_BLOB_VERSION_SIK)
- {
- se_ret = sgx_seal_data(sizeof(plaintext_epid_data),
- (uint8_t *)&plaintext_epid_data,
- sizeof(secret_epid_data),
- (uint8_t *)&secret_epid_data,
- SGX_TRUSTED_EPID_BLOB_SIZE_SDK,
- (sgx_sealed_data_t *)local_epid_blob);
- if(SGX_SUCCESS != se_ret)
- {
- // Clear the output buffer to make sure nothing leaks.
- memset_s(&secret_epid_data, sizeof(secret_epid_data), 0,
- sizeof(secret_epid_data));
- // *pp_epid_context contains pointers, so we cannot simply clear it.
- if(pp_epid_context)
- {
- EpidMemberDelete(pp_epid_context);
- *pp_epid_context = NULL;
- }
- return QE_UNEXPECTED_ERROR;
- }
- memcpy(p_epid_blob, local_epid_blob, blob_size);
- resealed = TRUE;
- }
- memset_s(&secret_epid_data, sizeof(secret_epid_data), 0,
- sizeof(secret_epid_data));
- *p_is_resealed = resealed;
- return AE_SUCCESS;
- }
- /*
- * External function used to verify EPID Blob and check whether QE has
- * been updated.
- *
- * @param p_blob[in, out] Pointer to EPID Blob.
- * @param blob_size[in] The size of EPID Blob, in bytes.
- * @param p_is_resealed[out] Whether the EPID Blob is resealed within this function call.
- * @return uint32_t AE_SUCCESS or other error cases.
- */
- uint32_t verify_blob(
- uint8_t *p_blob,
- uint32_t blob_size,
- uint8_t *p_is_resealed)
- {
- se_plaintext_epid_data_sdk_t plain_text;
- /* Actually, some cases here will be checked with code generated by
- edger8r. Here we just want to defend in depth. */
- if(NULL == p_blob || NULL == p_is_resealed)
- return QE_PARAMETER_ERROR;
-
- if(SGX_TRUSTED_EPID_BLOB_SIZE_SDK != blob_size)
- return QE_PARAMETER_ERROR;
- //
- // if we mispredict here and blob_size is too
- // small, we might overflow
- //
- sgx_lfence();
- if(!sgx_is_within_enclave(p_blob, blob_size))
- return QE_PARAMETER_ERROR;
- return verify_blob_internal(p_blob, blob_size,
- p_is_resealed, FALSE, plain_text, NULL);
- }
- /*
- * An internal function used to sign the EPID signature on the quote body.
- * Prefix "emp_" means it is a pointer points memory outside enclave.
- *
- * For quote with SIG-RL
- * |--------------------------------------------------------------------|
- * |sgx_quote_t|wrap_key_t|iv|payload_size|basic_sig|rl_ver|n2|nrp..|mac|
- * |--------------------------------------------------------------------|
- * For quote without SIG-RL
- * |--------------------------------------------------------------|
- * |sgx_quote_t|wrap_key_t|iv|payload_size|basic_sig|rl_ver|n2|mac|
- * |--------------------------------------------------------------|
- *
- * @param p_epid_context[in] Pointer to the EPID context.
- * @param plaintext[in] Reference to the plain text part of EPID blob.
- * @param p_basename[in] The pointer to basename.
- * @param emp_sig_rl_entries[in] The pointer to SIG-RL entries.
- * @param p_sig_rl_header[in] The header of SIG-RL, within EPC.
- * @param p_sig_rl_signature[in] The ecdsa signature of SIG-RL, within EPC.
- * @param p_enclave_report[in] The input isv report.
- * @param p_nonce[in] The input nonce.
- * @param p_qe_report[out] The output buffer for qe_report.
- * @param emp_quote[out] The output buffer for quote.
- * @param p_quote_body[in] The quote body in EPC.
- * @param sign_size[in] size of the signature.
- * @return ae_error_t AE_SUCCESS for success, otherwise for errors.
- */
- static ae_error_t qe_epid_sign(
- MemberCtx *p_epid_context,
- const se_plaintext_epid_data_sdk_t& plaintext,
- const sgx_basename_t *p_basename,
- const SigRlEntry *emp_sig_rl_entries,
- se_sig_rl_t *p_sig_rl_header,
- sgx_ec256_signature_t *p_sig_rl_signature,
- const sgx_report_t *p_enclave_report,
- const sgx_quote_nonce_t *p_nonce,
- sgx_report_t *p_qe_report,
- uint8_t *emp_quote,
- const sgx_quote_t *p_quote_body,
- uint32_t sign_size)
- {
- ae_error_t ret = AE_SUCCESS;
- IppStatus ipp_ret = ippStsNoErr;
- sgx_status_t se_ret = SGX_SUCCESS;
- EpidStatus epid_ret = kEpidNoErr;
- se_wrap_key_t wrap_key;
- BasicSignature basic_sig;
- BasicSignature encrypted_basic_sig;
- uint8_t aes_iv[QUOTE_IV_SIZE] = {0};
- uint8_t aes_key[QE_AES_KEY_SIZE] = {0};
- uint8_t aes_tag[SGX_SEAL_TAG_SIZE] = {0};
- Ipp8u seeds[QE_OAEP_SEED_SIZE] = {0};
- sgx_report_data_t qe_report_data = {{0}};
- sgx_target_info_t report_target;
- sgx_ec256_public_t ec_pub_key;
- se_ae_ecdsa_hash_t sig_rl_hash = {{0}};
- IppECResult ec_result = ippECValid ;
- int aes_context_size = 0;
- sgx_sha_state_handle_t sha_context = NULL;
- sgx_sha_state_handle_t sha_quote_context = NULL;
- IppsAES_GCMState *aes_context = NULL;
- IppsRSAPublicKeyState *pub_key = NULL;
- int pub_key_size = 0;
- uint8_t* pub_key_buffer = NULL;
- IppsECCPState *p_ecp = NULL;
- memset(&wrap_key, 0, sizeof(wrap_key));
- memset(&basic_sig, 0, sizeof(basic_sig));
- memset(&encrypted_basic_sig, 0, sizeof(encrypted_basic_sig));
- memset(&report_target, 0, sizeof(report_target));
- memset(&ec_pub_key, 0, sizeof(ec_pub_key));
- se_encrypted_sign_t *emp_p = (se_encrypted_sign_t *)
- (((sgx_quote_t *)emp_quote)->signature);
- uint8_t* emp_nr = NULL;
- uint32_t match = FALSE;
- /* Sign the quote body and get the basic signature*/
- epid_ret = EpidSignBasic(p_epid_context,
- (uint8_t *)const_cast<sgx_quote_t *>(p_quote_body),
- (uint32_t)QE_QUOTE_BODY_SIZE,
- (uint8_t *)const_cast<sgx_basename_t *>(p_basename),
- sizeof(*p_basename),
- &basic_sig);
- if(kEpidNoErr != epid_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- /* Prepare the context for SHA256 of quote. */
- if(p_qe_report)
- {
- se_ret = sgx_sha256_init(&sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- // Update hash for nonce.
- se_ret = sgx_sha256_update((uint8_t *)const_cast<sgx_quote_nonce_t *>(p_nonce),
- sizeof(*p_nonce),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- // Update hash for the first part of quote.
- se_ret = sgx_sha256_update((uint8_t *)const_cast<sgx_quote_t *>(p_quote_body),
- sizeof(*p_quote_body),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- }
- /* Prepare the context for SHA256 and start calculate the hash of header
- * of SIG-RL. */
- if(emp_sig_rl_entries)
- {
- se_ret = sgx_sha256_init(&sha_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- /* Calculate the hash of SIG-RL header. */
- se_ret = sgx_sha256_update((Ipp8u *)p_sig_rl_header,
- (uint32_t)(sizeof(se_sig_rl_t) - sizeof(SigRlEntry)),
- sha_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- }
- // Start encrypt the signature.
- ipp_ret = ippsAES_GCMGetSize(&aes_context_size);
- if(ipp_ret != ippStsNoErr){
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- aes_context = (IppsAES_GCMState *)malloc(aes_context_size);
- if(NULL == aes_context)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- /* Get the random wrap key */
- se_ret = sgx_read_rand(aes_key, sizeof(aes_key));
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- /* Copy the hash of wrap key into output buffer. */
- se_static_assert(sizeof(wrap_key.key_hash) == sizeof(sgx_sha256_hash_t));
- se_ret = sgx_sha256_msg(aes_key, sizeof(aes_key),
- (sgx_sha256_hash_t *)wrap_key.key_hash);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- //Start encrypt the wrap key by RSA IPP algorithm.
- ipp_ret = create_rsa_pub_key(sizeof(g_qsdk_pub_key_n),
- sizeof(g_qsdk_pub_key_e),
- g_qsdk_pub_key_n,
- g_qsdk_pub_key_e,
- &pub_key);
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- se_ret = sgx_read_rand(seeds, sizeof(seeds));
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- ipp_ret = ippsRSA_GetBufferSizePublicKey(&pub_key_size, pub_key);
- if (ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- pub_key_buffer = (uint8_t*)malloc(pub_key_size);
- if (pub_key_buffer == NULL)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- ipp_ret = ippsRSAEncrypt_OAEP(aes_key, sizeof(aes_key),
- NULL, 0, seeds,
- wrap_key.encrypted_key,
- pub_key, IPP_ALG_HASH_SHA256,
- pub_key_buffer);
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- ipp_ret = ippsAES_GCMInit(aes_key,
- sizeof(aes_key),
- aes_context,
- aes_context_size);
- memset_s(aes_key, sizeof(aes_key), 0, sizeof(aes_key));
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- /* Create the random AES IV. */
- se_ret = sgx_read_rand(aes_iv, sizeof(aes_iv));
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- /* Copy the wrap_key_t into output buffer. */
- memcpy(&emp_p->wrap_key, &wrap_key, sizeof(wrap_key));
- /* Copy the AES IV into output buffer. */
- memcpy(&emp_p->iv, aes_iv, sizeof(aes_iv));
- /* Copy the AES Blob payload size into output buffer. */
- memcpy(&emp_p->payload_size, &sign_size, sizeof(sign_size));
- ipp_ret = ippsAES_GCMStart(aes_iv, sizeof(aes_iv), NULL, 0,
- aes_context);
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- /* Encrypt the basic signature. */
- ipp_ret = ippsAES_GCMEncrypt((Ipp8u *)&basic_sig,
- (uint8_t *)&encrypted_basic_sig,
- sizeof(encrypted_basic_sig),
- aes_context);
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- /* Copy the encrypted basic signature into output buffer. */
- memcpy(&emp_p->basic_sign, &encrypted_basic_sig,
- sizeof(encrypted_basic_sig));
- if(p_qe_report)
- {
- se_ret = sgx_sha256_update((uint8_t *)&wrap_key,
- sizeof(wrap_key),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- se_ret = sgx_sha256_update(aes_iv,
- sizeof(aes_iv),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- se_ret = sgx_sha256_update((uint8_t *)&sign_size,
- sizeof(sign_size),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- se_ret = sgx_sha256_update((uint8_t *)&encrypted_basic_sig,
- sizeof(encrypted_basic_sig),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- }
- /* Start process the SIG-RL. */
- if(emp_sig_rl_entries)
- {
- unsigned int entry_count = 0;
- unsigned int i = 0;
- RLver_t encrypted_rl_ver = {{0}};
- RLCount encrypted_n2 = {{0}};
- entry_count = lv_ntohl(p_sig_rl_header->sig_rl.n2);//entry count for big endian to little endian
- // Continue encrypt the output
- ipp_ret = ippsAES_GCMEncrypt((Ipp8u *)&(p_sig_rl_header->sig_rl.version),
- (Ipp8u *)&encrypted_rl_ver,
- sizeof(encrypted_rl_ver),
- aes_context);
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- ipp_ret = ippsAES_GCMEncrypt((Ipp8u *)&(p_sig_rl_header->sig_rl.n2),
- (Ipp8u *)&encrypted_n2,
- sizeof(encrypted_n2),
- aes_context);
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- memcpy(&(emp_p->rl_ver), &encrypted_rl_ver,
- sizeof(encrypted_rl_ver));
- memcpy(&(emp_p->rl_num), &encrypted_n2,
- sizeof(encrypted_n2));
- if(p_qe_report)
- {
- se_ret = sgx_sha256_update((uint8_t *)&encrypted_rl_ver,
- sizeof(encrypted_rl_ver),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- se_ret = sgx_sha256_update((uint8_t *)&encrypted_n2,
- sizeof(encrypted_n2),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- }
- /* Start process the SIG-RL entries one by one. */
- emp_nr = emp_p->nrp_mac;
- for (i = 0; i < entry_count; i++, emp_nr += sizeof(NrProof))
- {
- /* Generate non-revoke prove one by one. */
- SigRlEntry entry;
- NrProof temp_nr;
- NrProof encrypted_temp_nr;
- memcpy(&entry, emp_sig_rl_entries + i, sizeof(entry));
- memset_s(&temp_nr, sizeof(temp_nr), 0, sizeof(temp_nr));
- memset_s(&encrypted_temp_nr, sizeof(encrypted_temp_nr), 0, sizeof(encrypted_temp_nr));
- epid_ret = EpidNrProve(p_epid_context,
- (uint8_t *)const_cast<sgx_quote_t *>(p_quote_body),
- (uint32_t)QE_QUOTE_BODY_SIZE,
- &basic_sig, // Basic signature with 'b' and 'k' in it
- &entry, //Single entry in SigRl composed of 'b' and 'k'
- &temp_nr); // The generated non-revoked proof
- if(kEpidNoErr != epid_ret)
- {
- if(kEpidSigRevokedInSigRl == epid_ret)
- match = TRUE;
- else
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- }
- /* Update the hash of SIG-RL */
- se_ret = sgx_sha256_update((Ipp8u *)&entry,
- sizeof(entry), sha_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- ipp_ret = ippsAES_GCMEncrypt((Ipp8u *)&temp_nr,
- (Ipp8u *)&encrypted_temp_nr,
- sizeof(NrProof),
- aes_context);
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- memcpy(emp_nr, &encrypted_temp_nr, sizeof(encrypted_temp_nr));
- if(p_qe_report)
- {
- se_ret = sgx_sha256_update((uint8_t *)&encrypted_temp_nr,
- sizeof(encrypted_temp_nr),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- }
- }
- /* Get the final hash of the whole SIG-RL. */
- se_ret = sgx_sha256_get_hash(sha_context,
- (sgx_sha256_hash_t *)&sig_rl_hash.hash);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- /* Verify the integraty of SIG-RL by check ECDSA signature. */
- ipp_ret = new_std_256_ecp(&p_ecp);
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- se_static_assert(sizeof(ec_pub_key) == sizeof(plaintext.epid_sk));
- // Both plaintext.epid_sk and ec_pub_key are little endian
- memcpy(&ec_pub_key, plaintext.epid_sk, sizeof(ec_pub_key));
- // se_ecdsa_verify_internal will take ec_pub_key as little endian
- se_ret = se_ecdsa_verify_internal(p_ecp,
- &ec_pub_key,
- p_sig_rl_signature,
- &sig_rl_hash,
- &ec_result);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- else if(ippECValid != ec_result)
- {
- ret = QE_SIGRL_ERROR;
- goto CLEANUP;
- }
- else if(match)
- {
- ret = QE_REVOKED_ERROR;
- goto CLEANUP;
- }
- }
- else
- {
- se_static_assert(sizeof(emp_p->rl_ver) == sizeof(RLver_t));
- se_static_assert(sizeof(emp_p->rl_num) == sizeof(RLCount));
- uint8_t temp_buf[sizeof(RLver_t) + sizeof(RLCount)] = {0};
- uint8_t encrypted_temp_buf[sizeof(temp_buf)] = {0};
- ipp_ret = ippsAES_GCMEncrypt(temp_buf,
- (Ipp8u *)&encrypted_temp_buf,
- sizeof(encrypted_temp_buf),
- aes_context);
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- /* This will copy both encrypted rl_ver and encrypted rl_num into
- Output buffer. */
- memcpy(&emp_p->rl_ver, &encrypted_temp_buf,
- sizeof(encrypted_temp_buf));
- if(p_qe_report)
- {
- se_ret = sgx_sha256_update((uint8_t *)&encrypted_temp_buf,
- sizeof(encrypted_temp_buf),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- }
- }
- ipp_ret = ippsAES_GCMGetTag(aes_tag, sizeof(aes_tag), aes_context);
- if(ipp_ret != ippStsNoErr)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- memcpy((uint8_t *)&(emp_p->basic_sign) + sign_size, &aes_tag,
- sizeof(aes_tag));
- if(p_qe_report)
- {
- se_ret = sgx_sha256_update(aes_tag, sizeof(aes_tag),
- sha_quote_context);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- se_ret = sgx_sha256_get_hash(sha_quote_context,
- (sgx_sha256_hash_t *)&qe_report_data);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- memcpy(&(report_target.attributes),
- &(((const sgx_report_t *)p_enclave_report)->body.attributes),
- sizeof(report_target.attributes));
- memcpy(&(report_target.mr_enclave),
- &(((const sgx_report_t *)p_enclave_report)->body.mr_enclave),
- sizeof(report_target.mr_enclave));
- memcpy(&(report_target.misc_select),
- &(((const sgx_report_t *)p_enclave_report)->body.misc_select),
- sizeof(report_target.misc_select));
- se_ret = sgx_create_report(&report_target, &qe_report_data, p_qe_report);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_PARAMETER_ERROR;
- goto CLEANUP;
- }
- }
- CLEANUP:
- memset_s(aes_key, sizeof(aes_key), 0, sizeof(aes_key));
- sgx_sha256_close(sha_context);
- sgx_sha256_close(sha_quote_context);
- if(aes_context)
- free(aes_context);
- if(pub_key)
- secure_free_rsa_pub_key(sizeof(g_qsdk_pub_key_n), sizeof(g_qsdk_pub_key_e), pub_key);
- if(pub_key_buffer)
- free(pub_key_buffer);
- secure_free_std_256_ecp(p_ecp);
- return ret;
- }
- /*
- * External function used to get quote. Prefix "emp_" means it is a pointer
- * points memory outside enclave.
- *
- * @param p_blob[in, out] Pointer to the EPID Blob.
- * @param blob_size[in] The size of EPID Blob, in bytes.
- * @param p_enclave_report[in] The application enclave's report.
- * @param quote_type[in] The type of quote, random based or name based.
- * @param p_spid[in] Pointer to SPID.
- * @param p_nonce[in] Pointer to nonce.
- * @param emp_sig_rl[in] Pointer to SIG-RL.
- * @param sig_rl_size[in] The size of SIG-RL, in bytes.
- * @param p_qe_report[out] Pointer to QE report, which reportdata is
- * sha256(nonce || quote)
- * @param emp_quote[out] Pointer to the output buffer for quote.
- * @param quote_size[in] The size of emp_quote, in bytes.
- * @param pce_isvsvn[in] The ISVSVN of PCE.
- * @return ae_error_t AE_SUCCESS for success, otherwise for errors.
- */
- uint32_t get_quote(
- uint8_t *p_blob,
- uint32_t blob_size,
- const sgx_report_t *p_enclave_report,
- sgx_quote_sign_type_t quote_type,
- const sgx_spid_t *p_spid,
- const sgx_quote_nonce_t *p_nonce,
- const uint8_t *emp_sig_rl,
- uint32_t sig_rl_size,
- sgx_report_t *p_qe_report,
- uint8_t *emp_quote,
- uint32_t quote_size,
- sgx_isv_svn_t pce_isvsvn)
- {
- ae_error_t ret = AE_SUCCESS;
- EpidStatus epid_ret = kEpidNoErr;
- MemberCtx *p_epid_context = NULL;
- sgx_quote_t quote_body;
- uint8_t is_resealed = 0;
- sgx_basename_t basename = {{0}};
- uint64_t sign_size = 0;
- sgx_status_t se_ret = SGX_SUCCESS;
- sgx_report_t qe_report;
- uint64_t required_buffer_size = 0;
- se_sig_rl_t sig_rl_header;
- se_plaintext_epid_data_sdk_t plaintext;
- sgx_ec256_signature_t ec_signature;
- memset("e_body, 0, sizeof(quote_body));
- memset(&sig_rl_header, 0, sizeof(sig_rl_header));
- memset(&plaintext, 0, sizeof(plaintext));
- memset(&ec_signature, 0, sizeof(ec_signature));
- /* Actually, some cases here will be checked with code generated by
- edger8r. Here we just want to defend in depth. */
- if((NULL == p_blob)
- || (NULL == p_enclave_report)
- || (NULL == p_spid)
- || (NULL == emp_quote)
- || (!quote_size)
- || ((NULL != emp_sig_rl) && (sig_rl_size < sizeof(se_sig_rl_t)
- + 2 * SE_ECDSA_SIGN_SIZE))
- //
- // this size check could mispredict and cause us to
- // overflow, but we have an lfence below
- // that's safe to use for this case
- //
- || ((NULL == emp_sig_rl) && (sig_rl_size != 0)))
- return QE_PARAMETER_ERROR;
- if(SGX_TRUSTED_EPID_BLOB_SIZE_SDK != blob_size)
- return QE_PARAMETER_ERROR;
- //
- // this could mispredict and cause us to
- // overflow, but we have an lfence below
- // that's safe to use for this case
- //
- if(SGX_LINKABLE_SIGNATURE != quote_type
- && SGX_UNLINKABLE_SIGNATURE != quote_type)
- return QE_PARAMETER_ERROR;
- if(!p_nonce && p_qe_report)
- return QE_PARAMETER_ERROR;
- if(p_nonce && !p_qe_report)
- return QE_PARAMETER_ERROR;
- /* To reduce the memory footprint of QE, we should leave sig_rl and
- quote buffer outside enclave. */
- if(!sgx_is_outside_enclave(emp_sig_rl, sig_rl_size))
- return QE_PARAMETER_ERROR;
- //
- // for user_check SigRL input
- // based on quote_size input parameter
- //
- sgx_lfence();
- if(!sgx_is_outside_enclave(emp_quote, quote_size))
- return QE_PARAMETER_ERROR;
- /* Check whether p_blob is copied into EPC. If we want to reduce the
- memory usage, maybe we can leave the p_blob outside EPC. */
- if(!sgx_is_within_enclave(p_blob, blob_size))
- return QE_PARAMETER_ERROR;
- if(!sgx_is_within_enclave(p_enclave_report, sizeof(*p_enclave_report)))
- return QE_PARAMETER_ERROR;
- if(!sgx_is_within_enclave(p_spid, sizeof(*p_spid)))
- return QE_PARAMETER_ERROR;
- /* If the code reach here, if p_nonce is NULL, then p_qe_report will be
- NULL also. So we only check p_nonce here.*/
- if(p_nonce)
- {
- /* Actually Edger8r will alloc the buffer within EPC, this is just kind
- of defense in depth. */
- if(!sgx_is_within_enclave(p_nonce, sizeof(*p_nonce)))
- return QE_PARAMETER_ERROR;
- if(!sgx_is_within_enclave(p_qe_report, sizeof(*p_qe_report)))
- return QE_PARAMETER_ERROR;
- }
- /* Verify the input report. */
- if(SGX_SUCCESS != sgx_verify_report(p_enclave_report))
- return QE_PARAMETER_ERROR;
- /* Verify EPID p_blob and create the context */
- ret = verify_blob_internal(p_blob,
- blob_size,
- &is_resealed,
- TRUE,
- plaintext,
- &p_epid_context);
- if(AE_SUCCESS != ret)
- goto CLEANUP;
- /* If SIG-RL is provided, we should check its size. */
- if(emp_sig_rl)
- {
- uint64_t temp_size = 0;
- uint64_t n2 = 0;
- memcpy(&sig_rl_header, emp_sig_rl, sizeof(sig_rl_header));
- if(sig_rl_header.protocol_version != SE_EPID_SIG_RL_VERSION)
- {
- ret = QE_PARAMETER_ERROR;
- goto CLEANUP;
- }
- if(sig_rl_header.epid_identifier != SE_EPID_SIG_RL_ID)
- {
- ret = QE_PARAMETER_ERROR;
- goto CLEANUP;
- }
- if(memcmp(&sig_rl_header.sig_rl.gid, &plaintext.epid_group_cert.gid,
- sizeof(sig_rl_header.sig_rl.gid)))
- {
- ret = QE_PARAMETER_ERROR;
- goto CLEANUP;
- }
- temp_size = se_get_sig_rl_size(&sig_rl_header);
- if(temp_size != sig_rl_size)
- {
- ret = QE_PARAMETER_ERROR;
- goto CLEANUP;
- }
- se_static_assert(sizeof(ec_signature.x) == SE_ECDSA_SIGN_SIZE);
- se_static_assert(sizeof(ec_signature.y) == SE_ECDSA_SIGN_SIZE);
- memcpy(ec_signature.x,
- emp_sig_rl + sig_rl_size - (SE_ECDSA_SIGN_SIZE * 2),
- sizeof(ec_signature.x));
- SWAP_ENDIAN_32B(ec_signature.x);
- memcpy(ec_signature.y,
- emp_sig_rl + sig_rl_size - (SE_ECDSA_SIGN_SIZE * 1),
- sizeof(ec_signature.y));
- SWAP_ENDIAN_32B(ec_signature.y);
- n2 = SWAP_4BYTES(sig_rl_header.sig_rl.n2);
- temp_size = sizeof(EpidSignature) - sizeof(NrProof)
- + n2 * sizeof(NrProof);
- if(temp_size > UINT32_MAX)
- {
- ret = QE_PARAMETER_ERROR;
- goto CLEANUP;
- }
- sign_size = temp_size;
- }
- else
- {
- sign_size = sizeof(BasicSignature)
- + sizeof(uint32_t) // rl_ver
- + sizeof(uint32_t); // rl_num
- }
- /* Verify sizeof basename is large enough and it should always be true*/
- se_static_assert(sizeof(basename) > sizeof(*p_spid));
- /* Because basename has already been zeroed,
- so we don't need to concatenating with 0s.*/
- memcpy(&basename, p_spid, sizeof(*p_spid));
- if(SGX_UNLINKABLE_SIGNATURE == quote_type)
- {
- uint8_t *p = (uint8_t *)&basename + sizeof(*p_spid);
- se_ret = sgx_read_rand(p, sizeof(basename) - sizeof(*p_spid));
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- }
- epid_ret = EpidRegisterBaseName(p_epid_context, (uint8_t *)&basename,
- sizeof(basename));
- if(kEpidNoErr != epid_ret)
- {
- ret = QE_UNEXPECTED_ERROR;
- goto CLEANUP;
- }
- required_buffer_size = SE_QUOTE_LENGTH_WITHOUT_SIG + sign_size;
- /* We should make sure the buffer size is big enough. */
- if(quote_size < required_buffer_size)
- {
- ret = QE_PARAMETER_ERROR;
- goto CLEANUP;
- }
- //
- // for user_check SigRL input
- // based on n2 field in SigRL
- //
- sgx_lfence();
- /* Copy the data in the report into quote body. */
- memset(emp_quote, 0, quote_size);
- quote_body.version = QE_QUOTE_VERSION;
- quote_body.sign_type = (uint16_t)quote_type;
- quote_body.pce_svn = pce_isvsvn; // Both are little endian
- quote_body.xeid = plaintext.xeid; // Both are little endian
- se_static_assert(sizeof(plaintext.epid_group_cert.gid) == sizeof(uint32_t));
- se_static_assert(sizeof(quote_body.epid_group_id) == sizeof(uint32_t));
- ((uint8_t *)("e_body.epid_group_id))[0] = plaintext.epid_group_cert.gid.data[3];
- ((uint8_t *)("e_body.epid_group_id))[1] = plaintext.epid_group_cert.gid.data[2];
- ((uint8_t *)("e_body.epid_group_id))[2] = plaintext.epid_group_cert.gid.data[1];
- ((uint8_t *)("e_body.epid_group_id))[3] = plaintext.epid_group_cert.gid.data[0];
- memcpy("e_body.basename, &basename, sizeof(quote_body.basename));
- // Get the QE's report.
- se_ret = sgx_create_report(NULL, NULL, &qe_report);
- if(SGX_SUCCESS != se_ret)
- {
- ret = QE_PARAMETER_ERROR;
- goto CLEANUP;
- }
- // Copy QE's security version in to Quote body.
- quote_body.qe_svn = qe_report.body.isv_svn;
- // Copy the incoming report into Quote body.
- memcpy("e_body.report_body, &(p_enclave_report->body),
- sizeof(quote_body.report_body));
- /* Because required_buffer_size is larger than signature_len, so if we
- get here, then no integer overflow will ocur. */
- quote_body.signature_len = (uint32_t)(sizeof(se_wrap_key_t)
- + QUOTE_IV_SIZE
- + sizeof(uint32_t)
- + sign_size
- + sizeof(sgx_mac_t));
- /* Make the signature. */
- ret = qe_epid_sign(p_epid_context,
- plaintext,
- &basename,
- emp_sig_rl ? ((const se_sig_rl_t *)emp_sig_rl)->sig_rl.bk
- : NULL,
- &sig_rl_header,
- &ec_signature,
- p_enclave_report,
- p_nonce,
- p_qe_report,
- emp_quote,
- "e_body,
- (uint32_t)sign_size);
- if(AE_SUCCESS != ret)
- {
- // Only need to clean the buffer after the fixed length part.
- memset_s(emp_quote + sizeof(sgx_quote_t), quote_size - sizeof(sgx_quote_t),
- 0, quote_size - sizeof(sgx_quote_t));
- goto CLEANUP;
- }
- memcpy(emp_quote, "e_body, sizeof(sgx_quote_t));
- CLEANUP:
- if(p_epid_context)
- EpidMemberDelete(&p_epid_context);
- return ret;
- }
|