コード例 #1
0
ファイル: aesm_logic.cpp プロジェクト: 0-T-0/linux-sgx
// Must be called when AESM starts
ae_error_t AESMLogic::service_start()
{
    AESM_PROFILE_INIT;
    ae_error_t ae_ret = AE_SUCCESS;

    AESM_LOG_INIT();

    //ippInit();//no ippInit available for c version ipp
    AESM_DBG_INFO("aesm service is starting");
    ae_ret = CLEClass::instance().load_enclave();
    if(AE_SUCCESS != ae_ret)
    {
        AESM_DBG_INFO("fail to load LE: %d", ae_ret);
        AESM_LOG_FATAL("%s", g_event_string_table[SGX_EVENT_SERVICE_UNAVAILABLE]);

        return ae_ret;
    }

    aesm_thread_t qe_thread=NULL;
    ae_error_t aesm_ret1 = aesm_create_thread(thread_to_load_qe, 0,&qe_thread);
    if(AE_SUCCESS != aesm_ret1 ){
        AESM_DBG_WARN("Fail to create thread to preload QE:%d",aesm_ret1);
    }else{
        (void)aesm_free_thread(qe_thread);//release thread handle to free memory
    }
        
    AESM_DBG_TRACE("aesm service is started");

    return AE_SUCCESS;
}
コード例 #2
0
ae_error_t CertificateProvisioningProtocol::sendReceive(const upse::Buffer& sendSerialized, upse::Buffer& recvSerialized)
{
    ae_error_t status = AE_FAILURE;

    uint8_t* recv = NULL;
    uint32_t recv_size = 0;

    do
    {
        AESM_DBG_INFO("start send msg");
	    status = AESMNetworkEncoding::aesm_send_recv_msg_encoding(m_url.c_str(), const_cast<uint8_t *>(sendSerialized.getData()), sendSerialized.getSize(), recv, recv_size);
	    if (AE_FAILED(status))
            break;
        AESM_DBG_INFO("msg received with size %u", recv_size);

        status = recvSerialized.Alloc(recv_size);
        if (AE_FAILED(status))
            break;
        AESM_DBG_INFO("buffer alloced");
        status = upse::BufferWriter(recvSerialized).writeRaw(recv, recv_size);
        if (AE_FAILED(status))
            break;
        AESM_DBG_INFO("buffer written");
        status = AE_SUCCESS;

    } while (0);

    if (NULL != recv)
        AESMNetworkEncoding::aesm_free_response_msg(recv);

    return status;
}
コード例 #3
0
ファイル: aesm_logic.cpp プロジェクト: 0-T-0/linux-sgx
aesm_error_t AESMLogic::get_quote(const uint8_t *report, uint32_t report_size,
                             uint32_t quote_type,
                             const uint8_t *spid, uint32_t spid_size,
                             const uint8_t *nonce, uint32_t nonce_size,
                             const uint8_t *sigrl, uint32_t sigrl_size,
                             uint8_t *qe_report, uint32_t qe_report_size,
                             uint8_t *quote, uint32_t buf_size)
{
    AESM_DBG_INFO("get_quote");
    if(sizeof(sgx_report_t) != report_size ||
       sizeof(sgx_spid_t) != spid_size)
    {
        return AESM_PARAMETER_ERROR;
    }
    if((nonce && sizeof(sgx_quote_nonce_t) != nonce_size)
        || (qe_report && sizeof(sgx_report_t) != qe_report_size))

    {
        return AESM_PARAMETER_ERROR;
    }
    AESMLogicLock lock(_qe_pve_mutex);
    CHECK_EPID_PROVISIONG_STATUS;
    return QEAESMLogic::get_quote(report, quote_type, spid, nonce, sigrl,
                                  sigrl_size, qe_report, quote, buf_size);
}
コード例 #4
0
ファイル: aesm_logic.cpp プロジェクト: 0-T-0/linux-sgx
aesm_error_t AESMLogic::init_quote(
    uint8_t *target_info, uint32_t target_info_size,
    uint8_t *gid, uint32_t gid_size)
{
    ae_error_t ret = AE_SUCCESS;
    uint16_t qe_isv_svn = 0xFFFF;
    sgx_cpu_svn_t qe_cpu_svn;
    memset(&qe_cpu_svn, 0, sizeof(qe_cpu_svn));
    AESM_DBG_INFO("init_quote");
    if(sizeof(sgx_target_info_t) != target_info_size ||
       sizeof(sgx_epid_group_id_t) != gid_size)
    {
        return AESM_PARAMETER_ERROR;
    }
    AESMLogicLock lock(_qe_pve_mutex);
    CHECK_EPID_PROVISIONG_STATUS;
    ret = get_qe_cpu_svn(qe_cpu_svn);
    if(AE_SUCCESS != ret)
    {
        return AESM_UNEXPECTED_ERROR;
    }
    ret = get_qe_isv_svn(qe_isv_svn);
    if(AE_SUCCESS != ret)
    {
        return AESM_UNEXPECTED_ERROR;
    }
    return QEAESMLogic::init_quote(
               reinterpret_cast<sgx_target_info_t *>(target_info),
               gid, gid_size, qe_isv_svn, qe_cpu_svn);
}
コード例 #5
0
ファイル: aesm_logic.cpp プロジェクト: 0-T-0/linux-sgx
/* This function will be called outside aesm(from urts_internal) */
extern "C" sgx_status_t get_launch_token(const enclave_css_t* signature,
                                         const sgx_attributes_t* attribute,
                                         sgx_launch_token_t* launch_token)
{
    AESM_DBG_INFO("enter function");
    return AESMLogic::get_launch_token(signature, attribute, launch_token);
}
コード例 #6
0
ファイル: aesm_logic.cpp プロジェクト: 0-T-0/linux-sgx
aesm_error_t AESMLogic::get_launch_token(
    const uint8_t * mrenclave, uint32_t mrenclave_size,
    const uint8_t *public_key, uint32_t public_key_size,
    const uint8_t *se_attributes, uint32_t se_attributes_size,
    uint8_t * lictoken, uint32_t lictoken_size)
{
    AESM_DBG_INFO("enter function");

    CHECK_SERVICE_STATUS;
    AESMLogicLock lock(_le_mutex);
    CHECK_SERVICE_STATUS;

    ae_error_t ret_le = AE_SUCCESS;
    if (NULL == mrenclave ||
        NULL == public_key ||
        NULL == se_attributes ||
        NULL == lictoken)
    {
        //sizes are checked in CLEClass::get_launch_token()
        AESM_DBG_TRACE("Invalid parameter");
        return AESM_PARAMETER_ERROR;
    }
    ae_error_t ae_ret = CLEClass::instance().load_enclave();
    if(ae_ret == AE_SERVER_NOT_AVAILABLE)
    {
        AESM_LOG_ERROR("%s", g_event_string_table[SGX_EVENT_SERVICE_UNAVAILABLE]);
        AESM_DBG_FATAL("LE not loaded due to AE_SERVER_NOT_AVAILABLE, possible SGX Env Not Ready");
        return AESM_NO_DEVICE_ERROR;
    }
    else if(AE_FAILED(ae_ret))
    {
        AESM_DBG_ERROR("LE not loaded:%d", ae_ret);
        return AESM_UNEXPECTED_ERROR;
    }
    ret_le = static_cast<ae_error_t>(CLEClass::instance().get_launch_token(
        const_cast<uint8_t *>(mrenclave), mrenclave_size,
        const_cast<uint8_t *>(public_key), public_key_size,
        const_cast<uint8_t *>(se_attributes), se_attributes_size,
        lictoken, lictoken_size));

    switch (ret_le)
    {
    case AE_SUCCESS:
        return AESM_SUCCESS;
    case LE_INVALID_PARAMETER:
        AESM_DBG_TRACE("Invalid parameter");
        return AESM_PARAMETER_ERROR;
    case LE_INVALID_ATTRIBUTE:
    case LE_INVALID_PRIVILEGE_ERROR:
        AESM_DBG_TRACE("Launch token error");
        return AESM_GET_LICENSETOKEN_ERROR;
    case LE_WHITELIST_UNINITIALIZED_ERROR:
        AESM_DBG_TRACE("LE whitelist uninitialized error");
        return AESM_UNEXPECTED_ERROR;
    default:
        AESM_DBG_WARN("unexpeted error %d", ret_le);
        return AESM_UNEXPECTED_ERROR;
    }
}
コード例 #7
0
ファイル: aesm_logic.cpp プロジェクト: 0-T-0/linux-sgx
aesm_error_t AESMLogic::report_attestation_status(
        uint8_t* platform_info, uint32_t platform_info_size,
        uint32_t attestation_status,
        uint8_t* update_info, uint32_t update_info_size)
{
    AESM_DBG_INFO("report_attestation_status");
    AESMLogicLock lock(_pse_mutex);
    return PlatformInfoLogic::report_attestation_status(platform_info, platform_info_size, attestation_status, update_info, update_info_size);
}
コード例 #8
0
//
// return values
// NEED_PSE_UPDATE: pse out of date, cert matches pse
// SUCCESS: have new cert
// PSE_CERT_PROVISIONING_ATTESTATION_FAILURE_NEED_EPID_UPDATE:
// PSE_CERT_PROVISIONING_ATTESTATION_FAILURE_MIGHT_NEED_EPID_UPDATE:
// SIMPLE_PSE_CERT_PROVISIONING_ERROR: internal error during cert provisioning
// SIMPLE_EPID_PROVISION_ERROR: internal error during epid provisioning during cert provisioning
//
ae_error_t PlatformInfoLogic::pse_cert_provisioning_helper(const platform_info_blob_wrapper_t* p_platform_info_blob)
{
    AESM_DBG_TRACE("enter fun");
    ae_error_t status = AESM_NPC_DONT_NEED_PSEP;

    ae_error_t npcStatus = need_pse_cert_provisioning();
    switch (npcStatus)
    {
    default:
    {
        assert(false); break;
    }
    case AESM_NPC_DONT_NEED_PSEP:
    {
        status = AESM_PCP_NEED_PSE_UPDATE;
        break;
    }
    case AESM_NPC_NO_PSE_CERT:
    {
        platform_info_blob_wrapper_t new_platform_info_blob;
        new_platform_info_blob.valid_info_blob = 0;
        AESM_DBG_INFO("helper; redo certificate provisioning");
        ae_error_t cpStatus = CPSEPRClass::instance().certificate_provisioning(&new_platform_info_blob);
        SGX_DBGPRINT_ONE_STRING_TWO_INTS_CREATE_SESSION("cpStatus = ", cpStatus, cpStatus);

        switch (cpStatus)
        {
        case AE_SUCCESS:
        case OAL_PROXY_SETTING_ASSIST:
        case PSW_UPDATE_REQUIRED:
        case AESM_AE_OUT_OF_EPC:
        case OAL_NETWORK_UNAVAILABLE_ERROR:
        {
            status = cpStatus;
            break;
        }
        case AESM_CP_ATTESTATION_FAILURE:
        {
            status = attestation_failure_in_pse_cert_provisioning(p_platform_info_blob);
            break;
        }

        default:
        {
            status = AESM_PCP_SIMPLE_PSE_CERT_PROVISIONING_ERROR;
            break;
        }
        }
        break;
    }
    }

    SGX_DBGPRINT_ONE_STRING_TWO_INTS_CREATE_SESSION(__FUNCTION__" returning ", status, status);
    return status;
}
コード例 #9
0
ファイル: aesm_logic.cpp プロジェクト: 0-T-0/linux-sgx
void AESMLogic::service_stop()
{
    CPVEClass::instance().unload_enclave();
    CQEClass::instance().unload_enclave();
    CLEClass::instance().unload_enclave();
    stop_all_long_lived_threads();
    AESM_DBG_INFO("aesm service down");
    AESM_LOG_FINI();

    AESM_PROFILE_OUTPUT;
}
コード例 #10
0
//Function to read urls from configure files
ae_error_t EndpointSelectionInfo::get_url_info()
{
    ae_error_t ae_err=AE_SUCCESS;
    uint32_t server_urls_size = sizeof(_server_urls);

    ae_err = aesm_read_data(FT_PERSISTENT_STORAGE, AESM_SERVER_URL_FID, reinterpret_cast<uint8_t *>(&_server_urls), &server_urls_size, AESMLogic::get_active_extended_epid_group_id());

    if(AE_SUCCESS != ae_err || 
        server_urls_size != sizeof(_server_urls)||
        !is_valid_server_url_infos(_server_urls)){ //If fail to read or data format error, use default value
            _is_server_url_valid = false;
            if(AE_SUCCESS == ae_err){//File available but format error, report ERROR LOG
                AESM_LOG_WARN("Server URL Blob file format error");
                AESM_DBG_INFO("fail to read server url info from persistent storage, error code (%d), size %d, expected size %d",
                    ae_err, server_urls_size, sizeof(_server_urls));
                ae_err = OAL_CONFIG_FILE_ERROR;
            }else{
                AESM_DBG_INFO("server url blob file not available in persistent storage");
            }
            if (AESMLogic::get_active_extended_epid_group_id() == DEFAULT_EGID){
                if (strcpy_s(_server_urls.endpoint_url, MAX_PATH, DEFAULT_URL) != 0)
                    return AE_FAILURE;
                if (strcpy_s(_server_urls.pse_rl_url, MAX_PATH, DEFAULT_PSE_RL_URL) != 0)
                    return AE_FAILURE;
                if (strcpy_s(_server_urls.pse_ocsp_url, MAX_PATH, DEFAULT_PSE_OCSP_URL) != 0)
                    return AE_FAILURE;
                _is_server_url_valid = true;
                return AE_SUCCESS;
            }
            else{
                return ae_err;
            }
    }

    _is_server_url_valid = true;
    return AE_SUCCESS;
}
コード例 #11
0
ファイル: aesm_logic.cpp プロジェクト: 0-T-0/linux-sgx
aesm_error_t AESMLogic::white_list_register(
        const uint8_t *white_list_cert, uint32_t white_list_cert_size)
{
    AESM_DBG_INFO("enter function");
    CHECK_SERVICE_STATUS;
    AESMLogicLock lock(_le_mutex);
    CHECK_SERVICE_STATUS;
    ae_error_t ret_le = AE_SUCCESS;
    if (NULL == white_list_cert||0==white_list_cert_size){
        AESM_DBG_TRACE("Invalid parameter");
        return AESM_PARAMETER_ERROR;
    }
    ae_error_t ae_ret = CLEClass::instance().load_enclave();
    if(ae_ret == AE_SERVER_NOT_AVAILABLE)
    {
        AESM_DBG_WARN("LE not loaded due to AE_SERVER_NOT_AVAILABLE, possible SGX Env Not Ready");
        ret_le = save_unverified_white_list(white_list_cert, white_list_cert_size);
    }
    else if(AE_FAILED(ae_ret))
    {
        AESM_DBG_ERROR("LE not loaded:%d", ae_ret);
        return AESM_UNEXPECTED_ERROR;
    }else{
        ret_le = static_cast<ae_error_t>(CLEClass::instance().white_list_register(
            white_list_cert, white_list_cert_size));
    }

    switch (ret_le)
    {
    case AE_SUCCESS:
        return AESM_SUCCESS;
    case LE_INVALID_PARAMETER:
        AESM_DBG_TRACE("Invalid parameter");
        return AESM_PARAMETER_ERROR;
    case LE_INVALID_ATTRIBUTE:
        AESM_DBG_TRACE("Launch token error");
        return AESM_GET_LICENSETOKEN_ERROR;
    default:
        AESM_DBG_WARN("unexpeted error %d", ret_le);
        return AESM_UNEXPECTED_ERROR;
    }
}
コード例 #12
0
ae_error_t EndpointSelectionInfo::read_pek(endpoint_selection_infos_t& es_info)
{
    ae_error_t ae_err=AE_SUCCESS;
    uint32_t es_info_size = sizeof(es_info);

    ae_err = aesm_read_data(FT_PERSISTENT_STORAGE, PROVISION_PEK_BLOB_FID, reinterpret_cast<uint8_t *>(&es_info), &es_info_size);

    if(AE_SUCCESS == ae_err && (es_info_size != sizeof(es_info)||!is_valid_endpoint_selection_info(es_info))){
        AESM_DBG_ERROR("Invalid ES result in persistent storage:size %d, expected size %d", es_info_size, sizeof(es_info));
        ae_err = OAL_FILE_ACCESS_ERROR;
    }

    if(AE_SUCCESS == ae_err){
        AESM_DBG_INFO("Read ES result from persistent storage successfully");
    }else{
        AESM_DBG_WARN("ES result in persistent storage failed to load:%d", ae_err);
    }

    return ae_err;
}
コード例 #13
0
ファイル: aesm_logic.cpp プロジェクト: 0-T-0/linux-sgx
sgx_status_t AESMLogic::get_launch_token(const enclave_css_t* signature,
                                         const sgx_attributes_t* attribute,
                                         sgx_launch_token_t* launch_token)
{
    AESM_DBG_INFO("enter function");
    AESMLogicLock lock(_le_mutex);

    ae_error_t ret_le = AE_SUCCESS;
    // load LE to get launch token
    if((ret_le=CLEClass::instance().load_enclave()) != AE_SUCCESS)
    {
        if(ret_le == AE_SERVER_NOT_AVAILABLE)
        {
            AESM_DBG_FATAL("LE not loaded due to AE_SERVER_NOT_AVAILABLE, possible SGX Env Not Ready");
            return SGX_ERROR_NO_DEVICE;
        }
        AESM_DBG_FATAL("fail to load LE:%d",ret_le);
        return SGX_ERROR_UNEXPECTED;
    }


    ret_le = static_cast<ae_error_t>(CLEClass::instance().get_launch_token(
        const_cast<uint8_t*>(reinterpret_cast<const uint8_t *>(&signature->body.enclave_hash)),
        sizeof(sgx_measurement_t),
        const_cast<uint8_t*>(reinterpret_cast<const uint8_t *>(&signature->key.modulus)),
        sizeof(signature->key.modulus),
        const_cast<uint8_t*>(reinterpret_cast<const uint8_t *>(attribute)),
        sizeof(sgx_attributes_t),
        reinterpret_cast<uint8_t*>(launch_token),
        sizeof(token_t)));
    switch (ret_le)
    {
    case AE_SUCCESS:
        break;
    case LE_INVALID_PARAMETER:
        AESM_DBG_TRACE("Invalid parameter");
        return SGX_ERROR_INVALID_PARAMETER;
    case LE_INVALID_ATTRIBUTE:
    case LE_INVALID_PRIVILEGE_ERROR:
        AESM_DBG_TRACE("Launch token error");
        return SGX_ERROR_SERVICE_INVALID_PRIVILEGE;
    case LE_WHITELIST_UNINITIALIZED_ERROR:
        AESM_DBG_TRACE("LE whitelist uninitialized error");
        return SGX_ERROR_UNEXPECTED;
    default:
        AESM_DBG_WARN("unexpeted error %d", ret_le);
        return SGX_ERROR_UNEXPECTED;
    }

    token_t *lt = reinterpret_cast<token_t *>(launch_token);
    ret_le = set_psvn(signature->body.isv_prod_id, signature->body.isv_svn, lt->cpu_svn_le);
    if(AE_PSVN_UNMATCHED_ERROR == ret_le)
    {
        //QE or PSE has been changed, but AESM doesn't restart. Will not provide service.
        return SGX_ERROR_SERVICE_UNAVAILABLE;
    }else if(AE_SUCCESS != ret_le) {
        AESM_DBG_ERROR("fail to save psvn:%d", ret_le);
        return SGX_ERROR_UNEXPECTED;
    }

    return SGX_SUCCESS;
}
コード例 #14
0
//Function to implement the end point selection protocol
ae_error_t EndpointSelectionInfo::start_protocol(endpoint_selection_infos_t& es_info)
{
    AESMLogicLock lock(_es_lock);
    uint32_t msg_size = 0;
    uint8_t *resp = NULL;
    uint32_t resp_size = 0;
    uint16_t provision_ttl = 0;
    uint8_t *msg = NULL;
    uint8_t rsa_signature[RSA_3072_KEY_BYTES];
    gen_endpoint_selection_output_t enclave_output;
    ae_error_t ae_ret = AE_SUCCESS;
    uint32_t enclave_lost_count = 0;

    AESM_DBG_DEBUG("enter fun");
    memset(&es_info, 0, sizeof(es_info));
    memset(&enclave_output, 0, sizeof(enclave_output));
    if(!_is_server_url_valid){
        ae_ret = get_url_info();
        if(AE_SUCCESS != ae_ret){//It is not likely happen, only fail when memcpy_s failed
            AESM_DBG_ERROR("Fail to initialize server URL information");
            goto final_point;
        }
    }

    do{
        if((ae_ret = CPVEClass::instance().load_enclave())!=AE_SUCCESS){
            AESM_DBG_ERROR("Fail to load PVE enclave:%d", ae_ret);
            goto final_point;
        }
        //call PvE to generate the partition and xid
        ae_ret = static_cast<ae_error_t>(CPVEClass::instance().gen_es_msg1_data(&enclave_output));
        if(ae_ret == AE_ENCLAVE_LOST&& (++enclave_lost_count)<=MAX_ENCLAVE_LOST_RETRY_TIME ){
            CPVEClass::instance().unload_enclave();//unload and reload PvE when enclave lost encountered
            continue;
        }else if(ae_ret == AE_SUCCESS){
            break;
        }else{
            AESM_DBG_ERROR("fail to generate parition by PvE");
            goto final_point;
        }
    }while(1);

    AESM_DBG_TRACE("use parition %d from PvE", (int)enclave_output.selector_id);

    AESM_DBG_INFO("Connect to server url \"%s\" for endpoint selection", _server_urls.endpoint_url);

    msg_size = estimate_es_msg1_size();
    assert(msg_size>0);
    msg = static_cast<uint8_t *>(malloc(msg_size));
    if(msg == NULL){
        AESM_DBG_ERROR("malloc error");
        ae_ret = AE_OUT_OF_MEMORY_ERROR;
        goto final_point;
    }
    memset(msg, 0, msg_size);

    ae_ret = static_cast<ae_error_t>(CPVEClass::instance().gen_es_msg1(msg, msg_size, enclave_output));//Generate EndPoint Selection Msg1
    if(ae_ret != AE_SUCCESS){
        AESM_DBG_ERROR("ES msg1 generation failed:%d",ae_ret);
        goto final_point;
    }
    AESM_DBG_TRACE("ES msg1 generated");

    ae_ret = AESMNetworkEncoding::aesm_send_recv_msg_encoding(_server_urls.endpoint_url, msg, msg_size, resp, resp_size);//Encoding/send/receive/Decoding

    if(ae_ret != AE_SUCCESS){
        AESM_DBG_ERROR("fail to send ES msg1 to backend server:%d",ae_ret);
        if(OAL_PROXY_SETTING_ASSIST == ae_ret){//when proxy setting assistant required, return directly
            goto final_point;
        }
        if(read_pek(es_info)==AE_SUCCESS){
            ae_ret = AE_SUCCESS;//use es_info inside persistent storage and ignore network error
        }
        goto final_point;
    }
    assert(resp != NULL);
    AESM_DBG_TRACE("start to process ES msg2");
    ae_ret = static_cast<ae_error_t>(CPVEClass::instance().proc_es_msg2(resp, resp_size, es_info.provision_url, provision_ttl, enclave_output.xid, rsa_signature , es_info.pek));
    if(AE_SUCCESS != ae_ret){
        AESM_DBG_WARN("Fail to process ES msg2 from backend server:%d",ae_ret);
        goto final_point;
    }

    AESM_DBG_TRACE("ES Msg2 decoded successfully, ttl %ds",provision_ttl);
    ae_ret = verify_signature(es_info, enclave_output.xid, rsa_signature, provision_ttl);
    if(AE_SUCCESS != ae_ret){
        AESM_DBG_WARN("Signature verification in ES Msg2 failed");
        goto final_point;
    }
    AESM_DBG_TRACE("Signature in ES Msg2 verified");
    es_info.aesm_data_type = AESM_DATA_ENDPOINT_SELECTION_INFOS;
    es_info.aesm_data_version = AESM_DATA_ENDPOINT_SELECTION_VERSION;
    (void)write_pek(es_info);//ignore file writing error
    AESM_DBG_TRACE("end point selection succ,  provisioning url: %s",es_info.provision_url);

final_point:
    if(msg!=NULL)free(msg);
    if(resp!=NULL){
        AESMNetworkEncoding::aesm_free_response_msg(resp);
    }

    return ae_ret;
}
コード例 #15
0
//The function is to verify the PEK ECDSA Signature and RSA Signature for ES Msg2
//   When PvE uses PEK, it will re-check the ECDSA Signature
//The function will only be called after ES protocol is completed. But it will not be called when reading data back from persitent storage
//@param provision_ttl: The TTL field from ES Msg2 in little endian format
//@param rsa_signature: The RSA Signature in ES Msg2, it is RSA Signature to XID:TTL:provision_url
//@param xid: The transaction id (XID) of the ES Protocol
//@return AE_SUCCESS if signature verification success and passed
//@return PVE_MSG_ERROR if signature verification failed or message error
//other kinds of error code could be returned too due to corresponding error situation
ae_error_t EndpointSelectionInfo::verify_signature(const endpoint_selection_infos_t& es_info, uint8_t xid[XID_SIZE], uint8_t rsa_signature[RSA_3072_KEY_BYTES], uint16_t provision_ttl)
{
    //Do signature verification here
    ae_error_t ae_err = AE_SUCCESS;
    IppsRSAPublicKeyState *rsa_pub_key = NULL;
    Ipp8u *buffer = NULL;
    int public_key_buffer_size = 0;
    int vr = 0;
    uint16_t ttl=_htons(provision_ttl);
    IppStatus ipp_status = ippStsNoErr;
    uint8_t msg_buf[XID_SIZE + sizeof(ttl) + MAX_PATH];
    uint32_t buf_size = 0;
    extended_epid_group_blob_t xegb;

    memset(&xegb, 0, sizeof(xegb));
    if (AE_SUCCESS != (ae_err=XEGDBlob::instance().read(xegb))){
        return ae_err;
    }

    ae_err = aesm_check_pek_signature(es_info.pek, xegb);
    if(AE_SUCCESS != ae_err){
        AESM_DBG_ERROR("PEK Signature verifcation not passed:%d",ae_err);
        goto ret_point;
    }
    AESM_DBG_INFO("PEK signature verified successfully");
    buf_size = XID_SIZE +static_cast<uint32_t>(sizeof(ttl) + strnlen(es_info.provision_url, MAX_PATH));
    if(0!=memcpy_s(msg_buf,sizeof(msg_buf), xid, XID_SIZE)||
        0!=memcpy_s(msg_buf+XID_SIZE, sizeof(ttl) + MAX_PATH, &ttl, sizeof(ttl))||
        0!=memcpy_s(msg_buf+XID_SIZE+sizeof(ttl),  MAX_PATH, es_info.provision_url, buf_size-XID_SIZE-sizeof(ttl))){
            ae_err = AE_FAILURE;
            AESM_DBG_ERROR("memcpy error");
            goto ret_point;
    }

    ipp_status = get_provision_server_rsa_pub_key_in_ipp_format(es_info.pek, &rsa_pub_key);
    if(ippStsNoErr != ipp_status){
        AESM_DBG_ERROR("Fail to load rsa public key from PEK:%d", ipp_status);
        ae_err = ipp_error_to_ae_error(ipp_status);
        goto ret_point;
    }
    ipp_status = ippsRSA_GetBufferSizePublicKey(&public_key_buffer_size, rsa_pub_key);
    if(ippStsNoErr != ipp_status){
        AESM_DBG_ERROR("Fail to get rsa public key size:%s", ipp_status);
        ae_err = ipp_error_to_ae_error(ipp_status);
        goto ret_point;
    }
    buffer = (Ipp8u *)malloc(public_key_buffer_size);
    if(NULL == buffer){
        AESM_DBG_ERROR("malloc error");
        ae_err = AE_OUT_OF_MEMORY_ERROR;
        goto ret_point;
    }
    ipp_status = ippsRSAVerify_PKCS1v15(msg_buf, buf_size, rsa_signature, &vr, rsa_pub_key, ippHashAlg_SHA256, buffer);
    if(ippStsNoErr != ipp_status){
        AESM_DBG_ERROR("Fail to verify rsa signature:%d", ipp_status);
        ae_err = ipp_error_to_ae_error(ipp_status);
        goto ret_point;
    }
    if(vr == 0){
        AESM_DBG_TRACE("rsa signature verification failed");
        ae_err = PVE_MSG_ERROR;
        goto ret_point;
    }else{
        AESM_DBG_TRACE("rsa signature verification passed");
        ae_err = AE_SUCCESS;
    }
ret_point:
    if(NULL != rsa_pub_key){
        secure_free_rsa_pub_key(RSA_3072_KEY_BYTES, sizeof(uint32_t), rsa_pub_key);
    }
    if(NULL != buffer){
        free(buffer);
    }
    return ae_err;
}