Ejemplo n.º 1
0
static ae_error_t http_network_init(CURL **curl, const char *url, bool is_ocsp)
{
    CURLcode cc = CURLE_OK;
    UNUSED(is_ocsp);
    AESM_DBG_TRACE("http init for url %s",url);
    if(!is_curl_initialized_succ()){
        AESM_DBG_ERROR("libcurl not initialized");
        return AE_FAILURE;//fatal error that libcurl could not be initialized
    }
    std::string url_path = url;
    uint32_t proxy_type;
    char proxy_url[MAX_PATH];
    EndpointSelectionInfo::instance().get_proxy(proxy_type, proxy_url);

    *curl = curl_easy_init();
    if(!*curl){
         AESM_DBG_ERROR("fail to init curl handle");
         return AE_FAILURE;
    }
    if((cc=curl_easy_setopt(*curl, CURLOPT_URL, url_path.c_str()))!=CURLE_OK){
       AESM_DBG_ERROR("fail error code %d in set url %s",(int)cc, url_path.c_str());
       curl_easy_cleanup(*curl);
       return AE_FAILURE;
    }
    (void)curl_easy_setopt(*curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
    //setting proxy now
    if(proxy_type == AESM_PROXY_TYPE_DIRECT_ACCESS){
        AESM_DBG_TRACE("use no proxy");
        (void)curl_easy_setopt(*curl, CURLOPT_NOPROXY , "*");
    }else if(proxy_type == AESM_PROXY_TYPE_MANUAL_PROXY){
        AESM_DBG_TRACE("use manual proxy %s",proxy_url);
        (void)curl_easy_setopt(*curl, CURLOPT_PROXY, proxy_url);
    }
    return AE_SUCCESS;
}
ae_error_t CertificateProvisioningProtocol::SendM3_ReceiveM4
(   /*in */ const upse::Buffer& csrBuffer,
    /*in */ const upse::Buffer& quoteBuffer,
    /*out*/ std::list< upse::Buffer >& certificateChainList,
    /*out*/ platform_info_blob_wrapper_t& piBlobWrapper
)
{
    ae_error_t status = AE_FAILURE;

    upse::Buffer serializedMsg3;
    upse::Buffer serializedMsg4;
    AESM_DBG_TRACE("start to send M3");

    do
    {
        BREAK_IF_FALSE((m_is_initialized), status, AESM_PSE_PR_BACKEND_NOT_INITIALIZED);

        BREAK_IF_FALSE( (msg_next_state_M3 == m_nextState), status, AESM_PSE_PR_CALL_ORDER_ERROR);

        status = msg3_generate(csrBuffer, quoteBuffer, serializedMsg3);
        BREAK_IF_FAILED_ERR(status, AESM_PSE_PR_BACKEND_MSG3_GENERATE);
//        BREAK_IF_FAILED(status);
        AESM_DBG_TRACE("M3 generated");
        status = sendReceive(serializedMsg3, serializedMsg4);
        BREAK_IF_FAILED(status);
        AESM_DBG_TRACE("start to process M4");
        status = msg4_process(serializedMsg4, certificateChainList, piBlobWrapper);
        BREAK_IF_FAILED(status);
        AESM_DBG_TRACE("finished M4");
    } while (0);

    m_nextState = msg_next_state_init;

    return status;
}
Ejemplo n.º 3
0
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;
    }
}
Ejemplo n.º 4
0
// 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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
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;
    }
}
Ejemplo n.º 7
0
//function to decode proxy type from string to integer value
static uint32_t read_aesm_proxy_type(const char *string, uint32_t len)
{
     uint32_t i;
     for(i=0;i<NUM_PROXY_TYPE;++i){
        if(strncasecmp(proxy_type_name[i],string,len)==0){
            return i;
        }
     }
     AESM_DBG_TRACE("Invalid proxy type %.*s",len,string);
     return (uint32_t)NUM_PROXY_TYPE;
}
Ejemplo n.º 8
0
ae_error_t AESMLogic::set_psvn(uint16_t prod_id, uint16_t isv_svn, sgx_cpu_svn_t cpu_svn)
{
    if(prod_id == QE_PROD_ID){
        if(_is_qe_psvn_set){
            if(0!=memcmp(&_qe_psvn.isv_svn, &isv_svn, sizeof(isv_svn))||
                0!=memcmp(&_qe_psvn.cpu_svn, &cpu_svn, sizeof(sgx_cpu_svn_t))){
                    AESM_DBG_ERROR("PSVN unmatched for QE/PVE");
                    return AE_PSVN_UNMATCHED_ERROR;
            }
        }else{
            if(0!=memcpy_s(&_qe_psvn.isv_svn, sizeof(_qe_psvn.isv_svn), &isv_svn, sizeof(isv_svn))||
                0!=memcpy_s(&_qe_psvn.cpu_svn, sizeof(_qe_psvn.cpu_svn), &cpu_svn, sizeof(sgx_cpu_svn_t))){
                    AESM_DBG_ERROR("memcpy failed");
                    return AE_FAILURE;
            }
            AESM_DBG_TRACE("get QE or PvE isv_svn=%d",(int)isv_svn);
            _is_qe_psvn_set = true;
            return AE_SUCCESS;
        }
    }else if(prod_id == PSE_PROD_ID){
        if(_is_pse_psvn_set){
            if(0!=memcmp(&_pse_psvn.isv_svn, &isv_svn, sizeof(isv_svn))||
                0!=memcmp(&_pse_psvn.cpu_svn, &cpu_svn, sizeof(sgx_cpu_svn_t))){
                    AESM_DBG_ERROR("PSVN unmatched for PSE");
                    return AE_PSVN_UNMATCHED_ERROR;
            }
        }else{
            if(0!=memcpy_s(&_pse_psvn.isv_svn, sizeof(_pse_psvn.isv_svn), &isv_svn, sizeof(isv_svn))||
                0!=memcpy_s(&_pse_psvn.cpu_svn, sizeof(_pse_psvn.cpu_svn), &cpu_svn, sizeof(sgx_cpu_svn_t))){
                    AESM_DBG_ERROR("memcpy failed");
                    return AE_FAILURE;
            }
            AESM_DBG_TRACE("get PSE isv_svn=%d", (int)isv_svn);
            _is_pse_psvn_set = true;
            return AE_SUCCESS;
        }
    }
    return AE_SUCCESS;
}
Ejemplo n.º 9
0
static ae_error_t thread_to_load_qe(aesm_thread_arg_type_t arg)
{
    epid_blob_with_cur_psvn_t epid_data;
    ae_error_t ae_ret = AE_FAILURE;
    UNUSED(arg);
    AESM_DBG_TRACE("start to load qe");
    memset(&epid_data, 0, sizeof(epid_data));
    AESMLogicLock lock(AESMLogic::_qe_pve_mutex);
    if((ae_ret = EPIDBlob::instance().read(epid_data)) == AE_SUCCESS)
    {
        AESM_DBG_TRACE("EPID blob is read successfully, loading QE ...");
        ae_ret = CQEClass::instance().load_enclave();
        if(AE_SUCCESS != ae_ret)
        {
            AESM_DBG_WARN("fail to load QE: %d", ae_ret);
        }else{
            AESM_DBG_TRACE("QE loaded successfully");
        }
    }
    AESM_DBG_TRACE("QE Thread finished succ");
    return AE_SUCCESS;
}
//*********************************************************************
// Main engine routine for Certificate Chain Provisioning
//*********************************************************************
ae_error_t certificate_chain_provisioning(const endpoint_selection_infos_t& es_info, platform_info_blob_wrapper_t* pib_wrapper)
{
    ae_error_t status = AE_FAILURE;
    AESM_DBG_TRACE("enter fun");

    try
    {
        do
        {

            status = do_certificate_chain_provisioning(es_info, pib_wrapper);

            if (status == PSE_PR_ENCLAVE_LOST_ERROR)
            {
                //
                // went to sleep while in enclave
                // in this case (beginning of flow), we should just retry, after first destroying and then reloading
                // note that this code gets significantly more complicated if the PSE-pr ever becomes multi-threaded
                //
                for (unsigned rcount = 0; rcount < PSEPR_LOST_ENCLAVE_RETRY_COUNT; rcount++)
                {
                    CPSEPRClass::instance().unload_enclave();
                    if (0 != CPSEPRClass::instance().load_enclave())
                    {
                        status = AE_FAILURE;
                        break;
                    }
                    SaveEnclaveID(CPSEPRClass::instance().GetEID());

                    status = do_certificate_chain_provisioning(es_info, pib_wrapper);
                    if (status != PSE_PR_ENCLAVE_LOST_ERROR)
                        break;
                }
            }

            BREAK_IF_FAILED(status);

            status = AE_SUCCESS;

        } while (0);
    }
    catch (...)
    {
        status = AESM_PSE_PR_EXCEPTION;
    }

    SGX_DBGPRINT_PRINT_FUNCTION_AND_RETURNVAL(__FUNCTION__, status);
    SGX_DBGPRINT_PRINT_ANSI_STRING("End Certificate Chain Provisioning");
    return status;
}
Ejemplo n.º 11
0
//
// return values
// AESM_NPC_DONT_NEED_PSEP: cert present, ltp blob present and current pse version at least matches
//                 pse version in cert - may also be latest; default
// AESM_NPC_NO_PSE_CERT: no cert or no ltp blob
ae_error_t PlatformInfoLogic::need_pse_cert_provisioning()
{
    AESM_DBG_TRACE("enter fun");
    ae_error_t status = AESM_NPC_DONT_NEED_PSEP;

    if (Helper::noPseCert() ||
        Helper::noLtpBlob())                        // long-term pairing blob holds verifier/pse private key
    {
        status = AESM_NPC_NO_PSE_CERT;               // break this up in order to distinguish between no cert and no ltp blob?
    }

    SGX_DBGPRINT_ONE_STRING_TWO_INTS_CREATE_SESSION(__FUNCTION__" returning ", status, status);
    return status;
}
Ejemplo n.º 12
0
ae_error_t upse_long_term_pairing(sgx_enclave_id_t enclave_id, bool* new_pairing)
{
    ae_error_t status = AE_SUCCESS;
    AESM_DBG_TRACE("enter fun");

    SaveEnclaveID(enclave_id);      // Save the enclave ID for use in ECALLs

    do
    {
        status = create_sigma_long_term_pairing(new_pairing);
        BREAK_IF_FAILED(status);

    } while (0);

    return status;
}
Ejemplo n.º 13
0
ae_error_t CPSEPRClass::long_term_pairing(bool* p_new_pairing)
{
    ae_error_t status = AE_FAILURE;
    AESM_DBG_TRACE("enter fun");

    do
    {
        if ((status = CPSEPRClass::instance().load_enclave()) != AE_SUCCESS)
            break;
        
        status = upse_long_term_pairing(m_enclave_id, p_new_pairing);
        
    } while (0);

    CPSEPRClass::instance().unload_enclave();


    return status;
}
Ejemplo n.º 14
0
ae_error_t CPSEPRClass::certificate_provisioning(platform_info_blob_wrapper_t* pib_wrapper)
{
    ae_error_t status = AE_FAILURE;
    AESM_DBG_TRACE("enter fun");

    do
    {
        if ((status = CPSEPRClass::instance().load_enclave()) != AE_SUCCESS)
            break;
        
        status = upse_certificate_provisioning(m_enclave_id, pib_wrapper);
        
    } while (0);

    CPSEPRClass::instance().unload_enclave();


    return status;
}
Ejemplo n.º 15
0
ae_error_t upse_certificate_provisioning(sgx_enclave_id_t enclave_id, platform_info_blob_wrapper_t* pib_wrapper)
{
    ae_error_t status = AE_SUCCESS;
    AESM_DBG_TRACE("enter fun");

    SaveEnclaveID(enclave_id);      // Save the enclave ID for use in ECALLs

    do
    {
        endpoint_selection_infos_t es_info;

        if(AE_SUCCESS == (status = (ae_error_t)AESMLogic::endpoint_selection(es_info)) )
		{
			status = certificate_chain_provisioning(es_info, pib_wrapper);
		}
        BREAK_IF_FAILED(status);

    } while (0);

    return status;
}
Ejemplo n.º 16
0
//
// get_sgx_gid
//
// get sgx gid from epid blob, specifically from stored group cert in epid blob
//
// inputs
//
// pgid: pointer to gid
//
// outputs
//
// *pgid: gid
// status
//
ae_error_t EPIDBlob::get_sgx_gid(uint32_t* pgid) 
{
    ae_error_t aesm_result = AE_SUCCESS;
    epid_blob_with_cur_psvn_t epid_blob;
    sgx_sealed_data_t *sealed_epid = reinterpret_cast<sgx_sealed_data_t *>(epid_blob.trusted_epid_blob);

    if (NULL != pgid) {
        //
        // get the epid blob
        //
        aesm_result = this->read(epid_blob);
        if (AE_SUCCESS == aesm_result) {
            //
            // get the gid
            //
            uint32_t plain_text_offset = sealed_epid->plain_text_offset;
            se_plaintext_epid_data_t* plain_text = reinterpret_cast<se_plaintext_epid_data_t *>(epid_blob.trusted_epid_blob + sizeof(sgx_sealed_data_t) + plain_text_offset);
            if(memcpy_s(pgid, sizeof(*pgid), &plain_text->epid_group_cert.gid, sizeof(plain_text->epid_group_cert.gid)))	//read gid from EPID Data blob
            {
                AESM_DBG_ERROR("memcpy_s failed");
                aesm_result = AE_FAILURE;
            }
            //
            // return little-endian
            //
            *pgid = _htonl(*pgid);
            AESM_DBG_TRACE(": get gid %d from epid blob", *pgid);
        }
    }
    else {
        aesm_result = AE_INVALID_PARAMETER;
    }

    return aesm_result;

}
Ejemplo n.º 17
0
tlv_status_t TLVsMsg::init_from_tlv_msg(const tlv_msg_t& tlv_msg)
{
    clear();
    msg.msg_size = tlv_msg.msg_size;
    msg.msg_buf = (uint8_t *)malloc(msg.msg_size);
    if(msg.msg_buf == NULL){
        msg.msg_size = 0;
        AESM_DBG_ERROR("malloc failed");
        return TLV_OUT_OF_MEMORY_ERROR;
    }
    if(memcpy_s(msg.msg_buf, msg.msg_size, tlv_msg.msg_buf, tlv_msg.msg_size)!=0){
        AESM_DBG_ERROR("memcpy failed");
        return TLV_UNKNOWN_ERROR;
    }
    tlv_msg_t tlv_tmp = msg;
    tlv_info_t one_info;
    tlv_info_t *new_info = NULL;
    while(tlv_tmp.msg_size>0){
        if(decode_one_tlv(tlv_tmp, &one_info)){
            tlv_status_t ret = create_new_info(new_info);
            if(ret != TLV_SUCCESS) return ret;
            if(memcpy_s(new_info, sizeof(*new_info), &one_info, sizeof(one_info))!=0){
                AESM_DBG_ERROR("memcpy failed");
               return TLV_UNKNOWN_ERROR;
            }
#ifdef DBG_LOG
            char dbg_str[256];
            aesm_dbg_format_hex(new_info->payload, new_info->size, dbg_str, 256);
            AESM_DBG_TRACE("Decode One TLV: type (tlv %d), size %u, version %d, payload:%s",new_info->type, new_info->size, (int)new_info->version,dbg_str);
#endif
        }else{
            return TLV_INVALID_MSG_ERROR;
        }
    }
    return TLV_SUCCESS;
}
Ejemplo n.º 18
0
/* Assuming buffer size is checked before calling this function, and get_quote
   in QE will also check size. */
aesm_error_t QEAESMLogic::get_quote(const uint8_t *report,
                                    uint32_t quote_type,
                                    const uint8_t *spid,
                                    const uint8_t *nonce,
                                    const uint8_t *sigrl, uint32_t sigrl_size,
                                    uint8_t *qe_report,
                                    uint8_t *quote, uint32_t buf_size)
{
    epid_blob_with_cur_psvn_t epid_data;
    uint32_t ae_ret = AE_SUCCESS;
    aesm_error_t aesm_result = AESM_UNEXPECTED_ERROR;
    EPIDBlob& epid_blob = EPIDBlob::instance();

    AESM_PROFILE_FUN;
    memset(&epid_data, 0, sizeof(epid_data));

    AESM_DBG_TRACE("start to read and verify epid blob");

    if((ae_ret = epid_blob.read(epid_data))!=AE_SUCCESS){
        if((aesm_result = PvEAESMLogic::provision(false, THREAD_TIMEOUT))!=AESM_SUCCESS){
            
            AESM_DBG_ERROR("pve provision failed:%d", aesm_result);
            goto CLEANUP;
        }
    }

    if(CQEClass::instance().load_enclave())
    {
        AESM_DBG_ERROR("load QE failed");
        aesm_result = AESM_UNEXPECTED_ERROR;
        goto CLEANUP;
    }
    AESM_DBG_TRACE("start to get quote");
    ae_ret = CQEClass::instance().get_quote(epid_data.trusted_epid_blob,
        SGX_TRUSTED_EPID_BLOB_SIZE,
        reinterpret_cast<const sgx_report_t *>(report),
        static_cast<sgx_quote_sign_type_t>(quote_type),
        reinterpret_cast<const sgx_spid_t *>(spid),
        reinterpret_cast<const sgx_quote_nonce_t *>(nonce),
        sigrl,
        sigrl_size,
        reinterpret_cast<sgx_report_t *>(qe_report),
        quote,
        buf_size);
    if(ae_ret != AE_SUCCESS)
    {
        AESM_DBG_TRACE("get_quote failed:%d",ae_ret);
        if(ae_ret == QE_EPIDBLOB_ERROR)
            aesm_result = AESM_EPIDBLOB_ERROR;
        else if(ae_ret == QE_PARAMETER_ERROR)
            aesm_result = AESM_PARAMETER_ERROR;
        else if(ae_ret == QE_REVOKED_ERROR)
            aesm_result = AESM_EPID_REVOKED_ERROR;
        else
            aesm_result = AESM_UNEXPECTED_ERROR;
        goto CLEANUP;
    }
    AESM_DBG_TRACE("get quote succ");
    aesm_result = AESM_SUCCESS;
CLEANUP:
    return aesm_result;
}
Ejemplo n.º 19
0
//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;
}
Ejemplo n.º 20
0
//Function to decode ProvMsg4 and generate epid data blob
uint32_t CPVEClass::proc_prov_msg4(
    const pve_data_t &data,
    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;
    uint8_t temp[XID_SIZE+NONCE_SIZE];
    sgx_status_t sgx_status;
    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 != SGX_TRUSTED_EPID_BLOB_SIZE_PAK) {
        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:(ae%d)",ret);
        return ret;
    }
    if(0!=memcmp(msg4_header->xid, data.xid, XID_SIZE)) {
        AESM_DBG_ERROR("Invalid XID in msg4 header");
        return PVE_MSG_ERROR;
    }
    ret = check_epid_pve_pg_status_before_mac_verification(msg4_header);
    if( AE_SUCCESS != ret) {
        AESM_DBG_ERROR("Backend return failure in ProvMsg4 Header:(ae%d)",ret);
        return ret;
    }

    do {
        TLVsMsg tlvs_msg4;
        uint8_t aad[PROVISION_RESPONSE_HEADER_SIZE+NONCE_SIZE];
        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:(ae%d)",ret);
            break;
        }
        ret = msg4_integrity_checking(tlvs_msg4);
        if(AE_SUCCESS != ret) {
            AESM_DBG_ERROR("ProvMsg4 integrity checking error:(ae%d)",ret);
            break;
        }
        AESM_DBG_TRACE("ProvMsg4 decoded");
        se_static_assert(sizeof(sgx_cmac_128bit_key_t)==SK_SIZE);
        if(0!=memcpy_s(temp,sizeof(temp), data.xid, XID_SIZE)||
                0!=memcpy_s(temp+XID_SIZE, sizeof(temp)-XID_SIZE, MSG4_TOP_FIELD_NONCE.payload, NONCE_SIZE)) {
            AESM_DBG_ERROR("Fail in memcpy");
            ret = AE_FAILURE;
            break;
        }
        if((sgx_status=sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(data.sk),
                                                temp, XID_SIZE+NONCE_SIZE, reinterpret_cast<sgx_cmac_128bit_tag_t *>(local_ek2)))!=SGX_SUCCESS) {
            AESM_DBG_ERROR("Fail to generate ek2:(sgx0x%x)",sgx_status);
            ret = AE_FAILURE;
            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;
        }
        if (memcpy_s(aad, sizeof(aad), msg4_header, PROVISION_RESPONSE_HEADER_SIZE) != 0 ||
                memcpy_s(aad + PROVISION_RESPONSE_HEADER_SIZE, sizeof(aad)-PROVISION_RESPONSE_HEADER_SIZE,
                         MSG4_TOP_FIELD_NONCE.payload, MSG4_TOP_FIELD_NONCE.size) != 0) {
            AESM_DBG_ERROR("memcpy failure");
            ret = AE_FAILURE;
            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,
                                  aad, sizeof(aad),
                                  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 (sgx0x%x)",sgx_status);
            ret = PVE_INTEGRITY_CHECK_ERROR;
            break;
        }
        if( AE_SUCCESS != (ret = sgx_error_to_ae_error(sgx_status))) {
            AESM_DBG_ERROR("error in decrypting ProvMsg4:(sgx0x%x)",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:(ae%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:(ae%d)",ret);
            break;
        }
        ret = msg4_field1_msg_checking(tlvs_field1);
        if( AE_SUCCESS != ret) {
            AESM_DBG_ERROR("ProvMsg4 Field2.1 invalid:(ae%d)",ret);
            break;
        }
        proc_prov_msg4_input_t msg4_input;
        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.n2, NONCE_2_SIZE, MSG4_FIELD1_Nonce2.payload, MSG4_FIELD1_Nonce2.size) ||
                0!=memcpy_s(&msg4_input.equivalent_psvn, sizeof(psvn_t), platform_info_tlv_get_psvn(MSG4_FIELD1_PLATFORM_INFO), sizeof(psvn_t))||
                0!=memcpy_s(&msg4_input.fmsp, sizeof(fmsp_t), platform_info_tlv_get_fmsp(MSG4_FIELD1_PLATFORM_INFO), sizeof(fmsp_t))||
                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;
        }
        if (AE_SUCCESS != (ret =XEGDBlob::instance().read(msg4_input.xegb))) {
            AESM_DBG_ERROR("Fail to read extend epid blob info (ae%d)",ret);
            return ret;
        }

        ret = CPVEClass::instance().load_enclave();//Load PvE enclave now
        if( ret != AE_SUCCESS) {
            AESM_DBG_ERROR("Fail to load PvE enclave:(ae%d)\n",ret);
            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 (ae%d) in Process ProvMsg4",ret);
    } while(0);
    if(decoded_msg4)free(decoded_msg4);
    return ret;
}
Ejemplo n.º 21
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;
}
Ejemplo n.º 22
0
//Function to fetch gid from Epid Data Blob and also return target info
//EPID Provisioning will be redone if Epid Data Blob is not existing/invalid or
// the qe_isv_svn or cpu_svn don't match that in Epid Data Blob
aesm_error_t QEAESMLogic::init_quote(
    sgx_target_info_t *target,
    uint8_t *gid, uint32_t gid_size,
    uint16_t qe_isv_svn, const sgx_cpu_svn_t qe_cpu_svn)
{
    ae_error_t ae_ret = AE_SUCCESS;
    EPIDBlob& epid_blob = EPIDBlob::instance();
    AESM_DBG_DEBUG("enter fun");
    aesm_error_t aesm_result = AESM_UNEXPECTED_ERROR;

    AESM_PROFILE_FUN;

    epid_blob_with_cur_psvn_t epid_data;
    bool resealed = false;
    bool updated = false;
    memset(&epid_data,0,sizeof(epid_data));

    AESM_DBG_TRACE("start read and verify old epid blob");
    if((ae_ret = epid_blob.read(epid_data))!=AE_SUCCESS){
        if(AESM_SUCCESS!=(aesm_result = try_reprovision_if_not(updated, epid_data))){
            goto ret_point;
        }
    }

    if((ae_ret = CQEClass::instance().load_enclave())!=AE_SUCCESS)
    {
        AESM_DBG_ERROR("Fail to load QE:%d", ae_ret);
        aesm_result = AESM_UNEXPECTED_ERROR;
        goto ret_point;
    }
    ae_ret = static_cast<ae_error_t>(CQEClass::instance().verify_blob(epid_data.trusted_epid_blob,
        SGX_TRUSTED_EPID_BLOB_SIZE,
        &resealed));
    if(ae_ret == QE_EPIDBLOB_ERROR){
        if(AESM_SUCCESS!=(aesm_result = try_reprovision_if_not(updated, epid_data))){
            goto ret_point;
        }
    }
    else if(ae_ret != AE_SUCCESS) 
    {
        aesm_result = AESM_UNEXPECTED_ERROR;
        goto ret_point;
    }

    // Assert the size of GID, we have already checked it in upper level.
    assert(sizeof(uint32_t) ==  gid_size);
    UNUSED(gid_size);

    if (AE_SUCCESS != EPIDBlob::instance().get_sgx_gid((uint32_t*) gid)) {
        aesm_result = AESM_UNEXPECTED_ERROR;
        goto ret_point;
    }

    AESM_DBG_TRACE("get gid %d from epid blob (little-endian)",
                    *(uint32_t*) gid);

    if(get_qe_target(target)!=AE_SUCCESS){
        AESM_DBG_ERROR("get qe target failed");
        aesm_result = AESM_UNEXPECTED_ERROR;
        goto ret_point;
    }
    AESM_DBG_TRACE("get qe_target flags:%llx xfrm:%llx",
                   target->attributes.flags, target->attributes.xfrm);
    //Any Quoting enclave related code must be before this section to avoid QE/PvE unloading each other
    //Do the upgrade reprovision if required
    AESM_DBG_TRACE("qe_isv_svn %d, epid_isv_svn %df",qe_isv_svn, epid_data.cur_psvn.isv_svn);
    if((qe_isv_svn > epid_data.cur_psvn.isv_svn)
       || (0!=memcmp(&qe_cpu_svn, &epid_data.cur_psvn.cpu_svn,
           sizeof(sgx_cpu_svn_t))))
    {
        //We will ignore all provision failure when there is a working EPID blob and leave the decision to attestation server
        if(AESM_SUCCESS == (aesm_result = try_reprovision_if_not(updated, epid_data))){
            resealed = false;
        }else if(AESM_PROXY_SETTING_ASSIST == aesm_result ||
            AESM_BUSY == aesm_result ||
            AESM_UPDATE_AVAILABLE == aesm_result ){//we should not ignore the three special error
            goto ret_point;
        }
    }
    //Any Quoting enclave related code must be before this section to avoid QE/PvE unloading each other */
    aesm_result = AESM_SUCCESS;
ret_point:
    if(resealed && aesm_result == AESM_SUCCESS){
        AESM_DBG_TRACE("Update epid blob");
        if((ae_ret=epid_blob.write(epid_data))!=AE_SUCCESS){
            AESM_DBG_WARN("Fail to update epid blob:%d",ae_ret);
        }
    }
    return aesm_result;
}
Ejemplo n.º 23
0
static ae_error_t http_network_send_data(CURL *curl, const char *req_msg, uint32_t msg_size, char **resp_msg, uint32_t& resp_size, http_methods_t method, bool is_ocsp)
{
    AESM_DBG_TRACE("send data method=%d",method);
    struct curl_slist *headers=NULL;
    struct curl_slist *tmp=NULL;
    ae_error_t ae_ret = AE_SUCCESS;
    CURLcode cc=CURLE_OK;
    int num_bytes = 0;
    if(is_ocsp){
        tmp = curl_slist_append(headers, "Accept: application/ocsp-response");
        if(tmp==NULL){
            AESM_DBG_ERROR("fail in add accept ocsp-response header");
            ae_ret = AE_FAILURE;
            goto fini;
        }
        headers = tmp;
        tmp = curl_slist_append(headers, "Content-Type: application/ocsp-request");
        if(tmp == NULL){
           AESM_DBG_ERROR("fail in add content type ocsp-request");
           ae_ret = AE_FAILURE;
           goto fini;
        }
        headers=tmp;
        AESM_DBG_TRACE("ocsp request");
    }
    char buf[50];
    num_bytes = snprintf(buf,sizeof(buf), "Content-Length: %u", (unsigned int)msg_size);
    if(num_bytes<0 || num_bytes>=sizeof(buf)){
         AESM_DBG_ERROR("fail to prepare string Content-Length");
         ae_ret = AE_FAILURE;
         goto fini;
    }
    tmp = curl_slist_append(headers, buf);
    if(tmp == NULL){
         AESM_DBG_ERROR("fail to add content-length header");
         ae_ret = AE_FAILURE;
         goto fini;
    }
    headers=tmp;
    if((cc=curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers))!=CURLE_OK){
        AESM_DBG_ERROR("fail to set http header:%d",(int)cc);
        ae_ret = AE_FAILURE;
        goto fini;
    }
    if(method == POST){
        if((cc=curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req_msg))!=CURLE_OK){
            AESM_DBG_ERROR("fail to set POST fields:%d",(int)cc);
            ae_ret = AE_FAILURE;
            goto fini;
        }
        if((cc=curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, msg_size))!=CURLE_OK){
            AESM_DBG_ERROR("fail to set POST fields size:%d",(int)cc);
            ae_ret = AE_FAILURE;
            goto fini;
        }
    }
    if((cc=curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback))!=CURLE_OK){
        AESM_DBG_ERROR("Fail to set callback function:%d",(int)cc);
        ae_ret = AE_FAILURE;
        goto fini;
    }

    network_malloc_info_t malloc_info;
    malloc_info.base=NULL;
    malloc_info.size = 0;
    if((cc=curl_easy_setopt(curl, CURLOPT_WRITEDATA, reinterpret_cast<void *>(&malloc_info)))!=CURLE_OK){
       AESM_DBG_ERROR("fail to set write back function parameter:%d",(int)cc);
       ae_ret = AE_FAILURE;
       goto fini;
    }
    if((cc=curl_easy_perform(curl))!=CURLE_OK){
        if(malloc_info.base){
            free(malloc_info.base);
        }
        AESM_DBG_ERROR("fail in connect:%d",(int)cc);
        ae_ret = OAL_NETWORK_UNAVAILABLE_ERROR;
        goto fini;
    }
    *resp_msg = malloc_info.base;
    resp_size = malloc_info.size;
    AESM_DBG_TRACE("get response size=%d",resp_size);
    ae_ret = AE_SUCCESS;
fini:
    if(headers!=NULL){
        curl_slist_free_all(headers);
    }
    return ae_ret;
}
Ejemplo n.º 24
0
//
// return values
// SUCCESS:
// NO_LONGTERM_PAIRING_BLOB:
// DONT_NEED_UPDATE_PAIR_LTP: psda svn now up to date
// MAY_NEED_UPDATE_LTP: psda updated, but may not be up to date
// OLD_EPID11_RLS:
//
ae_error_t PlatformInfoLogic::need_long_term_pairing(const platform_info_blob_wrapper_t* platformInfoBlobWrapper)
{
    AESM_DBG_TRACE("enter fun");
    ae_error_t status = AE_SUCCESS;

    pairing_blob_t pairing_blob;

    if (AE_FAILED(Helper::read_ltp_blob(pairing_blob)))
    {
        status = AESM_NLTP_NO_LTP_BLOB;
    }
    else if (Helper::noPseCert())
    {
        status = AESM_NPC_NO_PSE_CERT;
    }
    else
    {
        uint32_t current_psda_svn = PSDAService::instance().psda_svn;

        pse_pr_interface_psda* pPSDA = NULL;

        pPSDA = new(std::nothrow) pse_pr_interface_psda();
        if (pPSDA == NULL) {
            return AE_OUT_OF_MEMORY_ERROR;
        }
        EPID_GID meGid;

        if (NULL != platformInfoBlobWrapper)
        {

            //
            // psda svn was bad, cse gid was good and now psda svn is good
            // fact that we may not be able to get current PSDA SVN doesn't matter
            // here as long as expression involving it evaluates to false
            //
            uint32_t pib_psda_svn;
            pib_psda_svn = latest_psda_svn(platformInfoBlobWrapper);

            //pairing_blob_t pairing_blob;
            //Helper::read_ltp_blob(pairing_blob);

            //
            // psda svn was bad, cse gid was good and now psda svn is good
            // fact that we may not be able to get current PSDA SVN doesn't matter
            // here as long as expression involving it evaluates to false
            //
            if (((psda_svn_out_of_date(platformInfoBlobWrapper)) &&
                (current_psda_svn == pib_psda_svn)) || 0)
                //(!psda_svn_out_of_date(platformInfoBlobWrapper) && cse_gid_out_of_date(platformInfoBlobWrapper)))
            {
                status = AESM_NLTP_DONT_NEED_UPDATE_PAIR_LTP;      // don't need update, but need pairing
            }
            else if (cse_gid_out_of_date(platformInfoBlobWrapper)) {
                if (AE_SUCCESS == pPSDA->get_csme_gid(&meGid)) {
                    if (Helper::ltpBlobCseGid(pairing_blob) != meGid) {
                        status = AESM_NLTP_DONT_NEED_UPDATE_PAIR_LTP;
                    }
                }
                else {
                    status = AESM_NLTP_DONT_NEED_UPDATE_PAIR_LTP;
                }

            }
            //
            // we need to handle cases where current psda svn or psda svn in ltp
            // blob is unavailable
            // no ltp blob is handled above
            // not being able to get current psda svn is handled elsewhere
            // we just need to make sure we don't return something misleading
            //
            else if (newer_psda_svn(current_psda_svn, Helper::ltpBlobPsdaSvn(pairing_blob)))
                //(currentCse_gid() != ltpBlobCse_gid()))                       // assume no rollback
            {
                status = AESM_NLTP_MAY_NEED_UPDATE_LTP;       // may need update and need pairing
            }
            else if (old_epid11_rls(platformInfoBlobWrapper))
            {
                status = AESM_NLTP_OLD_EPID11_RLS;
            }
        }
        else
        {
            if ((AE_SUCCESS == pPSDA->get_csme_gid(&meGid)) && (Helper::ltpBlobCseGid(pairing_blob) != meGid)) {
                status = AESM_NLTP_DONT_NEED_UPDATE_PAIR_LTP;

            }
            //
            // see comment above about what happens when no ltp blob
            // or we can't get current psda svn
            //
            else if (newer_psda_svn(current_psda_svn, Helper::ltpBlobPsdaSvn(pairing_blob)))
                //(currentCse_gid() != ltpBlobCse_gid()))
            {
                status = AESM_NLTP_MAY_NEED_UPDATE_LTP;
            }
        }

        delete pPSDA;
        pPSDA = NULL;
    }
    SGX_DBGPRINT_ONE_STRING_TWO_INTS_CREATE_SESSION(__FUNCTION__" returning ", status, status);
    return status;
}
Ejemplo n.º 25
0
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;
}
Ejemplo n.º 26
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;
}