/* * 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 #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;iprotocol != 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(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(PROVISION_RESPONSE_HEADER_SIZE), msg4_size - static_cast(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(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(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(local_ek2), field1.msg_buf, field1.msg_size, decoded_msg4, reinterpret_cast(block_cipher_tlv_get_iv(MSG4_TOP_FIELD_DATA)), IV_SIZE, reinterpret_cast(msg4_header), PROVISION_RESPONSE_HEADER_SIZE, reinterpret_cast(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(data_blob)); AESM_DBG_TRACE("PvE return %d in Process ProvMsg4",ret); }while(0); if(decoded_msg4)free(decoded_msg4); return ret; }