123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- /*
- * Copyright (C) 2011-2016 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 "type_length_value.h"
- #include "sgx_tcrypto_internal.h"
- #include <sgx_trts.h>
- #include "epid_utility.h"
- #include "aeerror.h"
- #include "PVEClass.h"
- #include "se_wrapper.h"
- #include "oal/internal_log.h"
- /**
- * File: epid_provision_msg4.cpp
- * Description: Provide the untrusted implementation of code to process ProvMsg4
- *
- * Untrusted Code for EPID Provision
- */
- #define MSG4_TOP_FIELDS_COUNT 3
- #define MSG4_TOP_FIELD_NONCE tlvs_msg4[0]
- #define MSG4_TOP_FIELD_DATA tlvs_msg4[1]
- #define MSG4_TOP_FIELD_MAC tlvs_msg4[2]
- #define MSG4_FIELD1_COUNT 6
- #define MSG4_FIELD1_DEVICE_ID tlvs_field1[5]
- #define MSG4_FIELD1_ENC_TCB tlvs_field1[0]
- #define MSG4_FIELD1_MAC_TCB tlvs_field1[1]
- #define MSG4_FIELD1_ENC_Axf tlvs_field1[2]
- #define MSG4_FIELD1_MAC_Axf tlvs_field1[3]
- #define MSG4_FIELD1_GROUP_CERT tlvs_field1[4]
- static ae_error_t msg4_integrity_checking(const TLVsMsg& tlvs_msg4)
- {
- uint32_t tlv_count = tlvs_msg4.get_tlv_count();
- if(tlv_count != MSG4_TOP_FIELDS_COUNT)
- return PVE_INTEGRITY_CHECK_ERROR;
- if(MSG4_TOP_FIELD_NONCE.type != TLV_NONCE || MSG4_TOP_FIELD_NONCE.size != NONCE_SIZE ||
- MSG4_TOP_FIELD_NONCE.version != TLV_VERSION_1 || MSG4_TOP_FIELD_NONCE.header_size != SMALL_TLV_HEADER_SIZE)
- return PVE_INTEGRITY_CHECK_ERROR;
- if(MSG4_TOP_FIELD_DATA.type != TLV_BLOCK_CIPHER_TEXT || MSG4_TOP_FIELD_DATA.version != TLV_VERSION_1)
- return PVE_INTEGRITY_CHECK_ERROR;
- if(MSG4_TOP_FIELD_MAC.type != TLV_MESSAGE_AUTHENTICATION_CODE || MSG4_TOP_FIELD_MAC.version != TLV_VERSION_1 ||
- MSG4_TOP_FIELD_MAC.size != MAC_SIZE || MSG4_TOP_FIELD_MAC.header_size != SMALL_TLV_HEADER_SIZE)
- return PVE_INTEGRITY_CHECK_ERROR;
- return AE_SUCCESS;
- }
- static ae_error_t msg4_field1_msg_checking(const TLVsMsg& tlvs_field1)
- {
- uint32_t tlv_count = tlvs_field1.get_tlv_count();
- if(tlv_count!=MSG4_FIELD1_COUNT){
- return PVE_MSG_ERROR;
- }
- uint32_t i;
- for(i=0;i<tlv_count;++i)
- if(tlvs_field1[i].version != TLV_VERSION_1)
- return PVE_MSG_ERROR;
- if(MSG4_FIELD1_GROUP_CERT.type != TLV_EPID_GROUP_CERT||
- MSG4_FIELD1_GROUP_CERT.size != sizeof(signed_epid_group_cert_t)||
- MSG4_FIELD1_GROUP_CERT.header_size != SMALL_TLV_HEADER_SIZE)
- return PVE_MSG_ERROR;
- if(MSG4_FIELD1_DEVICE_ID.type != TLV_DEVICE_ID ||
- MSG4_FIELD1_DEVICE_ID.size != sizeof(device_id_t)||
- MSG4_FIELD1_DEVICE_ID.header_size != SMALL_TLV_HEADER_SIZE)
- return PVE_MSG_ERROR;
- if(MSG4_FIELD1_ENC_TCB.type != TLV_BLOCK_CIPHER_TEXT||
- MSG4_FIELD1_ENC_TCB.size != BLOCK_CIPHER_TEXT_TLV_PAYLOAD_SIZE(SK_SIZE))
- return PVE_MSG_ERROR;
- if(MSG4_FIELD1_MAC_TCB.type != TLV_MESSAGE_AUTHENTICATION_CODE||
- MSG4_FIELD1_MAC_TCB.size != MAC_SIZE ||
- MSG4_FIELD1_MAC_TCB.header_size != SMALL_TLV_HEADER_SIZE)
- return PVE_MSG_ERROR;
- if(MSG4_FIELD1_ENC_Axf.type != TLV_BLOCK_CIPHER_TEXT||
- MSG4_FIELD1_ENC_Axf.size != BLOCK_CIPHER_TEXT_TLV_PAYLOAD_SIZE(HARD_CODED_EPID_MEMBER_WITH_ESCROW_TLV_SIZE))
- return PVE_MSG_ERROR;
- if(MSG4_FIELD1_MAC_Axf.type != TLV_MESSAGE_AUTHENTICATION_CODE||
- MSG4_FIELD1_MAC_Axf.size != MAC_SIZE||
- MSG4_FIELD1_MAC_Axf.header_size != SMALL_TLV_HEADER_SIZE)
- return PVE_MSG_ERROR;
- return AE_SUCCESS;
- }
- //Function to check message header of ProvMsg4 to determine whether it is valid
- //@msg4_header, input the message header of ProvMsg4
- //@return AE_SUCCESS if the message header is valid ProvMsg4 or error code if there're any problems
- static ae_error_t check_prov_msg4_header(const provision_response_header_t *msg4_header, uint32_t msg4_size)
- {
- if(msg4_header->protocol != SE_EPID_PROVISIONING || msg4_header->type != TYPE_PROV_MSG4 ||
- msg4_header->version != TLV_VERSION_1){
- return PVE_INTEGRITY_CHECK_ERROR;
- }
- uint32_t size_in_header = lv_ntohl(msg4_header->size);
- if(size_in_header + PROVISION_RESPONSE_HEADER_SIZE != msg4_size)
- return PVE_INTEGRITY_CHECK_ERROR;
- return AE_SUCCESS;
- }
- //Function to decode ProvMsg4 and generate epid data blob
- uint32_t CPVEClass::proc_prov_msg4(
- bool use_ek2_in_input,
- const uint8_t ek2[SK_SIZE],
- const uint8_t* msg4,
- uint32_t msg4_size,
- uint8_t* data_blob,
- uint32_t blob_size)
- {
- ae_error_t ret = AE_SUCCESS;
- uint8_t local_ek2[SK_SIZE];
- uint8_t *decoded_msg4 = NULL;
- const provision_response_header_t *msg4_header = reinterpret_cast<const provision_response_header_t *>(msg4);
- if(msg4_size < PROVISION_RESPONSE_HEADER_SIZE){
- AESM_DBG_ERROR("invalid msg4 size");
- return PVE_MSG_ERROR;
- }
- if(blob_size != HARD_CODED_EPID_BLOB_SIZE){
- AESM_DBG_FATAL("invalid input epid blob size");
- return PVE_PARAMETER_ERROR;
- }
- ret = check_prov_msg4_header(msg4_header, msg4_size);
- if( AE_SUCCESS != ret){
- AESM_DBG_ERROR("Invalid ProvMsg4 Header:%d",ret);
- return ret;
- }
- ret = check_epid_pve_pg_status_before_mac_verification(msg4_header);
- if( AE_SUCCESS != ret){
- AESM_DBG_ERROR("Backend return failure in ProvMsg4 Header:%d",ret);
- return ret;
- }
- do{
- TLVsMsg tlvs_msg4;
- tlv_status_t tlv_status;
- tlv_status = tlvs_msg4.init_from_buffer(msg4+static_cast<uint32_t>(PROVISION_RESPONSE_HEADER_SIZE), msg4_size - static_cast<uint32_t>(PROVISION_RESPONSE_HEADER_SIZE));
- ret = tlv_error_2_pve_error(tlv_status);
- if(AE_SUCCESS!=ret){
- AESM_DBG_ERROR("fail to decode ProvMsg4:%d",tlv_status);
- break;
- }
- ret = msg4_integrity_checking(tlvs_msg4);
- if(AE_SUCCESS != ret){
- AESM_DBG_ERROR("ProvMsg4 integrity checking error:%d",ret);
- break;
- }
- AESM_DBG_TRACE("ProvMsg4 decoded");
- if(!use_ek2_in_input){ //we need generate ek2
- prov_get_ek2_input_t ek2_input;
- if(memcpy_s(ek2_input.nonce, NONCE_SIZE, MSG4_TOP_FIELD_NONCE.payload, NONCE_SIZE)!=0){
- AESM_DBG_ERROR("fail in memcpy");
- ret = PVE_UNEXPECTED_ERROR;
- break;
- }
- if(memcpy_s(ek2_input.xid, XID_SIZE, msg4_header->xid, XID_SIZE)!=0){
- AESM_DBG_ERROR("fail in memcpy");
- ret = PVE_UNEXPECTED_ERROR;
- break;
- }
- //call PvE to get EK2
- se_static_assert(SK_SIZE == sizeof(prov_get_ek2_output_t));
- ret = (ae_error_t)get_ek2(&ek2_input, reinterpret_cast<prov_get_ek2_output_t *>(local_ek2));
- if(AE_SUCCESS != ret){
- AESM_DBG_ERROR("fail to get EK2:%d",ret);
- break;
- }
- }else{//reuse ek2 generated in processing ProvMsg2
- if(0!=memcpy_s(local_ek2, sizeof(local_ek2), ek2, SK_SIZE)){
- AESM_DBG_ERROR("fail in memcpy");
- ret = PVE_UNEXPECTED_ERROR;
- break;
- }
- }
- se_static_assert(SK_SIZE==sizeof(sgx_aes_gcm_128bit_key_t));
- tlv_msg_t field1 = block_cipher_tlv_get_encrypted_text(MSG4_TOP_FIELD_DATA);
- decoded_msg4 = reinterpret_cast<uint8_t *>(malloc(field1.msg_size));
- if(NULL == decoded_msg4){
- AESM_DBG_ERROR("malloc error");
- ret = AE_OUT_OF_MEMORY_ERROR;
- break;
- }
- sgx_status_t sgx_status = sgx_rijndael128GCM_decrypt(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(local_ek2),
- field1.msg_buf, field1.msg_size, decoded_msg4,
- reinterpret_cast<uint8_t *>(block_cipher_tlv_get_iv(MSG4_TOP_FIELD_DATA)), IV_SIZE,
- reinterpret_cast<const uint8_t *>(msg4_header), PROVISION_RESPONSE_HEADER_SIZE,
- reinterpret_cast<const sgx_aes_gcm_128bit_tag_t *>(MSG4_TOP_FIELD_MAC.payload));
- if(SGX_ERROR_MAC_MISMATCH == sgx_status){
- AESM_DBG_ERROR("fail to decrypt ProvMsg4 by EK2");
- ret = PVE_INTEGRITY_CHECK_ERROR;
- break;
- }
- if( AE_SUCCESS != (ret = sgx_error_to_ae_error(sgx_status))){
- AESM_DBG_ERROR("error in decrypting ProvMsg4:%d",sgx_status);
- break;
- }
- AESM_DBG_TRACE("ProvMsg4 decrypted by EK2 successfully");
- ret = check_epid_pve_pg_status_after_mac_verification(msg4_header);
- if(AE_SUCCESS != ret){
- AESM_DBG_ERROR("Backend reported error passed MAC verification:%d",ret);
- break;
- }
- TLVsMsg tlvs_field1;
- tlv_status = tlvs_field1.init_from_buffer(decoded_msg4, field1.msg_size);
- ret = tlv_error_2_pve_error(tlv_status);
- if(AE_SUCCESS != ret){
- AESM_DBG_ERROR("ProvMsg4 Field2.1 decoding failed:%d",tlv_status);
- break;
- }
- ret = msg4_field1_msg_checking(tlvs_field1);
- if( AE_SUCCESS != ret){
- AESM_DBG_ERROR("ProvMsg4 Field2.1 invalid:%d",ret);
- break;
- }
- proc_prov_msg4_input_t msg4_input;
- if(sizeof(proc_prov_msg4_output_t)!=SGX_TRUSTED_EPID_BLOB_SIZE){
- AESM_DBG_FATAL("Trusted ProvMsg4 output buffer size error");
- ret = PVE_UNEXPECTED_ERROR;
- break;
- }
- tlv_msg_t tcb_data = block_cipher_tlv_get_encrypted_text(MSG4_FIELD1_ENC_TCB);
- tlv_msg_t Axf_data = block_cipher_tlv_get_encrypted_text(MSG4_FIELD1_ENC_Axf);
- if(0!=memcpy_s(&msg4_input.group_cert, sizeof(msg4_input.group_cert), MSG4_FIELD1_GROUP_CERT.payload, MSG4_FIELD1_GROUP_CERT.size)||
- 0!=memcpy_s(&msg4_input.equivalent_psvn, sizeof(psvn_t), device_id_tlv_get_psvn(MSG4_FIELD1_DEVICE_ID), sizeof(psvn_t))||
- 0!=memcpy_s(&msg4_input.fmsp, sizeof(fmsp_t), device_id_tlv_get_fmsp(MSG4_FIELD1_DEVICE_ID), sizeof(fmsp_t))||
- 0!=memcpy_s(&msg4_input.tcb_iv, IV_SIZE, block_cipher_tlv_get_iv(MSG4_FIELD1_ENC_TCB), IV_SIZE)||
- 0!=memcpy_s(&msg4_input.encrypted_tcb, SK_SIZE, tcb_data.msg_buf, tcb_data.msg_size)||
- 0!=memcpy_s(&msg4_input.tcb_mac, MAC_SIZE, MSG4_FIELD1_MAC_TCB.payload, MSG4_FIELD1_MAC_TCB.size)||
- 0!=memcpy_s(&msg4_input.member_credential_iv, IV_SIZE, block_cipher_tlv_get_iv(MSG4_FIELD1_ENC_Axf), IV_SIZE)||
- 0!=memcpy_s(&msg4_input.encrypted_member_credential, HARD_CODED_EPID_MEMBER_WITH_ESCROW_TLV_SIZE, Axf_data.msg_buf, Axf_data.msg_size)||
- 0!=memcpy_s(&msg4_input.member_credential_mac, MAC_SIZE, MSG4_FIELD1_MAC_Axf.payload, MSG4_FIELD1_MAC_Axf.size)){
- AESM_DBG_ERROR("memcpy error");
- ret = PVE_UNEXPECTED_ERROR;
- break;
- }
- ret = (ae_error_t)proc_prov_msg4_data(&msg4_input, reinterpret_cast<proc_prov_msg4_output_t *>(data_blob));
- AESM_DBG_TRACE("PvE return %d in Process ProvMsg4",ret);
- }while(0);
- if(decoded_msg4)free(decoded_msg4);
- return ret;
- }
|