//Function to verify that ECDSA signature of XEGB is correct sgx_status_t verify_xegb(const extended_epid_group_blob_t& xegb, uint8_t *result){ if (lv_htons(xegb.data_length) != EXTENDED_EPID_GROUP_BLOB_DATA_LEN || xegb.format_id != XEGB_FORMAT_ID){ return SGX_ERROR_INVALID_PARAMETER; } sgx_status_t status = SGX_SUCCESS; sgx_ecc_state_handle_t handle= 0; sgx_ec256_signature_t ec_signature; status = sgx_ecc256_open_context(&handle); if(SGX_SUCCESS!=status){ return status; } se_static_assert(sizeof(ec_signature)==sizeof(xegb.signature)); memcpy(&ec_signature, xegb.signature, sizeof(xegb.signature)); SWAP_ENDIAN_32B(ec_signature.x); SWAP_ENDIAN_32B(ec_signature.y); status = sgx_ecdsa_verify(reinterpret_cast<const uint8_t *>(&xegb), static_cast<uint32_t>(sizeof(xegb)-sizeof(xegb.signature)), const_cast<sgx_ec256_public_t *>(&g_sdsk_pub_key_little_endian), &ec_signature, result, handle); (void)sgx_ecc256_close_context(handle); if(SGX_SUCCESS!=status){ return status; } return SGX_SUCCESS; }
extern "C" sgx_status_t sgx_ra_get_ga( sgx_ra_context_t context, sgx_ec256_public_t *g_a) { sgx_status_t se_ret; if(vector_size(&g_ra_db) <= context||!g_a) return SGX_ERROR_INVALID_PARAMETER; ra_db_item_t* item = NULL; if(0 != vector_get(&g_ra_db, context, reinterpret_cast<void**>(&item)) || item == NULL ) return SGX_ERROR_INVALID_PARAMETER; sgx_ecc_state_handle_t ecc_state = NULL; sgx_ec256_public_t pub_key; sgx_ec256_private_t priv_key; memset(&pub_key, 0, sizeof(pub_key)); memset(&priv_key, 0, sizeof(priv_key)); sgx_spin_lock(&item->item_lock); do { //sgx_ra_init must have been called if (item->state != ra_inited) { se_ret = SGX_ERROR_INVALID_STATE; break; } // ecc_state should be closed when exit. se_ret = sgx_ecc256_open_context(&ecc_state); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } se_ret = sgx_ecc256_create_key_pair(&priv_key, &pub_key, ecc_state); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } memcpy(&item->a, &priv_key, sizeof(item->a)); memcpy(&item->g_a, &pub_key, sizeof(item->g_a)); memcpy(g_a, &pub_key, sizeof(sgx_ec256_public_t)); item->state = ra_get_gaed; //clear local private key to defense in depth memset_s(&priv_key,sizeof(priv_key),0,sizeof(sgx_ec256_private_t)); }while(0); sgx_spin_unlock(&item->item_lock); if(ecc_state!=NULL) sgx_ecc256_close_context(ecc_state); return se_ret; }
ae_error_t pib_verify_signature(platform_info_blob_wrapper_t& piBlobWrapper) { ae_error_t ae_err = AE_FAILURE; sgx_ecc_state_handle_t ecc_handle = NULL; uint8_t result = SGX_EC_INVALID_SIGNATURE; const uint32_t data_size = static_cast<uint32_t>(sizeof(piBlobWrapper.platform_info_blob) - sizeof(piBlobWrapper.platform_info_blob.signature)); piBlobWrapper.valid_info_blob = false; do { sgx_ec256_public_t publicKey; sgx_ec256_signature_t signature; sgx_status_t sgx_status; //BREAK_IF_TRUE((sizeof(publicKey) != sizeof(s_pib_pub_key_big_endian)), ae_err, AE_FAILURE); //BREAK_IF_TRUE((sizeof(signature) != sizeof(piBlobWrapper.platform_info_blob.signature)), ae_err, AE_FAILURE); if(0!=memcpy_s(&publicKey, sizeof(publicKey), s_pib_pub_key_big_endian, sizeof(s_pib_pub_key_big_endian))){ ae_err = AE_FAILURE; break; } if(0!=memcpy_s(&signature, sizeof(signature), &piBlobWrapper.platform_info_blob.signature, sizeof(piBlobWrapper.platform_info_blob.signature))){ ae_err = AE_FAILURE; break; } sgx_status = sgx_ecc256_open_context(&ecc_handle); BREAK_IF_TRUE((SGX_SUCCESS != sgx_status), ae_err, AE_FAILURE); sgx_status = sgx_ecdsa_verify((uint8_t*)&piBlobWrapper.platform_info_blob, data_size, &publicKey, &signature, &result, ecc_handle); BREAK_IF_TRUE((SGX_SUCCESS != sgx_status), ae_err, AE_FAILURE); if (SGX_EC_VALID != result) { AESM_LOG_WARN(g_event_string_table[SGX_EVENT_PID_SIGNATURE_FAILURE]); break; } piBlobWrapper.valid_info_blob = true; ae_err = AE_SUCCESS; } while (0); if (ecc_handle != NULL) { sgx_ecc256_close_context(ecc_handle); } return ae_err; }
//Function to verify the ECDSA signature of a PEK //SHA1 value for integrity checking is not verified since the ECDSA verification could make sure the integrity at the same time. sgx_status_t check_pek_signature(const signed_pek_t& signed_pek, const sgx_ec256_public_t* pek_sk, uint8_t *result) { sgx_status_t status = SGX_SUCCESS; sgx_ecc_state_handle_t handle= 0; sgx_ec256_signature_t ec_signature; status = sgx_ecc256_open_context(&handle); if(SGX_SUCCESS!=status){ return status; } se_static_assert(sizeof(ec_signature)==sizeof(signed_pek.pek_signature)); memcpy(&ec_signature, signed_pek.pek_signature, sizeof(signed_pek.pek_signature)); SWAP_ENDIAN_32B(ec_signature.x); SWAP_ENDIAN_32B(ec_signature.y); status = sgx_ecdsa_verify(reinterpret_cast<const uint8_t *>(&signed_pek), static_cast<uint32_t>(sizeof(signed_pek.n)+sizeof(signed_pek.e)), pek_sk, &ec_signature, result, handle); (void)sgx_ecc256_close_context(handle); return status; }
// TKE interface for isv enclaves sgx_status_t sgx_ra_init_ex( const sgx_ec256_public_t *p_pub_key, int b_pse, sgx_ra_derive_secret_keys_t derive_key_cb, sgx_ra_context_t *p_context) { int valid = 0; sgx_status_t ret = SGX_SUCCESS; sgx_ecc_state_handle_t ecc_state = NULL; // initialize g_kdf_cookie for the first time sgx_ra_init_ex is called. if (unlikely(g_kdf_cookie == 0)) { uintptr_t rand = 0; do { if (SGX_SUCCESS != sgx_read_rand((unsigned char *)&rand, sizeof(rand))) { return SGX_ERROR_UNEXPECTED; } } while (rand == 0); sgx_spin_lock(&g_ra_db_lock); if (g_kdf_cookie == 0) { g_kdf_cookie = rand; memset_s(&rand, sizeof(rand), 0, sizeof(rand)); } sgx_spin_unlock(&g_ra_db_lock); } if(!p_pub_key || !p_context) return SGX_ERROR_INVALID_PARAMETER; if(!sgx_is_within_enclave(p_pub_key, sizeof(sgx_ec256_public_t))) return SGX_ERROR_INVALID_PARAMETER; //derive_key_cb can be NULL if (NULL != derive_key_cb && !sgx_is_within_enclave((const void*)derive_key_cb, 0)) { return SGX_ERROR_INVALID_PARAMETER; } ret = sgx_ecc256_open_context(&ecc_state); if(SGX_SUCCESS != ret) { if(SGX_ERROR_OUT_OF_MEMORY != ret) ret = SGX_ERROR_UNEXPECTED; return ret; } ret = sgx_ecc256_check_point((const sgx_ec256_public_t *)p_pub_key, ecc_state, &valid); if(SGX_SUCCESS != ret) { if(SGX_ERROR_OUT_OF_MEMORY != ret) ret = SGX_ERROR_UNEXPECTED; sgx_ecc256_close_context(ecc_state); return ret; } if(!valid) { sgx_ecc256_close_context(ecc_state); return SGX_ERROR_INVALID_PARAMETER; } sgx_ecc256_close_context(ecc_state); //add new item to g_ra_db ra_db_item_t* new_item = (ra_db_item_t*)malloc(sizeof(ra_db_item_t)); if (!new_item) { return SGX_ERROR_OUT_OF_MEMORY; } memset(new_item,0, sizeof(ra_db_item_t)); memcpy(&new_item->sp_pubkey, p_pub_key, sizeof(new_item->sp_pubkey)); if(b_pse) { //sgx_create_pse_session() must have been called ret = sgx_get_ps_sec_prop(&new_item->ps_sec_prop); if (ret!=SGX_SUCCESS) { SAFE_FREE(new_item); return ret; } } new_item->derive_key_cb = ENC_KDF_POINTER(derive_key_cb); new_item->state = ra_inited; //find first empty slot in g_ra_db int first_empty = -1; ra_db_item_t* item = NULL; sgx_spin_lock(&g_ra_db_lock); uint32_t size = vector_size(&g_ra_db); for (uint32_t i = 0; i < size; i++) { if(0 != vector_get(&g_ra_db, i, reinterpret_cast<void**>(&item))) { sgx_spin_unlock(&g_ra_db_lock); SAFE_FREE(new_item); return SGX_ERROR_UNEXPECTED; } if(item == NULL) { first_empty = i; break; } } //if there is a empty slot, use it if (first_empty >= 0) { errno_t vret = vector_set(&g_ra_db, first_empty, new_item); UNUSED(vret); assert(vret == 0); *p_context = first_empty; } //if there are no empty slots, add a new item to g_ra_db else { if(size >= INT32_MAX) { //overflow sgx_spin_unlock(&g_ra_db_lock); SAFE_FREE(new_item); return SGX_ERROR_OUT_OF_MEMORY; } if(0 != vector_push_back(&g_ra_db, new_item)) { sgx_spin_unlock(&g_ra_db_lock); SAFE_FREE(new_item); return SGX_ERROR_OUT_OF_MEMORY; } *p_context = size; } sgx_spin_unlock(&g_ra_db_lock); return SGX_SUCCESS; }
extern "C" sgx_status_t sgx_ra_proc_msg2_trusted( sgx_ra_context_t context, const sgx_ra_msg2_t *p_msg2, //(g_b||spid||quote_type|| KDF_ID ||sign_gb_ga||cmac||sig_rl_size||sig_rl) const sgx_target_info_t *p_qe_target, sgx_report_t *p_report, sgx_quote_nonce_t* p_nonce) { sgx_status_t se_ret = SGX_ERROR_UNEXPECTED; //p_msg2[in] p_qe_target[in] p_report[out] p_nonce[out] in EDL file if(vector_size(&g_ra_db) <= context || !p_msg2 || !p_qe_target || !p_report || !p_nonce) return SGX_ERROR_INVALID_PARAMETER; ra_db_item_t* item = NULL; if(0 != vector_get(&g_ra_db, context, reinterpret_cast<void**>(&item)) || item == NULL ) return SGX_ERROR_INVALID_PARAMETER; sgx_ec256_private_t a; memset(&a, 0, sizeof(a)); // Create gb_ga sgx_ec256_public_t gb_ga[2]; sgx_ec256_public_t sp_pubkey; sgx_ec_key_128bit_t smkey = {0}; sgx_ec_key_128bit_t skey = {0}; sgx_ec_key_128bit_t mkey = {0}; sgx_ec_key_128bit_t vkey = {0}; sgx_ra_derive_secret_keys_t ra_key_cb = NULL; memset(&gb_ga[0], 0, sizeof(gb_ga)); sgx_spin_lock(&item->item_lock); //sgx_ra_get_ga must have been called if (item->state != ra_get_gaed) { sgx_spin_unlock(&item->item_lock); return SGX_ERROR_INVALID_STATE; } memcpy(&a, &item->a, sizeof(a)); memcpy(&gb_ga[1], &item->g_a, sizeof(gb_ga[1])); memcpy(&sp_pubkey, &item->sp_pubkey, sizeof(sp_pubkey)); ra_key_cb = DEC_KDF_POINTER(item->derive_key_cb); sgx_spin_unlock(&item->item_lock); memcpy(&gb_ga[0], &p_msg2->g_b, sizeof(gb_ga[0])); sgx_ecc_state_handle_t ecc_state = NULL; // ecc_state need to be freed when exit. se_ret = sgx_ecc256_open_context(&ecc_state); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; return se_ret; } sgx_ec256_dh_shared_t dh_key; memset(&dh_key, 0, sizeof(dh_key)); sgx_ec256_public_t* p_msg2_g_b = const_cast<sgx_ec256_public_t*>(&p_msg2->g_b); se_ret = sgx_ecc256_compute_shared_dhkey(&a, (sgx_ec256_public_t*)p_msg2_g_b, &dh_key, ecc_state); if(SGX_SUCCESS != se_ret) { if (SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; sgx_ecc256_close_context(ecc_state); return se_ret; } // Verify signature of gb_ga uint8_t result; sgx_ec256_signature_t* p_msg2_sign_gb_ga = const_cast<sgx_ec256_signature_t*>(&p_msg2->sign_gb_ga); se_ret = sgx_ecdsa_verify((uint8_t *)&gb_ga, sizeof(gb_ga), &sp_pubkey, p_msg2_sign_gb_ga, &result, ecc_state); if(SGX_SUCCESS != se_ret) { if (SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; sgx_ecc256_close_context(ecc_state); return se_ret; } if(SGX_EC_VALID != result) { sgx_ecc256_close_context(ecc_state); return SGX_ERROR_INVALID_SIGNATURE; } do { if(NULL != ra_key_cb) { se_ret = ra_key_cb(&dh_key, p_msg2->kdf_id, &smkey, &skey, &mkey, &vkey); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret && SGX_ERROR_INVALID_PARAMETER != se_ret && SGX_ERROR_KDF_MISMATCH != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } } else if (p_msg2->kdf_id == 0x0001) { se_ret = derive_key(&dh_key, "SMK", (uint32_t)(sizeof("SMK") -1), &smkey); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } se_ret = derive_key(&dh_key, "SK", (uint32_t)(sizeof("SK") -1), &skey); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } se_ret = derive_key(&dh_key, "MK", (uint32_t)(sizeof("MK") -1), &mkey); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } se_ret = derive_key(&dh_key, "VK", (uint32_t)(sizeof("VK") -1), &vkey); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } } else { se_ret = SGX_ERROR_KDF_MISMATCH; break; } sgx_cmac_128bit_tag_t mac; uint32_t maced_size = offsetof(sgx_ra_msg2_t, mac); se_ret = sgx_rijndael128_cmac_msg(&smkey, (const uint8_t *)p_msg2, maced_size, &mac); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } //Check mac if(0 == consttime_memequal(mac, p_msg2->mac, sizeof(mac))) { se_ret = SGX_ERROR_MAC_MISMATCH; break; } //create a nonce se_ret =sgx_read_rand((uint8_t*)p_nonce, sizeof(sgx_quote_nonce_t)); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; break; } sgx_spin_lock(&item->item_lock); //sgx_ra_get_ga must have been called if (item->state != ra_get_gaed) { se_ret = SGX_ERROR_INVALID_STATE; sgx_spin_unlock(&item->item_lock); break; } memcpy(&item->g_b, &p_msg2->g_b, sizeof(item->g_b)); memcpy(&item->smk_key, smkey, sizeof(item->smk_key)); memcpy(&item->sk_key, skey, sizeof(item->sk_key)); memcpy(&item->mk_key, mkey, sizeof(item->mk_key)); memcpy(&item->vk_key, vkey, sizeof(item->vk_key)); memcpy(&item->qe_target, p_qe_target, sizeof(sgx_target_info_t)); memcpy(&item->quote_nonce, p_nonce, sizeof(sgx_quote_nonce_t)); sgx_report_data_t report_data = {{0}}; se_static_assert(sizeof(sgx_report_data_t)>=sizeof(sgx_sha256_hash_t)); // H = SHA256(ga || gb || VK_CMAC) uint32_t sha256ed_size = offsetof(ra_db_item_t, sp_pubkey); //report_data is 512bits, H is 256bits. The H is in the lower 256 bits of report data while the higher 256 bits are all zeros. se_ret = sgx_sha256_msg((uint8_t *)&item->g_a, sha256ed_size, (sgx_sha256_hash_t *)&report_data); if(SGX_SUCCESS != se_ret) { if (SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; sgx_spin_unlock(&item->item_lock); break; } //REPORTDATA = H se_ret = sgx_create_report(p_qe_target, &report_data, p_report); if (SGX_SUCCESS != se_ret) { if(SGX_ERROR_OUT_OF_MEMORY != se_ret) se_ret = SGX_ERROR_UNEXPECTED; sgx_spin_unlock(&item->item_lock); break; } item->state = ra_proc_msg2ed; sgx_spin_unlock(&item->item_lock); }while(0); memset_s(&dh_key, sizeof(dh_key), 0, sizeof(dh_key)); sgx_ecc256_close_context(ecc_state); memset_s(&a, sizeof(sgx_ec256_private_t),0, sizeof(sgx_ec256_private_t)); memset_s(smkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); memset_s(skey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); memset_s(mkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); memset_s(vkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); return se_ret; }
/* * 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; 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}; sgx_report_data_t qe_report_data = {{0}}; sgx_target_info_t report_target; sgx_ec256_public_t ec_pub_key; // little endian se_ae_ecdsa_hash_t sig_rl_hash = {{0}}; uint8_t ecc_result = SGX_EC_INVALID_SIGNATURE; sgx_sha_state_handle_t sha_context = NULL; sgx_sha_state_handle_t sha_quote_context = NULL; sgx_aes_state_handle_t aes_gcm_state = NULL; void *pub_key = NULL; size_t pub_key_size = 0; uint8_t* pub_key_buffer = NULL; sgx_ecc_state_handle_t ecc_handle = 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, NULL); //Random basename, can be NULL if basename is provided 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((uint8_t *)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. /* 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 algorithm. */ se_ret = sgx_create_rsa_pub1_key(sizeof(g_qsdk_pub_key_n), sizeof(g_qsdk_pub_key_e), (const unsigned char *)g_qsdk_pub_key_n, (const unsigned char *)g_qsdk_pub_key_e, &pub_key); if(se_ret != SGX_SUCCESS) { ret = QE_UNEXPECTED_ERROR; goto CLEANUP; } /* Get output buffer size */ se_ret = sgx_rsa_pub_encrypt_sha256(pub_key, NULL, &pub_key_size, aes_key, sizeof(aes_key)); if(SGX_SUCCESS != se_ret) { ret = QE_UNEXPECTED_ERROR; goto CLEANUP; } se_ret = sgx_rsa_pub_encrypt_sha256(pub_key, wrap_key.encrypted_key, &pub_key_size, aes_key, sizeof(aes_key)); if(SGX_SUCCESS != se_ret) { 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)); se_ret = sgx_aes_gcm128_enc_init( aes_key, aes_iv, //input initial vector. randomly generated value and encryption of different msg should use different iv sizeof(aes_iv), //length of initial vector, usually IV_SIZE NULL,//AAD of AES-GCM, it could be NULL 0, //length of bytes of AAD &aes_gcm_state); if(SGX_SUCCESS != se_ret) { ret = QE_UNEXPECTED_ERROR; goto CLEANUP; } memset_s(aes_key, sizeof(aes_key), 0, sizeof(aes_key)); /* Encrypt the basic signature. */ se_ret = sgx_aes_gcm128_enc_update( (uint8_t *)&basic_sig, //start address to data before/after encryption sizeof(basic_sig), (uint8_t *)&encrypted_basic_sig, //length of data aes_gcm_state); //pointer to a state if(SGX_SUCCESS != se_ret) { 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 se_ret = sgx_aes_gcm128_enc_update( (uint8_t *)&(p_sig_rl_header->sig_rl.version), //start address to data before/after encryption sizeof(p_sig_rl_header->sig_rl.version), (uint8_t *)&encrypted_rl_ver, //length of data aes_gcm_state); //pointer to a state if(SGX_SUCCESS != se_ret) { ret = QE_UNEXPECTED_ERROR; goto CLEANUP; } se_ret = sgx_aes_gcm128_enc_update( (uint8_t *)&(p_sig_rl_header->sig_rl.n2), //start address to data before/after encryption sizeof(p_sig_rl_header->sig_rl.n2), (uint8_t *)&encrypted_n2, //length of data aes_gcm_state); //pointer to a state if(SGX_SUCCESS != se_ret) { 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, (uint8_t *)const_cast<sgx_basename_t *>(p_basename), // basename is required, otherwise it will return kEpidBadArgErr sizeof(*p_basename), &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((uint8_t *)&entry, sizeof(entry), sha_context); if(SGX_SUCCESS != se_ret) { ret = QE_UNEXPECTED_ERROR; goto CLEANUP; } se_ret = sgx_aes_gcm128_enc_update( (uint8_t *)&temp_nr, //start address to data before/after encryption sizeof(encrypted_temp_nr), (uint8_t *)&encrypted_temp_nr, //length of data aes_gcm_state); //pointer to a state if(SGX_SUCCESS != se_ret) { 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 integrity of SIG-RL by check ECDSA signature. */ 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_ret = sgx_ecc256_open_context(&ecc_handle); if(SGX_SUCCESS != se_ret) { ret = QE_UNEXPECTED_ERROR; goto CLEANUP; } // sgx_ecdsa_verify_hash will take ec_pub_key as little endian se_ret = sgx_ecdsa_verify_hash((uint8_t*)&(sig_rl_hash.hash), (const sgx_ec256_public_t *)&ec_pub_key, p_sig_rl_signature, &ecc_result, ecc_handle); if(SGX_SUCCESS != se_ret) { ret = QE_UNEXPECTED_ERROR; goto CLEANUP; } else if(SGX_EC_VALID != ecc_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}; se_ret = sgx_aes_gcm128_enc_update( (uint8_t *)&temp_buf, //start address to data before/after encryption sizeof(encrypted_temp_buf), (uint8_t *)&encrypted_temp_buf, //length of data aes_gcm_state); //pointer to a state if(SGX_SUCCESS != se_ret) { 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; } } } se_ret = sgx_aes_gcm128_enc_get_mac(aes_tag, aes_gcm_state); if(SGX_SUCCESS != se_ret) { 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_gcm_state) sgx_aes_gcm_close(aes_gcm_state); if (pub_key) sgx_free_rsa_key(pub_key, SGX_RSA_PUBLIC_KEY, sizeof(plaintext.qsdk_mod), sizeof(plaintext.qsdk_exp)); if (pub_key_buffer) free(pub_key_buffer); if (ecc_handle) sgx_ecc256_close_context(ecc_handle); return ret; }
ae_error_t prepare_for_certificate_provisioning ( /*in */ UINT64 nonce64, /*in */ const sgx_target_info_t* pTargetInfo, /*in */ UINT16 nMax_CSR_pse, /*out*/ UINT8* pCSR_pse, /*out*/ UINT16* pnLen_CSR_pse, /*out*/ sgx_report_t* pREPORT, /*i/o*/ pairing_blob_t* pPairingBlob ) { // Flow: 1) Check pointers for buffer data sizes // 2) If buffers are too small, return and tell caller size required // 3) Validate pointers and ensure buffers are within the enclave // 4) Generate a new private/public ECDSA key pair // 5) Request signed CSR template // 6) Calculate HASH_pse of (CSR_pse || nonce64) // 7) Generate REPORT with HASH_pse as the REPORTDATA, targeting QE // 8) Copy private key and public key into unsealed_pairing buffer // 9) Seal pairing blob // 10) Return Sealed pairing blob, generated CSR, REPORT, and status ae_error_t status = AE_FAILURE; pairing_data_t pairingData; EcDsaPrivKey privateKey; EcDsaPubKey publicKey; uint8_t temp_instance_id[16]; SignCSR CSR; size_t nMaxSizeCSR = CSR.GetMaxSize(); sgx_ecc_state_handle_t csr_ecc_handle = NULL; memset(&pairingData, 0, sizeof(pairingData)); ///////////////////////////////////////////////////////////////// do { //********************************************************************* // Validate pointers and sizes //********************************************************************* BREAK_IF_TRUE((NULL == pPairingBlob), status, PSE_PR_BAD_POINTER_ERROR); // save SW_INSTANCE_ID memcpy(temp_instance_id, pPairingBlob->plaintext.pse_instance_id, sizeof(temp_instance_id)); { BREAK_IF_TRUE((NULL == pTargetInfo), status, PSE_PR_BAD_POINTER_ERROR); BREAK_IF_TRUE((NULL == pREPORT), status, PSE_PR_BAD_POINTER_ERROR); BREAK_IF_TRUE((NULL == pCSR_pse || NULL == pnLen_CSR_pse), status, PSE_PR_BAD_POINTER_ERROR); BREAK_IF_TRUE((nMax_CSR_pse < nMaxSizeCSR), status, PSE_PR_PARAMETER_ERROR); BREAK_IF_FALSE(sgx_is_within_enclave(pCSR_pse, nMaxSizeCSR), status, PSE_PR_BAD_POINTER_ERROR); //********************************************************************* // Generate a new ECDSA Key Pair //********************************************************************* sgx_status_t sgx_status = sgx_ecc256_open_context(&csr_ecc_handle); BREAK_IF_TRUE((SGX_ERROR_OUT_OF_MEMORY == sgx_status), status, PSE_PR_INSUFFICIENT_MEMORY_ERROR); BREAK_IF_TRUE((SGX_SUCCESS != sgx_status), status, PSE_PR_KEY_PAIR_GENERATION_ERROR); sgx_status = sgx_ecc256_create_key_pair((sgx_ec256_private_t *)privateKey, (sgx_ec256_public_t*)publicKey, csr_ecc_handle); BREAK_IF_TRUE((SGX_SUCCESS != sgx_status), status, PSE_PR_KEY_PAIR_GENERATION_ERROR); *pnLen_CSR_pse = (uint16_t)nMaxSizeCSR; //********************************************************************* // Get a signed Certificate Signing Request from the template //********************************************************************* status = CSR.GetSignedTemplate(&privateKey, &publicKey, csr_ecc_handle, pCSR_pse, pnLen_CSR_pse); BREAK_IF_FAILED(status); //********************************************************************* // Calculate HASH_pse of (CSR_pse || nonce64) //********************************************************************* PrepareHashSHA256 hash; SHA256_HASH computedHash; status = hash.Update(pCSR_pse, *pnLen_CSR_pse); BREAK_IF_FAILED(status); status = hash.Update(&nonce64, sizeof(nonce64)); BREAK_IF_FAILED(status); status = hash.Finalize(&computedHash); BREAK_IF_FAILED(status); //********************************************************************* // Generate a REPORT with HASH_pse //********************************************************************* sgx_report_data_t report_data = {{0}}; memcpy(&report_data, &computedHash, sizeof(computedHash)); if (SGX_SUCCESS != sgx_create_report(const_cast<sgx_target_info_t*>(pTargetInfo), &report_data, (sgx_report_t*)pREPORT)) { status = PSE_PR_CREATE_REPORT_ERROR; break; } //********************************************************************* // Try to unseal the pairing data //********************************************************************* status = UnsealPairingBlob(pPairingBlob, &pairingData); if (AE_FAILED(status)) memset_s(&pairingData, sizeof(pairingData), 0, sizeof(pairingData)); //********************************************************************* // Seal ECDSA Verifier Private Key into blob //********************************************************************* memcpy(pairingData.secret_data.VerifierPrivateKey, &privateKey, sizeof(EcDsaPrivKey)); } // "Public" PSE Cert // Set pairingData.plaintext.pse_instance_id using saved temp_instance_id memcpy(pairingData.plaintext.pse_instance_id, temp_instance_id, sizeof(pairingData.plaintext.pse_instance_id)); status = SealPairingBlob(&pairingData, pPairingBlob); BREAK_IF_FAILED(status); //********************************************************************* // WE PASSED ALL BARRIERS TO SUCCESS //********************************************************************* status = AE_SUCCESS; // OutputOctets("::tPrepareForCertificateProvisioning:: New CSR generated", NULL, 0); } while (false); // Defense-in-depth: clear the data on stack that contains enclave secret. memset_s(&pairingData, sizeof(pairingData), 0, sizeof(pairingData)); memset_s(&privateKey, sizeof(privateKey), 0, sizeof(privateKey)); if (csr_ecc_handle != NULL) sgx_ecc256_close_context(csr_ecc_handle); return map_error_for_return(status); }
/* * Internal function used to init white list. It will check the content of the * cert chain, and verify the signature of input cert chains. If no problem, * it will cache the input white list into EPC. * * @param p_wl_cert_chain[in] Pointer to the white list cert chain. * @param entry_number[in] The entry number within the white list. * @param wl_cert_chain_size[in] The size of white list cert chain, in bytes. * @return uint32_t AE_SUCCESS for success, otherwise for errors. */ uint32_t le_init_white_list( const wl_cert_chain_t *p_wl_cert_chain, uint32_t entry_number, uint32_t wl_cert_chain_size) { sgx_status_t sgx_ret = SGX_SUCCESS; uint32_t ret = AE_SUCCESS; uint32_t new_wl_version = 0; uint8_t verify_result = 0; int valid = 0; const uint8_t *buf = NULL; uint32_t buf_size = 0; sgx_prod_id_t wl_prod_id = 0; sgx_ecc_state_handle_t ecc_handle = NULL; wl_cert_t *p_wl_cert_cache = (wl_cert_t *)g_wl_cert_buf; sgx_report_t report; sgx_ec256_signature_t wl_signature; sgx_ec256_public_t wl_pubkey; // Check fields of provider cert // Format version should be 1 (big endian) if(p_wl_cert_chain->wl_provider_cert.version != WL_PROVIDER_CERT_VERSION) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } // For Enclave Signing Key White List Cert, must be 0 if(p_wl_cert_chain->wl_provider_cert.cert_type != WL_PROVIDER_CERT_TYPE) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } // only one White List Provider is approved: // WLProviderID: ISecG = 0 if(p_wl_cert_chain->wl_provider_cert.provider_id != WL_PROVIDER_CERT_PROVIDER_ID) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } // only one WLRootID is valid: WLRootID-iKGF-Key-0 = 0 if(p_wl_cert_chain->wl_provider_cert.root_id != WL_PROVIDER_CERT_ROOT_ID) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } // Check fields of wl cert // only valid version is 1 if(p_wl_cert_chain->wl_cert.version != WL_CERT_VERSION) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } // For Enclave Signing Key White List Cert, must be 1 if(p_wl_cert_chain->wl_cert.cert_type != WL_CERT_TYPE) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } // only one White List Provider is approved: // WLProviderID: ISecG = 0 if(p_wl_cert_chain->wl_cert.provider_id != WL_CERT_PROVIDER_ID) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } // If cache exists new_wl_version = p_wl_cert_chain->wl_cert.wl_version; new_wl_version = _ntohl(new_wl_version); if(p_wl_cert_cache->version != 0) { // the logic will be needed to support more than // one providers in the future. //if(p_wl_cert_chain->wl_cert.provider_id // != p_wl_cert_cache->provider_id) //{ // ret = LE_INVALID_PARAMETER; // goto CLEANUP; //} if(new_wl_version < p_wl_cert_cache->wl_version) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } } sgx_ret = sgx_ecc256_open_context(&ecc_handle); if (SGX_SUCCESS != sgx_ret) { ret = LE_UNEXPECTED_ERROR; goto CLEANUP; } memset(&wl_signature, 0, sizeof(wl_signature)); // Convert the signature of provider cert into little endian memcpy(&wl_signature, &(p_wl_cert_chain->wl_provider_cert.signature), sizeof(wl_signature)); SWAP_ENDIAN_8X32B(wl_signature.x); SWAP_ENDIAN_8X32B(wl_signature.y); // Verify the wl provider cert buf = (const uint8_t *)&(p_wl_cert_chain->wl_provider_cert); buf_size = static_cast<uint32_t>(sizeof(p_wl_cert_chain->wl_provider_cert) - sizeof(p_wl_cert_chain->wl_provider_cert.signature)); sgx_ret = sgx_ecdsa_verify(buf, buf_size, &g_wl_root_pubkey, &wl_signature, &verify_result, ecc_handle); if (SGX_SUCCESS != sgx_ret) { ret = LE_UNEXPECTED_ERROR; goto CLEANUP; } if(SGX_EC_VALID != verify_result) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } // Convert the signature of wl cert into little endian buf = (const uint8_t *)p_wl_cert_chain + wl_cert_chain_size - sizeof(wl_signature); memcpy(&wl_signature, buf, sizeof(wl_signature)); SWAP_ENDIAN_8X32B(wl_signature.x); SWAP_ENDIAN_8X32B(wl_signature.y); // Convert the pubkey into little endian memset(&wl_pubkey, 0, sizeof(wl_pubkey)); memcpy(&wl_pubkey, &(p_wl_cert_chain->wl_provider_cert.pub_key), sizeof(wl_pubkey)); reverse_byte_array(wl_pubkey.gx, sizeof(wl_pubkey.gx)); reverse_byte_array(wl_pubkey.gy, sizeof(wl_pubkey.gy)); // Check whether the pubkey is valid first. sgx_ret = sgx_ecc256_check_point(&wl_pubkey, ecc_handle, &valid); if(SGX_SUCCESS != sgx_ret) { ret = LE_UNEXPECTED_ERROR; goto CLEANUP; } if(!valid) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } // Verify the wl_cert buf = (const uint8_t *)&(p_wl_cert_chain->wl_cert); buf_size = wl_cert_chain_size - static_cast<uint32_t>(sizeof(wl_provider_cert_t) + sizeof(sgx_ec256_signature_t)); sgx_ret = sgx_ecdsa_verify(buf, buf_size, &wl_pubkey, &wl_signature, &verify_result, ecc_handle); if (SGX_SUCCESS != sgx_ret) { ret = LE_UNEXPECTED_ERROR; goto CLEANUP; } if(SGX_EC_VALID != verify_result) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } memset(&report, 0, sizeof(report)); // Create report to get current mrsigner. sgx_ret = sgx_create_report(NULL, NULL, &report); if(SGX_SUCCESS != sgx_ret) { ret = LE_UNEXPECTED_ERROR; goto CLEANUP; } // Convert the big endian prod id to little endian. wl_prod_id = p_wl_cert_chain->wl_cert.le_prod_id; wl_prod_id = _ntohs(wl_prod_id); if(report.body.isv_prod_id != wl_prod_id) { ret = LE_INVALID_PARAMETER; goto CLEANUP; } // Cache the wl cert memset(g_wl_cert_buf, 0, sizeof(g_wl_cert_buf)); memcpy(g_wl_cert_buf, &(p_wl_cert_chain->wl_cert), buf_size); // Change entry_number and wl_version to little endian, so we don't need to // convert them next time. p_wl_cert_cache->entry_number = entry_number; p_wl_cert_cache->wl_version = new_wl_version; CLEANUP: if(ecc_handle != NULL) { sgx_ecc256_close_context(ecc_handle); } return ret; }