123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738 |
- /*
- * Copyright (C) 2011-2017 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.
- *
- */
- #include "service_provider.h"
- #include "sample_libcrypto.h"
- #include "ecp.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <stddef.h>
- #include <time.h>
- #include <string.h>
- #include "ias_ra.h"
- #ifndef SAFE_FREE
- #define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr) = NULL;}}
- #endif
- // This is supported extended epid group of SP. SP can support more than one
- // extended epid group with different extended epid group id and credentials.
- static const sample_extended_epid_group g_extended_epid_groups[] = {
- {
- 0,
- ias_enroll,
- ias_get_sigrl,
- ias_verify_attestation_evidence
- }
- };
- // This is the private EC key of SP, the corresponding public EC key is
- // hard coded in isv_enclave. It is based on NIST P-256 curve.
- static const sample_ec256_private_t g_sp_priv_key = {
- {
- 0x90, 0xe7, 0x6c, 0xbb, 0x2d, 0x52, 0xa1, 0xce,
- 0x3b, 0x66, 0xde, 0x11, 0x43, 0x9c, 0x87, 0xec,
- 0x1f, 0x86, 0x6a, 0x3b, 0x65, 0xb6, 0xae, 0xea,
- 0xad, 0x57, 0x34, 0x53, 0xd1, 0x03, 0x8c, 0x01
- }
- };
- // This is the public EC key of SP, this key is hard coded in isv_enclave.
- // It is based on NIST P-256 curve. Not used in the SP code.
- static const sample_ec_pub_t g_sp_pub_key = {
- {
- 0x72, 0x12, 0x8a, 0x7a, 0x17, 0x52, 0x6e, 0xbf,
- 0x85, 0xd0, 0x3a, 0x62, 0x37, 0x30, 0xae, 0xad,
- 0x3e, 0x3d, 0xaa, 0xee, 0x9c, 0x60, 0x73, 0x1d,
- 0xb0, 0x5b, 0xe8, 0x62, 0x1c, 0x4b, 0xeb, 0x38
- },
- {
- 0xd4, 0x81, 0x40, 0xd9, 0x50, 0xe2, 0x57, 0x7b,
- 0x26, 0xee, 0xb7, 0x41, 0xe7, 0xc6, 0x14, 0xe2,
- 0x24, 0xb7, 0xbd, 0xc9, 0x03, 0xf2, 0x9a, 0x28,
- 0xa8, 0x3c, 0xc8, 0x10, 0x11, 0x14, 0x5e, 0x06
- }
- };
- // This is a context data structure used on SP side
- typedef struct _sp_db_item_t
- {
- sample_ec_pub_t g_a;
- sample_ec_pub_t g_b;
- sample_ec_key_128bit_t vk_key;// Shared secret key for the REPORT_DATA
- sample_ec_key_128bit_t mk_key;// Shared secret key for generating MAC's
- sample_ec_key_128bit_t sk_key;// Shared secret key for encryption
- sample_ec_key_128bit_t smk_key;// Used only for SIGMA protocol
- sample_ec_priv_t b;
- sample_ps_sec_prop_desc_t ps_sec_prop;
- }sp_db_item_t;
- static sp_db_item_t g_sp_db;
- static const sample_extended_epid_group* g_sp_extended_epid_group_id= NULL;
- static bool g_is_sp_registered = false;
- static int g_sp_credentials = 0;
- static int g_authentication_token = 0;
- uint8_t g_secret[8] = {0,1,2,3,4,5,6,7};
- sample_spid_t g_spid;
- // Verify message 0 then configure extended epid group.
- int sp_ra_proc_msg0_req(const sample_ra_msg0_t *p_msg0,
- uint32_t msg0_size)
- {
- int ret = -1;
- if (!p_msg0 ||
- (msg0_size != sizeof(sample_ra_msg0_t)))
- {
- return -1;
- }
- uint32_t extended_epid_group_id = p_msg0->extended_epid_group_id;
- // Check to see if we have registered with the attestation server yet?
- if (!g_is_sp_registered ||
- (g_sp_extended_epid_group_id != NULL && g_sp_extended_epid_group_id->extended_epid_group_id != extended_epid_group_id))
- {
- // Check to see if the extended_epid_group_id is supported?
- ret = SP_UNSUPPORTED_EXTENDED_EPID_GROUP;
- for (size_t i = 0; i < sizeof(g_extended_epid_groups) / sizeof(sample_extended_epid_group); i++)
- {
- if (g_extended_epid_groups[i].extended_epid_group_id == extended_epid_group_id)
- {
- g_sp_extended_epid_group_id = &(g_extended_epid_groups[i]);
- // In the product, the SP will establish a mutually
- // authenticated SSL channel. During the enrollment process, the ISV
- // registers it exchanges TLS certs with attestation server and obtains an SPID and
- // Report Key from the attestation server.
- // For a product attestation server, enrollment is an offline process. See the 'on-boarding'
- // documentation to get the information required. The enrollment process is
- // simulated by a call in this sample.
- ret = g_sp_extended_epid_group_id->enroll(g_sp_credentials, &g_spid,
- &g_authentication_token);
- if (0 != ret)
- {
- ret = SP_IAS_FAILED;
- break;
- }
- g_is_sp_registered = true;
- ret = SP_OK;
- break;
- }
- }
- }
- else
- {
- ret = SP_OK;
- }
- return ret;
- }
- // Verify message 1 then generate and return message 2 to isv.
- int sp_ra_proc_msg1_req(const sample_ra_msg1_t *p_msg1,
- uint32_t msg1_size,
- ra_samp_response_header_t **pp_msg2)
- {
- int ret = 0;
- ra_samp_response_header_t* p_msg2_full = NULL;
- sample_ra_msg2_t *p_msg2 = NULL;
- sample_ecc_state_handle_t ecc_state = NULL;
- sample_status_t sample_ret = SAMPLE_SUCCESS;
- bool derive_ret = false;
- if(!p_msg1 ||
- !pp_msg2 ||
- (msg1_size != sizeof(sample_ra_msg1_t)))
- {
- return -1;
- }
- // Check to see if we have registered?
- if (!g_is_sp_registered)
- {
- return SP_UNSUPPORTED_EXTENDED_EPID_GROUP;
- }
- do
- {
- // Get the sig_rl from attestation server using GID.
- // GID is Base-16 encoded of EPID GID in little-endian format.
- // In the product, the SP and attesation server uses an established channel for
- // communication.
- uint8_t* sig_rl;
- uint32_t sig_rl_size = 0;
- // The product interface uses a REST based message to get the SigRL.
-
- ret = g_sp_extended_epid_group_id->get_sigrl(p_msg1->gid, &sig_rl_size, &sig_rl);
- if(0 != ret)
- {
- fprintf(stderr, "\nError, ias_get_sigrl [%s].", __FUNCTION__);
- ret = SP_IAS_FAILED;
- break;
- }
- // Need to save the client's public ECCDH key to local storage
- if (memcpy_s(&g_sp_db.g_a, sizeof(g_sp_db.g_a), &p_msg1->g_a,
- sizeof(p_msg1->g_a)))
- {
- fprintf(stderr, "\nError, cannot do memcpy in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- // Generate the Service providers ECCDH key pair.
- sample_ret = sample_ecc256_open_context(&ecc_state);
- if(SAMPLE_SUCCESS != sample_ret)
- {
- fprintf(stderr, "\nError, cannot get ECC context in [%s].",
- __FUNCTION__);
- ret = -1;
- break;
- }
- sample_ec256_public_t pub_key = {{0},{0}};
- sample_ec256_private_t priv_key = {{0}};
- sample_ret = sample_ecc256_create_key_pair(&priv_key, &pub_key,
- ecc_state);
- if(SAMPLE_SUCCESS != sample_ret)
- {
- fprintf(stderr, "\nError, cannot generate key pair in [%s].",
- __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- // Need to save the SP ECCDH key pair to local storage.
- if(memcpy_s(&g_sp_db.b, sizeof(g_sp_db.b), &priv_key,sizeof(priv_key))
- || memcpy_s(&g_sp_db.g_b, sizeof(g_sp_db.g_b),
- &pub_key,sizeof(pub_key)))
- {
- fprintf(stderr, "\nError, cannot do memcpy in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- // Generate the client/SP shared secret
- sample_ec_dh_shared_t dh_key = {{0}};
- sample_ret = sample_ecc256_compute_shared_dhkey(&priv_key,
- (sample_ec256_public_t *)&p_msg1->g_a,
- (sample_ec256_dh_shared_t *)&dh_key,
- ecc_state);
- if(SAMPLE_SUCCESS != sample_ret)
- {
- fprintf(stderr, "\nError, compute share key fail in [%s].",
- __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- #ifdef SUPPLIED_KEY_DERIVATION
- // smk is only needed for msg2 generation.
- derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SMK_SK,
- &g_sp_db.smk_key, &g_sp_db.sk_key);
- if(derive_ret != true)
- {
- fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- // The rest of the keys are the shared secrets for future communication.
- derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_MK_VK,
- &g_sp_db.mk_key, &g_sp_db.vk_key);
- if(derive_ret != true)
- {
- fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- #else
- // smk is only needed for msg2 generation.
- derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SMK,
- &g_sp_db.smk_key);
- if(derive_ret != true)
- {
- fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- // The rest of the keys are the shared secrets for future communication.
- derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_MK,
- &g_sp_db.mk_key);
- if(derive_ret != true)
- {
- fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SK,
- &g_sp_db.sk_key);
- if(derive_ret != true)
- {
- fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_VK,
- &g_sp_db.vk_key);
- if(derive_ret != true)
- {
- fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- #endif
- uint32_t msg2_size = sizeof(sample_ra_msg2_t) + sig_rl_size;
- p_msg2_full = (ra_samp_response_header_t*)malloc(msg2_size
- + sizeof(ra_samp_response_header_t));
- if(!p_msg2_full)
- {
- fprintf(stderr, "\nError, out of memory in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- memset(p_msg2_full, 0, msg2_size + sizeof(ra_samp_response_header_t));
- p_msg2_full->type = TYPE_RA_MSG2;
- p_msg2_full->size = msg2_size;
- // The simulated message2 always passes. This would need to be set
- // accordingly in a real service provider implementation.
- p_msg2_full->status[0] = 0;
- p_msg2_full->status[1] = 0;
- p_msg2 = (sample_ra_msg2_t *)p_msg2_full->body;
- // Assemble MSG2
- if(memcpy_s(&p_msg2->g_b, sizeof(p_msg2->g_b), &g_sp_db.g_b,
- sizeof(g_sp_db.g_b)) ||
- memcpy_s(&p_msg2->spid, sizeof(sample_spid_t),
- &g_spid, sizeof(g_spid)))
- {
- fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- // The service provider is responsible for selecting the proper EPID
- // signature type and to understand the implications of the choice!
- p_msg2->quote_type = SAMPLE_QUOTE_LINKABLE_SIGNATURE;
- #ifdef SUPPLIED_KEY_DERIVATION
- //isv defined key derivation function id
- #define ISV_KDF_ID 2
- p_msg2->kdf_id = ISV_KDF_ID;
- #else
- p_msg2->kdf_id = SAMPLE_AES_CMAC_KDF_ID;
- #endif
- // Create gb_ga
- sample_ec_pub_t gb_ga[2];
- if(memcpy_s(&gb_ga[0], sizeof(gb_ga[0]), &g_sp_db.g_b,
- sizeof(g_sp_db.g_b))
- || memcpy_s(&gb_ga[1], sizeof(gb_ga[1]), &g_sp_db.g_a,
- sizeof(g_sp_db.g_a)))
- {
- fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- // Sign gb_ga
- sample_ret = sample_ecdsa_sign((uint8_t *)&gb_ga, sizeof(gb_ga),
- (sample_ec256_private_t *)&g_sp_priv_key,
- (sample_ec256_signature_t *)&p_msg2->sign_gb_ga,
- ecc_state);
- if(SAMPLE_SUCCESS != sample_ret)
- {
- fprintf(stderr, "\nError, sign ga_gb fail in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- // Generate the CMACsmk for gb||SPID||TYPE||KDF_ID||Sigsp(gb,ga)
- uint8_t mac[SAMPLE_EC_MAC_SIZE] = {0};
- uint32_t cmac_size = offsetof(sample_ra_msg2_t, mac);
- sample_ret = sample_rijndael128_cmac_msg(&g_sp_db.smk_key,
- (uint8_t *)&p_msg2->g_b, cmac_size, &mac);
- if(SAMPLE_SUCCESS != sample_ret)
- {
- fprintf(stderr, "\nError, cmac fail in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- if(memcpy_s(&p_msg2->mac, sizeof(p_msg2->mac), mac, sizeof(mac)))
- {
- fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- if(memcpy_s(&p_msg2->sig_rl[0], sig_rl_size, sig_rl, sig_rl_size))
- {
- fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- p_msg2->sig_rl_size = sig_rl_size;
- }while(0);
- if(ret)
- {
- *pp_msg2 = NULL;
- SAFE_FREE(p_msg2_full);
- }
- else
- {
- // Freed by the network simulator in ra_free_network_response_buffer
- *pp_msg2 = p_msg2_full;
- }
- if(ecc_state)
- {
- sample_ecc256_close_context(ecc_state);
- }
- return ret;
- }
- // Process remote attestation message 3
- int sp_ra_proc_msg3_req(const sample_ra_msg3_t *p_msg3,
- uint32_t msg3_size,
- ra_samp_response_header_t **pp_att_result_msg)
- {
- int ret = 0;
- sample_status_t sample_ret = SAMPLE_SUCCESS;
- const uint8_t *p_msg3_cmaced = NULL;
- sample_quote_t *p_quote = NULL;
- sample_sha_state_handle_t sha_handle = NULL;
- sample_report_data_t report_data = {0};
- sample_ra_att_result_msg_t *p_att_result_msg = NULL;
- ra_samp_response_header_t* p_att_result_msg_full = NULL;
- uint32_t i;
- if((!p_msg3) ||
- (msg3_size < sizeof(sample_ra_msg3_t)) ||
- (!pp_att_result_msg))
- {
- return SP_INTERNAL_ERROR;
- }
- // Check to see if we have registered?
- if (!g_is_sp_registered)
- {
- return SP_UNSUPPORTED_EXTENDED_EPID_GROUP;
- }
- do
- {
- // Compare g_a in message 3 with local g_a.
- ret = memcmp(&g_sp_db.g_a, &p_msg3->g_a, sizeof(sample_ec_pub_t));
- if(ret)
- {
- fprintf(stderr, "\nError, g_a is not same [%s].", __FUNCTION__);
- ret = SP_PROTOCOL_ERROR;
- break;
- }
- //Make sure that msg3_size is bigger than sample_mac_t.
- uint32_t mac_size = msg3_size - sizeof(sample_mac_t);
- p_msg3_cmaced = reinterpret_cast<const uint8_t*>(p_msg3);
- p_msg3_cmaced += sizeof(sample_mac_t);
- // Verify the message mac using SMK
- sample_cmac_128bit_tag_t mac = {0};
- sample_ret = sample_rijndael128_cmac_msg(&g_sp_db.smk_key,
- p_msg3_cmaced,
- mac_size,
- &mac);
- if(SAMPLE_SUCCESS != sample_ret)
- {
- fprintf(stderr, "\nError, cmac fail in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- // In real implementation, should use a time safe version of memcmp here,
- // in order to avoid side channel attack.
- ret = memcmp(&p_msg3->mac, mac, sizeof(mac));
- if(ret)
- {
- fprintf(stderr, "\nError, verify cmac fail [%s].", __FUNCTION__);
- ret = SP_INTEGRITY_FAILED;
- break;
- }
- if(memcpy_s(&g_sp_db.ps_sec_prop, sizeof(g_sp_db.ps_sec_prop),
- &p_msg3->ps_sec_prop, sizeof(p_msg3->ps_sec_prop)))
- {
- fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- p_quote = (sample_quote_t *)p_msg3->quote;
- // Check the quote version if needed. Only check the Quote.version field if the enclave
- // identity fields have changed or the size of the quote has changed. The version may
- // change without affecting the legacy fields or size of the quote structure.
- //if(p_quote->version < ACCEPTED_QUOTE_VERSION)
- //{
- // fprintf(stderr,"\nError, quote version is too old.", __FUNCTION__);
- // ret = SP_QUOTE_VERSION_ERROR;
- // break;
- //}
- // Verify the report_data in the Quote matches the expected value.
- // The first 32 bytes of report_data are SHA256 HASH of {ga|gb|vk}.
- // The second 32 bytes of report_data are set to zero.
- sample_ret = sample_sha256_init(&sha_handle);
- if(sample_ret != SAMPLE_SUCCESS)
- {
- fprintf(stderr,"\nError, init hash failed in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- sample_ret = sample_sha256_update((uint8_t *)&(g_sp_db.g_a),
- sizeof(g_sp_db.g_a), sha_handle);
- if(sample_ret != SAMPLE_SUCCESS)
- {
- fprintf(stderr,"\nError, udpate hash failed in [%s].",
- __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- sample_ret = sample_sha256_update((uint8_t *)&(g_sp_db.g_b),
- sizeof(g_sp_db.g_b), sha_handle);
- if(sample_ret != SAMPLE_SUCCESS)
- {
- fprintf(stderr,"\nError, udpate hash failed in [%s].",
- __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- sample_ret = sample_sha256_update((uint8_t *)&(g_sp_db.vk_key),
- sizeof(g_sp_db.vk_key), sha_handle);
- if(sample_ret != SAMPLE_SUCCESS)
- {
- fprintf(stderr,"\nError, udpate hash failed in [%s].",
- __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- sample_ret = sample_sha256_get_hash(sha_handle,
- (sample_sha256_hash_t *)&report_data);
- if(sample_ret != SAMPLE_SUCCESS)
- {
- fprintf(stderr,"\nError, Get hash failed in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- ret = memcmp((uint8_t *)&report_data,
- (uint8_t *)&(p_quote->report_body.report_data),
- sizeof(report_data));
- if(ret)
- {
- fprintf(stderr, "\nError, verify hash fail [%s].", __FUNCTION__);
- ret = SP_INTEGRITY_FAILED;
- break;
- }
- // Verify Enclave policy (an attestation server may provide an API for this if we
- // registered an Enclave policy)
- // Verify quote with attestation server.
- // In the product, an attestation server could use a REST message and JSON formatting to request
- // attestation Quote verification. The sample only simulates this interface.
- ias_att_report_t attestation_report = {0};
- ret = g_sp_extended_epid_group_id->verify_attestation_evidence(p_quote, NULL,
- &attestation_report);
- if(0 != ret)
- {
- ret = SP_IAS_FAILED;
- break;
- }
- FILE* OUTPUT = stdout;
- fprintf(OUTPUT, "\n\n\tAtestation Report:");
- fprintf(OUTPUT, "\n\tid: 0x%0x.", attestation_report.id);
- fprintf(OUTPUT, "\n\tstatus: %d.", attestation_report.status);
- fprintf(OUTPUT, "\n\trevocation_reason: %u.",
- attestation_report.revocation_reason);
- // attestation_report.info_blob;
- fprintf(OUTPUT, "\n\tpse_status: %d.", attestation_report.pse_status);
- // Note: This sample always assumes the PIB is sent by attestation server. In the product
- // implementation, the attestation server could only send the PIB for certain attestation
- // report statuses. A product SP implementation needs to handle cases
- // where the PIB is zero length.
- // Respond the client with the results of the attestation.
- uint32_t att_result_msg_size = sizeof(sample_ra_att_result_msg_t);
- p_att_result_msg_full =
- (ra_samp_response_header_t*)malloc(att_result_msg_size
- + sizeof(ra_samp_response_header_t) + sizeof(g_secret));
- if(!p_att_result_msg_full)
- {
- fprintf(stderr, "\nError, out of memory in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- memset(p_att_result_msg_full, 0, att_result_msg_size
- + sizeof(ra_samp_response_header_t) + sizeof(g_secret));
- p_att_result_msg_full->type = TYPE_RA_ATT_RESULT;
- p_att_result_msg_full->size = att_result_msg_size;
- if(IAS_QUOTE_OK != attestation_report.status)
- {
- p_att_result_msg_full->status[0] = 0xFF;
- }
- if(IAS_PSE_OK != attestation_report.pse_status)
- {
- p_att_result_msg_full->status[1] = 0xFF;
- }
- p_att_result_msg =
- (sample_ra_att_result_msg_t *)p_att_result_msg_full->body;
- // In a product implementation of attestation server, the HTTP response header itself could have
- // an RK based signature that the service provider needs to check here.
- // The platform_info_blob signature will be verified by the client
- // when sent. No need to have the Service Provider to check it. The SP
- // should pass it down to the application for further analysis.
- fprintf(OUTPUT, "\n\n\tEnclave Report:");
- fprintf(OUTPUT, "\n\tSignature Type: 0x%x", p_quote->sign_type);
- fprintf(OUTPUT, "\n\tSignature Basename: ");
- for(i=0; i<sizeof(p_quote->basename.name) && p_quote->basename.name[i];
- i++)
- {
- fprintf(OUTPUT, "%c", p_quote->basename.name[i]);
- }
- #ifdef __x86_64__
- fprintf(OUTPUT, "\n\tattributes.flags: 0x%0lx",
- p_quote->report_body.attributes.flags);
- fprintf(OUTPUT, "\n\tattributes.xfrm: 0x%0lx",
- p_quote->report_body.attributes.xfrm);
- #else
- fprintf(OUTPUT, "\n\tattributes.flags: 0x%0llx",
- p_quote->report_body.attributes.flags);
- fprintf(OUTPUT, "\n\tattributes.xfrm: 0x%0llx",
- p_quote->report_body.attributes.xfrm);
- #endif
- fprintf(OUTPUT, "\n\tmr_enclave: ");
- for(i=0;i<sizeof(sample_measurement_t);i++)
- {
- fprintf(OUTPUT, "%02x",p_quote->report_body.mr_enclave[i]);
- //fprintf(stderr, "%02x",p_quote->report_body.mr_enclave.m[i]);
- }
- fprintf(OUTPUT, "\n\tmr_signer: ");
- for(i=0;i<sizeof(sample_measurement_t);i++)
- {
- fprintf(OUTPUT, "%02x",p_quote->report_body.mr_signer[i]);
- //fprintf(stderr, "%02x",p_quote->report_body.mr_signer.m[i]);
- }
- fprintf(OUTPUT, "\n\tisv_prod_id: 0x%0x",
- p_quote->report_body.isv_prod_id);
- fprintf(OUTPUT, "\n\tisv_svn: 0x%0x",p_quote->report_body.isv_svn);
- fprintf(OUTPUT, "\n");
- // A product service provider needs to verify that its enclave properties
- // match what is expected. The SP needs to check these values before
- // trusting the enclave. For the sample, we always pass the policy check.
- // Attestation server only verifies the quote structure and signature. It does not
- // check the identity of the enclave.
- bool isv_policy_passed = true;
- // Assemble Attestation Result Message
- // Note, this is a structure copy. We don't copy the policy reports
- // right now.
- p_att_result_msg->platform_info_blob = attestation_report.info_blob;
- // Generate mac based on the mk key.
- mac_size = sizeof(ias_platform_info_blob_t);
- sample_ret = sample_rijndael128_cmac_msg(&g_sp_db.mk_key,
- (const uint8_t*)&p_att_result_msg->platform_info_blob,
- mac_size,
- &p_att_result_msg->mac);
- if(SAMPLE_SUCCESS != sample_ret)
- {
- fprintf(stderr, "\nError, cmac fail in [%s].", __FUNCTION__);
- ret = SP_INTERNAL_ERROR;
- break;
- }
- // Generate shared secret and encrypt it with SK, if attestation passed.
- uint8_t aes_gcm_iv[SAMPLE_SP_IV_SIZE] = {0};
- p_att_result_msg->secret.payload_size = 8;
- if((IAS_QUOTE_OK == attestation_report.status) &&
- (IAS_PSE_OK == attestation_report.pse_status) &&
- (isv_policy_passed == true))
- {
- ret = sample_rijndael128GCM_encrypt(&g_sp_db.sk_key,
- &g_secret[0],
- p_att_result_msg->secret.payload_size,
- p_att_result_msg->secret.payload,
- &aes_gcm_iv[0],
- SAMPLE_SP_IV_SIZE,
- NULL,
- 0,
- &p_att_result_msg->secret.payload_tag);
- }
- }while(0);
- if(ret)
- {
- *pp_att_result_msg = NULL;
- SAFE_FREE(p_att_result_msg_full);
- }
- else
- {
- // Freed by the network simulator in ra_free_network_response_buffer
- *pp_att_result_msg = p_att_result_msg_full;
- }
- return ret;
- }
|