ae_error_t CertificateProvisioningProtocol::check_response_status(const  provision_response_header_t& msg2_header)
{
    ae_error_t status = PVE_SERVER_REPORTED_ERROR;

    do
    {
        generalResponseStatus = static_cast<general_response_status_t>(lv_ntohs(msg2_header.gstatus));
        protocolResponseStatus = static_cast<pse_protocol_response_status_t>(lv_ntohs(msg2_header.pstatus));

        // gstatus: GRS_OK, GRS_SERVER_BUSY, GRS_INTEGRITY_CHECK_FAIL, GRS_INCORRECT_SYNTAX,
        //          GRS_INCOMPATIBLE_VERSION, GRS_TRANSACTION_STATE_LOST, GRS_PROTOCOL_ERROR, GRS_INTERNAL_ERROR
        // pstatus: PSE_PRS_OK, PSE_PRS_INVALID_GID, PSE_PRS_GID_REVOKED, PSE_PRS_INVALID_QUOTE, PSE_PRS_INVALID_REQUEST

        if (protocolResponseStatus != PSE_PRS_OK || generalResponseStatus != GRS_OK)
            break;

        status = AE_SUCCESS;
    } while (0);

    return status;
}
ae_error_t PlatformInfoLogic::get_pse_evaluation_flags(const platform_info_blob_wrapper_t* p_platform_info_blob, uint16_t* pflags)
{
    ae_error_t retval = AE_SUCCESS;
    if (NULL != pflags && NULL != p_platform_info_blob && p_platform_info_blob->valid_info_blob) {
        const uint16_t* p = reinterpret_cast<const uint16_t*>(p_platform_info_blob->platform_info_blob.pse_evaluation_flags);
        *pflags = lv_ntohs(*p);
    }
    else {
        retval = AE_INVALID_PARAMETER;
    }
    return retval;
}
uint16_t PlatformInfoLogic::latest_pse_svn(const platform_info_blob_wrapper_t* p_platform_info_blob)
{
    uint16_t pse_svn = 0;
    // value of latest psda svn in platform info blob
    if (NULL != p_platform_info_blob && p_platform_info_blob->valid_info_blob)
    {
        //pse_svn = *((uint16_t*)p_platform_info_blob->platform_info_blob.latest_pse_isvsvn);
        const uint16_t* p = reinterpret_cast<const uint16_t*>(p_platform_info_blob->platform_info_blob.latest_pse_isvsvn);
        pse_svn = lv_ntohs(*p);
    }

    SGX_DBGPRINT_ONE_STRING_TWO_INTS_CREATE_SESSION(__FUNCTION__" returning ", pse_svn, pse_svn);
    return pse_svn;
}
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_size<PROVISION_RESPONSE_HEADER_SIZE){//at least response header is available
        AESM_DBG_ERROR("Endpoint selection Msg2 buffer size too small");
        goto final_point;
    }
    //first checking resp header for protocol, version and type
    if(resp_header->protocol != 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<uint32_t>(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].size<ES_FIELD0_MIN_SIZE||tlvs_msg[0].size>ES_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;
}