/* * 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 "provision_msg.h" #include "type_length_value.h" #include #include "PVEClass.h" #include "aesm_rand.h" #include "se_wrapper.h" #include "epid_utility.h" #include "prof_fun.h" #include "oal/internal_log.h" #include static ae_error_t prov_es_gen_header(provision_request_header_t *es_header, const uint8_t *xid, uint32_t msg_buffer_size) { uint32_t total_size = 0; total_size = ES_SELECTOR_TLV_SIZE(); //initialize ES Msg1 Header es_header->protocol = ENDPOINT_SELECTION; es_header->type = TYPE_ES_MSG1; es_header->version = TLV_VERSION_1; if(0!=memcpy_s(es_header->xid, XID_SIZE, xid, XID_SIZE)){ AESM_DBG_FATAL("memcpy error"); return PVE_UNEXPECTED_ERROR; } uint32_t size_in; size_in = _htonl(total_size);//big endian size required in msg header if(0!=memcpy_s(&es_header->size,sizeof(es_header->size), &size_in, sizeof(size_in))){ AESM_DBG_FATAL("memcpy error"); return PVE_UNEXPECTED_ERROR; } if(total_size +sizeof(*es_header) >msg_buffer_size){//the input msg body buffer size is not large enough AESM_DBG_ERROR("input msg buffer is too small"); return PVE_INSUFFICIENT_MEMORY_ERROR; } return AE_SUCCESS; } uint32_t CPVEClass::gen_es_msg1( uint8_t *msg, uint32_t msg_size, const gen_endpoint_selection_output_t& es_output) { ae_error_t ret; AESM_PROFILE_FUN; if(msg_size < PROVISION_REQUEST_HEADER_SIZE) return PVE_INSUFFICIENT_MEMORY_ERROR; provision_request_header_t *es_header = reinterpret_cast(msg); ret = prov_es_gen_header(es_header, es_output.xid, msg_size); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("Fail to generate Endpoint Selection Msg1 Header:%d",ret); return ret; } { TLVsMsg tlvs_msg; tlv_status_t tlv_status = tlvs_msg.add_es_selector(SE_EPID_PROVISIONING, es_output.selector_id); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS!=ret){ AESM_DBG_ERROR("fail to create ES Selector TLV:%d",ret); return ret; } assert(tlvs_msg.get_tlv_msg_size()<=msg_size - PROVISION_REQUEST_HEADER_SIZE); //The checking should have been done in prov_es_gen_header if(0!=memcpy_s(msg+PROVISION_REQUEST_HEADER_SIZE, msg_size-PROVISION_REQUEST_HEADER_SIZE, tlvs_msg.get_tlv_msg(), tlvs_msg.get_tlv_msg_size())){ AESM_DBG_FATAL("memcpy failed"); return PVE_UNEXPECTED_ERROR; } return AE_SUCCESS; } } #define ES_MSG2_FIELD_COUNT 3 #define ES_FIELD0_MIN_SIZE 3 #define ES_FIELD0_MAX_SIZE (MAX_PATH-1) uint32_t CPVEClass::proc_es_msg2( const uint8_t *msg, uint32_t msg_size, char server_url[MAX_PATH], uint16_t& ttl, const uint8_t xid[XID_SIZE], uint8_t rsa_signature[PVE_RSA_KEY_BYTES], signed_pek_t& pek) { uint32_t ae_ret = PVE_MSG_ERROR; TLVsMsg tlvs_msg; AESM_PROFILE_FUN; tlv_status_t tlv_status; uint16_t time_in_net; const provision_response_header_t *resp_header = (const provision_response_header_t *)msg; const uint8_t *resp_body = msg + PROVISION_RESPONSE_HEADER_SIZE; if(msg_sizeprotocol != ENDPOINT_SELECTION || resp_header->version!=TLV_VERSION_1 || resp_header->type != TYPE_ES_MSG2){ AESM_DBG_ERROR("ES Msg2 header error"); goto final_point; } ae_ret = check_endpoint_pg_stauts(resp_header); if(AE_SUCCESS != ae_ret){ AESM_DBG_ERROR("Backend report error in ES Msg2 Header:%d",ae_ret); goto final_point; } if(0!=memcmp(xid, resp_header->xid, XID_SIZE)){ AESM_DBG_ERROR("XID in ES Msg2 header doesn't match the one in ES Msg1"); ae_ret = PVE_MSG_ERROR; goto final_point; } uint32_t size; size = GET_BODY_SIZE_FROM_PROVISION_RESPONSE(msg); if(size + PROVISION_RESPONSE_HEADER_SIZE != msg_size){ //size information inconsistent AESM_DBG_ERROR("message size inconsistent in ES Msg2"); ae_ret = PVE_MSG_ERROR; goto final_point; } tlv_status = tlvs_msg.init_from_buffer(resp_body, msg_size - static_cast(PROVISION_RESPONSE_HEADER_SIZE)); ae_ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS!=ae_ret){ AESM_DBG_ERROR("Fail to decode ES Msg2:%d",ae_ret); goto final_point; } if(tlvs_msg.get_tlv_count() != ES_MSG2_FIELD_COUNT){//three TLVs AESM_DBG_ERROR("Invaid number of TLV in ES Msg2"); ae_ret = PVE_MSG_ERROR; goto final_point; } if(tlvs_msg[0].type != TLV_ES_INFORMATION || tlvs_msg[0].version != TLV_VERSION_1 || tlvs_msg[0].header_size != SMALL_TLV_HEADER_SIZE){//TLV header checking AESM_DBG_ERROR("Invalid TLV in ES Msg2"); ae_ret = PVE_MSG_ERROR; goto final_point; } if(tlvs_msg[0].sizeES_FIELD0_MAX_SIZE){//size checking AESM_DBG_ERROR("Invalid TLV in ES Msg2"); ae_ret = PVE_MSG_ERROR; goto final_point; } if(tlvs_msg[1].type != TLV_SIGNATURE || tlvs_msg[1].version != TLV_VERSION_1 || tlvs_msg[1].header_size!=SMALL_TLV_HEADER_SIZE||tlvs_msg[1].size != PVE_RSA_KEY_BYTES+1 || tlvs_msg[1].payload[0] != PEK_PRIV){ ae_ret = PVE_MSG_ERROR; AESM_DBG_ERROR("Invalid Signature TLV: type %d, version %d, size %d while expected value is %d, %d, %d", tlvs_msg[1].type, tlvs_msg[1].version, tlvs_msg[1].size, TLV_SIGNATURE, TLV_VERSION_1, PVE_RSA_KEY_BYTES); goto final_point; } if(tlvs_msg[2].type != TLV_PEK || tlvs_msg[2].version != TLV_VERSION_1 || tlvs_msg[2].header_size!=SMALL_TLV_HEADER_SIZE||tlvs_msg[2].size != sizeof(signed_pek_t)){ ae_ret = PVE_MSG_ERROR; AESM_DBG_ERROR("Invalid PEK TLV: type %d, version %d, size %d while expected value is %d, %d, %d", tlvs_msg[2].type, tlvs_msg[2].version, tlvs_msg[2].size, TLV_PEK, TLV_VERSION_1, sizeof(signed_pek_t)); goto final_point; } //skip the byte for KEY_ID if(memcpy_s(rsa_signature, PVE_RSA_KEY_BYTES, tlvs_msg[1].payload+1, tlvs_msg[1].size-1)!=0){ ae_ret = AE_FAILURE; AESM_DBG_ERROR("memcpy failed"); goto final_point; } if(memcpy_s(&pek, sizeof(pek), tlvs_msg[2].payload, tlvs_msg[2].size)!=0){ ae_ret = AE_FAILURE; AESM_DBG_ERROR("memcpy failed"); goto final_point; } time_in_net = *(uint16_t *)tlvs_msg[0].payload;//TTL in ES ttl = lv_ntohs(time_in_net);//First two bytes in payload for TTL (maximal seconds that the URL to be valid) if(memcpy_s(server_url, MAX_PATH, tlvs_msg[0].payload+2, tlvs_msg[0].size-2)!=0){//other bytes for URL ae_ret = AE_FAILURE; AESM_DBG_ERROR("memcpy failed"); goto final_point; } server_url[tlvs_msg[0].size-2]='\0'; ae_ret = AE_SUCCESS; final_point: return ae_ret; }