Exemple #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;
}
Exemple #2
0
//Function to do reprovision if flag updated is false and set it to true if updated successfully
//The flag updated is used to simpilify logic in caller's code so that provision will not be invoked again 
//if a previous provision has been successfully run
//After reprovision, the output epid_blob will be copied into output parameter epid_data
static aesm_error_t try_reprovision_if_not(bool& updated, epid_blob_with_cur_psvn_t& epid_data)
{
    aesm_error_t aesm_result;
    ae_error_t ae_ret;
    if(updated){
        // We've just got a EPID blob. It's a rare case to reach here.
        // No retry, just return error.
        AESM_DBG_ERROR("try to reprovision again after another provision");
        return AESM_EPIDBLOB_ERROR;
    }
    // The EPID blob is corrupted, and we've not provisioned yet, then
    // we need to start the provision process.
    if((aesm_result = PvEAESMLogic::provision(false, THREAD_TIMEOUT))!=AESM_SUCCESS){
        
        AESM_DBG_ERROR("pve provision failed:%d", aesm_result);
        return aesm_result;
    }
    updated = true;
    // Update the epid blob after a successful provisioning.
    if((ae_ret = EPIDBlob::instance().read(epid_data))!=AE_SUCCESS){
        AESM_DBG_ERROR("read epid blob failed:%d", ae_ret);
        return AESM_EPIDBLOB_ERROR;
    }
    return AESM_SUCCESS;
}
Exemple #3
0
static size_t write_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
    network_malloc_info_t* s=reinterpret_cast<network_malloc_info_t *>(stream);
    uint32_t start=0;
    if(s->base==NULL){
        if(UINT32_MAX/size<nmemb){
              return 0;//buffer overflow
        }
        s->base = reinterpret_cast<char *>(malloc(size*nmemb));
        s->size = static_cast<uint32_t>(size*nmemb);
        if(s->base==NULL){
            AESM_DBG_ERROR("malloc error in write callback fun");
            return 0;
        }
    }else{
        uint32_t newsize = s->size+static_cast<uint32_t>(size*nmemb);
        if((UINT32_MAX-s->size)/size<nmemb){
             return 0;//buffer overflow
        }
        char *p=reinterpret_cast<char *>(malloc(newsize));
        if(p == NULL){
            free(s->base);
            s->base = NULL;
            AESM_DBG_ERROR("malloc error in write callback fun");
            return 0;
        }
        memcpy(p, s->base, s->size);
        free(s->base);
        start = s->size;
        s->base = p;
        s->size = newsize;
    }
    memcpy(s->base +start, ptr, size*nmemb);
    return nmemb;
}
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<provision_request_header_t *>(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;
    }
}
//Function to write tlv header into a msg according to tlv info, the input buffer size should be at least MAX_TLV_HEADER_SIZE
static tlv_status_t write_tlv_header(uint8_t *msg, const tlv_info_t *info)
{
    uint8_t type = info->type;
    if(info->size>UINT16_MAX ||info->header_size == LARGE_TLV_HEADER_SIZE){//6 bytes header
        uint32_t size = info->size; //4 bytes in size field
        type |= FOUR_BYTES_SIZE_TYPE;
        msg[0] = type;
        msg[1] = info->version;
        size = _htonl(size);
        if(memcpy_s(&msg[2], sizeof(uint32_t), &size, sizeof(size))!=0){
            AESM_DBG_ERROR("memcpy failed");
            return TLV_UNKNOWN_ERROR;
        }
    }else{//4 bytes header
        uint16_t size = (uint16_t)info->size;//2 bytes in size field
        msg[0] = type;
        msg[1] = info->version;
        size = _htons(size); 
        if(memcpy_s(&msg[2], sizeof(uint16_t), &size, sizeof(size))!=0){
            AESM_DBG_ERROR("memcpy failed");
            return TLV_UNKNOWN_ERROR;
        }
    }
    return TLV_SUCCESS;
}
Exemple #6
0
ae_error_t AESMLogic::get_qe_cpu_svn(sgx_cpu_svn_t& cpu_svn)
{
    if(!_is_qe_psvn_set){
        ae_error_t ae_err = CQEClass::instance().load_enclave();
        if(AE_SUCCESS != ae_err){
            AESM_DBG_ERROR("Fail to load QE Enclave:%d",ae_err);
            return ae_err;
        }
    }
    assert(_is_qe_psvn_set);
    if(0!=memcpy_s(&cpu_svn, sizeof(sgx_cpu_svn_t), &_qe_psvn.cpu_svn, sizeof(_qe_psvn.cpu_svn))){
        AESM_DBG_ERROR("memcpy failed");
        return AE_FAILURE;
    }
    return AE_SUCCESS;
}
Exemple #7
0
uint32_t CPCEClass::sign_report(const psvn_t& cert_psvn, const sgx_report_t& report, uint8_t signed_sign[2*SE_ECDSA_SIGN_SIZE])
{
    sgx_status_t status = SGX_SUCCESS;
    uint32_t ret_val = 0;
    uint32_t ret_size = 2*SE_ECDSA_SIGN_SIZE;
    int retry = 0;
    AESM_PROFILE_FUN;
    if (m_enclave_id == 0){
        AESM_DBG_ERROR("call certify_enclave without loading PCE");
        return AE_FAILURE;
    }

    status = ::certify_enclave(m_enclave_id, &ret_val, &cert_psvn, &report, signed_sign, 2*SE_ECDSA_SIGN_SIZE, &ret_size);
    for(; status == SGX_ERROR_ENCLAVE_LOST && retry < AESM_RETRY_COUNT; retry++)
    {
        unload_enclave();
        if(AE_SUCCESS != load_enclave())
            return AE_FAILURE;
        status = ::certify_enclave(m_enclave_id, &ret_val, &cert_psvn, &report, signed_sign, 2*SE_ECDSA_SIGN_SIZE, &ret_size);
    }
    if(status != SGX_SUCCESS)
        return AE_FAILURE;
    if(ret_val != AE_SUCCESS){
        return ret_val;
    }
    if(ret_size != 2*SE_ECDSA_SIGN_SIZE)
        return AE_FAILURE;
    return AE_SUCCESS;
}
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;
}
Exemple #9
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;
    }
}
Exemple #10
0
//Function to processing one line in config file
//  If any pattern is matched, get the correspondent data and set it into the output parameter 'infos'
static bool config_process_one_line(const char *line, config_entry_t entries[], aesm_config_infos_t& infos)
{
    uint32_t i;
    regmatch_t matches[MAX_MATCHED_REG_EXP];
    for(i=0;i<config_value_nums;++i){
        if(!entries[i].initialized){
            continue;
        }
        if(regexec(&entries[i].reg, line, MAX_MATCHED_REG_EXP, matches, 0)==0){
            switch(i){
            case config_comment:
            case config_space:
                 //ignore comment and space only line
                 break;
            case config_white_list_url://Matching White List URL setting
                 if(matches[1].rm_eo-matches[1].rm_so>=MAX_PATH){
                     AESM_DBG_ERROR("too long white list url in config file");
                 }else{
                     memcpy(infos.white_list_url, line+matches[1].rm_so,matches[1].rm_eo-matches[1].rm_so);
                     infos.white_list_url[matches[1].rm_eo-matches[1].rm_so]='\0';
                 }
                 break;
           case config_aesm_proxy_url:
                 if(matches[1].rm_eo-matches[1].rm_so>=MAX_PATH){
                     AESM_DBG_ERROR("too long aesm proxy url in config file");
                 }else{
                     memcpy(infos.aesm_proxy, line+matches[1].rm_so,matches[1].rm_eo-matches[1].rm_so);
                     infos.aesm_proxy[matches[1].rm_eo-matches[1].rm_so]='\0';
                 }
                 break;
            case config_aesm_proxy_type://It is a proxy type, we need change the string to integer by calling function read_aesm_proxy_type
                 infos.proxy_type = read_aesm_proxy_type(line+matches[1].rm_so, matches[1].rm_eo-matches[1].rm_so);
                 break;
            default:
                 AESM_DBG_ERROR("reg exp type %d not processed", i);
                 break;
            }
            break;
        }
    }
    if(i>=config_value_nums){//the line matching nothing
        AESM_DBG_ERROR("aesm config file error: invalid line[%s]",line);
        return false;
    }
    return true;
}
Exemple #11
0
ae_error_t XEGDBlob::verify(const extended_epid_group_blob_t& signed_xegb)
{
    ae_error_t aesm_result = aesm_verify_xegb(signed_xegb);
    if (AE_SUCCESS != aesm_result)
    {
        AESM_DBG_ERROR("Extended EPID Group Blob Signature verifcation not passed:%d", aesm_result);
        return aesm_result;
    }
    return aesm_result;
}
//Function to initialize request header for ProvMsg1
//msg1_header: request header for ProvMsg1 to fill in
//use_flags: whether the flag tlv is included
//xid: transaction ID
//msg1_buffer_size: buffer size for ProvMsg1, in bytes
static ae_error_t prov_msg1_gen_header(provision_request_header_t *msg1_header,
                                       bool use_flags,
                                       const uint8_t *xid,
                                       uint32_t msg1_buffer_size)
{
    uint32_t total_size = 0;
    //platform info tlv size
    uint32_t field1_data_size = PLATFORM_INFO_TLV_SIZE();
    field1_data_size += CIPHER_TEXT_TLV_SIZE(RSA_3072_KEY_BYTES);
    //add flag tlv if needed
    if(use_flags){
        field1_data_size += FLAGS_TLV_SIZE();
    }

    if(sizeof(*msg1_header)>msg1_buffer_size){
        AESM_DBG_ERROR("Too small ProvMsg1 buffer size");
        return PVE_INSUFFICIENT_MEMORY_ERROR;
    }
    total_size = CIPHER_TEXT_TLV_SIZE(RSA_3072_KEY_BYTES) + BLOCK_CIPHER_TEXT_TLV_SIZE(field1_data_size) +MAC_TLV_SIZE(MAC_SIZE);
    //initialize Msg1 Header
    msg1_header->protocol = SE_EPID_PROVISIONING;
    msg1_header->type = TYPE_PROV_MSG1;
    msg1_header->version = TLV_VERSION_2;
    if(0!=memcpy_s(msg1_header->xid, sizeof(msg1_header->xid), xid, XID_SIZE)){
        AESM_DBG_FATAL("fail in memcpy_s");
        return PVE_UNEXPECTED_ERROR;
    }
    uint32_t size_in;
    //use as a tmp size, big endian required in msg header
    size_in = _htonl(total_size);
    //copy big endian msg body size into header
    if(0!=memcpy_s(&msg1_header->size, sizeof(msg1_header->size),&size_in, sizeof(size_in))){
        AESM_DBG_FATAL("fail in memcpy_s");
        return PVE_UNEXPECTED_ERROR;
    }
    if(total_size +sizeof(*msg1_header) >msg1_buffer_size){
        //the input msg body size is not large enough
        AESM_DBG_ERROR("Too small ProvMsg1 buffer size");
        return PVE_INSUFFICIENT_MEMORY_ERROR;
    }
    return AE_SUCCESS;
}
Exemple #13
0
//static function to initialize all regular expression pattern
static void init_config_patterns(config_entry_t entries[])
{
    uint32_t i;
    for(i=0;i<NUM_CONFIG_PATTERNS;++i){
       uint32_t entry_id = config_patterns[i].id;
       if(entry_id>=config_value_nums){
          AESM_DBG_ERROR("config id %d is too large", entry_id);
          continue;
       }
       if(entries[entry_id].initialized){
          AESM_DBG_ERROR("duplicated item for config id %d",entry_id);
          continue;
       }
       if(regcomp(&entries[entry_id].reg,config_patterns[i].pattern, REG_EXTENDED|REG_ICASE)!=0){
          AESM_DBG_ERROR("Invalid config pattern %s", config_patterns[i].pattern);
          continue;
       }
       entries[entry_id].initialized=true;
    }
}
Exemple #14
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;
}
Exemple #15
0
static ae_error_t get_qe_target(sgx_target_info_t *p_qe_target)
{
    ae_error_t ae_ret = AE_SUCCESS;

    if((ae_ret = CQEClass::instance().load_enclave())!=AE_SUCCESS)
    {
        AESM_DBG_ERROR("Fail to load QE:%d",ae_ret);
        return ae_ret;
    }
    ae_ret = static_cast<ae_error_t>(CQEClass::instance().get_qe_target(p_qe_target));
    if(ae_ret != AE_SUCCESS)
        return ae_ret;
    return AE_SUCCESS;
}
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;
}
Exemple #17
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;
    }
}
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;
}
Exemple #19
0
ae_error_t XEGDBlob::read(extended_epid_group_blob_t& blob)
{
    ae_error_t ae_ret = AE_FAILURE;
    if(status == not_initialized){
        uint32_t data_size = sizeof(blob_cache);
        if ((ae_ret = aesm_read_data(FT_PERSISTENT_STORAGE, EXTENDED_EPID_GROUP_BLOB_INFO_FID, reinterpret_cast<uint8_t *>(&blob_cache), &data_size, AESMLogic::get_active_extended_epid_group_id())) != AE_SUCCESS){
            goto CLEANUP_READ_FILE;
        }
        if (data_size != sizeof(blob_cache)){
            ae_ret = OAL_CONFIG_FILE_ERROR;
            goto CLEANUP_READ_FILE;
        }
        ae_ret = verify(blob_cache);
        if (AE_SUCCESS != ae_ret){
            AESM_DBG_ERROR("signature error in XEGD file");
            goto CLEANUP_READ_FILE;
        }
        status = update_to_date;
CLEANUP_READ_FILE:
        if (status != update_to_date){
            if (AESMLogic::get_active_extended_epid_group_id() == DEFAULT_EGID){
                memset(&blob_cache, 0, sizeof(blob_cache));//indicate other part to use default data
                status = update_to_date;
            }
            else{
                status = not_available;//xegd blob lost
            }
        }
    }
    if(status == update_to_date){
        if(memcpy_s(&blob, sizeof(blob), &blob_cache, sizeof(blob_cache))!=0){
            status = not_available; //invalid
            ae_ret = AE_FAILURE;
        }else{
            ae_ret = AE_SUCCESS;
        }
    }
    return ae_ret;
}
Exemple #20
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;

}
Exemple #21
0
bool read_aesm_config(aesm_config_infos_t& infos)
{
    char line[MAX_LINE];
    int line_no=0;
    bool ret = true;
    config_entry_t entries[config_value_nums];
    memset(&entries,0,sizeof(entries));
    memset(&infos, 0, sizeof(aesm_config_infos_t));
    strcpy(infos.white_list_url, DEFAULT_WHITE_LIST_URL);
    
    infos.proxy_type = AESM_PROXY_TYPE_DEFAULT_PROXY;
    FILE *f =fopen(AESM_CONFIG_FILE, "r");
    if(f==NULL){
         AESM_DBG_ERROR("Cannnot read aesm config file %s",AESM_CONFIG_FILE);
         return false;
    }
    init_config_patterns(entries);
    while(fgets(line, MAX_LINE, f)!=NULL){
        size_t len=strlen(line);
        if(len>0&&line[len-1]=='\n')line[len-1]='\0';//remove the line ending
        line_no++;
        if(!config_process_one_line(line, entries, infos)){
            AESM_LOG_WARN("format error in file %s:%d [%s]",AESM_CONFIG_FILE, line_no, line);
            ret = false;//continue process the file but save the error status
        }
    }
    release_config_patterns(entries);
    fclose(f);
    if(infos.proxy_type>=NUM_PROXY_TYPE||
          (infos.proxy_type==AESM_PROXY_TYPE_MANUAL_PROXY&&infos.aesm_proxy[0]=='\0')){
            AESM_DBG_WARN("Invalid proxy type %d",infos.proxy_type);
            infos.proxy_type = AESM_PROXY_TYPE_DIRECT_ACCESS;
            ret = false;
    }
    return ret;
}
Exemple #22
0
uint32_t CPCEClass::get_pce_info(const sgx_report_t& report, const signed_pek_t& pek, uint16_t& pce_id, uint16_t& isv_svn, uint8_t encrypted_ppid[PEK_MOD_SIZE])
{
    sgx_status_t status = SGX_SUCCESS;
    uint32_t ret_val = 0;
    uint32_t ret_size = PEK_MOD_SIZE;
    int retry = 0;
    pce_info_t pce_info;
    uint8_t signature_scheme;
    AESM_PROFILE_FUN;
    if (m_enclave_id == 0){
        AESM_DBG_ERROR("call get_pc_info without loading PCE");
        return AE_FAILURE;
    }

    status = ::get_pc_info(m_enclave_id, &ret_val, &report, (uint8_t*)&pek, PEK_MOD_SIZE + sizeof(pek.e), ALG_RSA_OAEP_2048, encrypted_ppid, PEK_MOD_SIZE, &ret_size, &pce_info, &signature_scheme);
    for(; status == SGX_ERROR_ENCLAVE_LOST && retry < AESM_RETRY_COUNT; retry++)
    {
        unload_enclave();
        if(AE_SUCCESS != load_enclave())
            return AE_FAILURE;
        status = ::get_pc_info(m_enclave_id, &ret_val, &report, (uint8_t*)&pek, PEK_MOD_SIZE + sizeof(pek.e), ALG_RSA_OAEP_2048, encrypted_ppid, PEK_MOD_SIZE, &ret_size, &pce_info, &signature_scheme);
    }
    if(status != SGX_SUCCESS)
        return AE_FAILURE;
    if (ret_val != AE_SUCCESS)
        return ret_val;
    if(signature_scheme != NIST_P256_ECDSA_SHA256){
        return AE_FAILURE;
    }
    if(ret_size != PEK_MOD_SIZE){
        return AE_FAILURE;
    }
    pce_id = pce_info.pce_id;
    isv_svn = pce_info.pce_isvn;
    return AE_SUCCESS;
}
Exemple #23
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;
}
 uint32_t CPVEClass::gen_prov_msg1(
     pve_data_t &pve_data,
     uint8_t *msg1,
     uint32_t msg1_size)
{
    uint32_t ret = AE_SUCCESS;
    uint16_t pce_id = 0;
    uint16_t pce_isv_svn = 0;
    sgx_report_t pek_report;
    uint8_t *field2 = NULL;
    uint8_t field2_iv[IV_SIZE];
    uint8_t field2_mac[MAC_SIZE];
    uint8_t encrypted_ppid[RSA_3072_KEY_BYTES];
    //msg1 header will be in the beginning part of the output msg
    provision_request_header_t *msg1_header = reinterpret_cast<provision_request_header_t *>(msg1);
    memset(&pek_report, 0, sizeof(pek_report));
    sgx_target_info_t pce_target_info;
    sgx_status_t sgx_status;

    //Load PCE Enclave required
    ret = CPCEClass::instance().load_enclave();
    if(ret != AE_SUCCESS){
        AESM_DBG_ERROR("Fail to load PCE enclave:( ae%d)\n",ret);
        return ret;
    }
    ret = CPCEClass::instance().get_pce_target(&pce_target_info);
    if(ret != AE_SUCCESS){
        AESM_DBG_ERROR("Fail to get PCE target info:( ae %d)\n",ret);
        return ret;
    }

    //Load PvE enclave now
    ret = CPVEClass::instance().load_enclave();
    if( ret != AE_SUCCESS){
        AESM_DBG_ERROR("Fail to load PvE enclave:(ae%d)\n",ret);
        return ret;
    }
    //The code will generate a report on PEK by PvE
    ret = gen_prov_msg1_data(&pve_data.pek, &pce_target_info, &pek_report);
    if(AE_SUCCESS != ret ){
        AESM_DBG_ERROR("Gen ProvMsg1 in trusted code failed:( ae %d)",ret);
        return ret;
    }
    se_static_assert(sizeof(encrypted_ppid)==PEK_MOD_SIZE);
    //Load PCE Enclave required
    ret = CPCEClass::instance().load_enclave();
    if(ret != AE_SUCCESS){
        AESM_DBG_ERROR("Fail to load PCE enclave:( ae %d)\n",ret);
        return ret;
    }
    ret = CPCEClass::instance().get_pce_info(pek_report, pve_data.pek, pce_id,
        pce_isv_svn, encrypted_ppid);
    if(AE_SUCCESS != ret){
        AESM_DBG_ERROR("Fail to generate pc_info:(ae%d)",ret);
        return ret;
    }

    //randomly generate XID
    ret = aesm_read_rand(pve_data.xid, XID_SIZE);
    if(AE_SUCCESS != ret ){
        AESM_DBG_ERROR("Fail to generate random XID (ae%d)",ret);
        return ret;
    }
    //randomly generate SK
    ret = aesm_read_rand(pve_data.sk, SK_SIZE);
    if(AE_SUCCESS != ret ){
        AESM_DBG_ERROR("Fail to generate random SK (ae%d)",ret);
        return ret;
    }
    CPCEClass::instance().unload_enclave();
    ret = prov_msg1_gen_header(msg1_header, pve_data.is_performance_rekey, pve_data.xid, msg1_size);
    if(AE_SUCCESS != ret){
        AESM_DBG_ERROR("fail to generate ProvMsg1 Header:(ae %d)",ret);
        return ret;
    }

    {
        TLVsMsg tlvs_msg1_sub;
        tlv_status_t tlv_status;

        sgx_sha256_hash_t psid;
        tlv_status = tlvs_msg1_sub.add_block_cipher_info(pve_data.sk);
        ret = tlv_error_2_pve_error(tlv_status);
        if(AE_SUCCESS!=ret){

            AESM_DBG_ERROR("Fail to generate SK TLV of ProvMsg1 (ae %d)",ret);
            return ret;
        }
        sgx_status = sgx_sha256_msg(reinterpret_cast<const uint8_t *>(&pve_data.pek.n),
            static_cast<uint32_t>(sizeof(pve_data.pek.n) + sizeof(pve_data.pek.e)), &psid);
        if(SGX_SUCCESS != sgx_status){
            AESM_DBG_ERROR("Fail to generate PSID, (sgx0x%x)",sgx_status);
            return AE_FAILURE;
        }
        se_static_assert(sizeof(sgx_sha256_hash_t)==sizeof(psid_t));
        tlv_status = tlvs_msg1_sub.add_psid(reinterpret_cast<const psid_t *>(&psid));
        ret = tlv_error_2_pve_error(tlv_status);
        if(SGX_SUCCESS != ret){
            AESM_DBG_ERROR("Fail to add PSID TLV ae(%d)",ret);
            return ret;
        }
        //transform rsa format PEK public key of Provision Server
        void *rsa_pub_key = NULL;
        signed_pek_t le_pek{};

        // Change the endian for the PEK public key
        for(uint32_t i = 0; i< sizeof(le_pek.n); i++)
        {
        	le_pek.n[i] = pve_data.pek.n[sizeof(le_pek.n) - i - 1];
        }
        for(uint32_t i= 0; i < sizeof(le_pek.e); i++)
        {
        	le_pek.e[i] = pve_data.pek.e[sizeof(le_pek.e) - i - 1];
        }

        sgx_status = get_provision_server_rsa_pub_key(le_pek, &rsa_pub_key);
        if( SGX_SUCCESS != sgx_status){
            AESM_DBG_ERROR("Fail to decode PEK:%d",sgx_status);
            return AE_FAILURE;
        }
        uint8_t field0[RSA_3072_KEY_BYTES];
        ret = aesm_rsa_oaep_encrypt(tlvs_msg1_sub.get_tlv_msg(), tlvs_msg1_sub.get_tlv_msg_size(), rsa_pub_key, field0);
        sgx_free_rsa_key(rsa_pub_key, SGX_RSA_PUBLIC_KEY, RSA_3072_KEY_BYTES, sizeof(le_pek.e));
        if(AE_SUCCESS!=ret){
            AESM_DBG_ERROR("Fail to in RSA_OAEP for ProvMsg1:(ae%d)",ret);
            return ret;
        }
        TLVsMsg tlvs_msg1;
        tlv_status= tlvs_msg1.add_cipher_text(field0, RSA_3072_KEY_BYTES, PEK_3072_PUB);
        ret = tlv_error_2_pve_error(tlv_status);
        if(AE_SUCCESS!=ret){
            AESM_DBG_ERROR("Fail to generate field0 TLV of ProvMsg1( ae%d)",ret);
            return ret;
        }

        TLVsMsg tlvs_msg2_sub;
        tlv_status = tlvs_msg2_sub.add_cipher_text(encrypted_ppid, RSA_3072_KEY_BYTES, PEK_3072_PUB);
        ret = tlv_error_2_pve_error(tlv_status);
        if(AE_SUCCESS!=ret){
            return ret;
        }

        if(!pve_data.is_backup_retrieval){
            if(0!=memcpy_s(&pve_data.bpi.cpu_svn, sizeof(pve_data.bpi.cpu_svn),
                     &pek_report.body.cpu_svn, sizeof(pek_report.body.cpu_svn))){
                AESM_DBG_FATAL("fail in memcpy_s");
                return PVE_UNEXPECTED_ERROR;
            }
            if(0!=memcpy_s(&pve_data.bpi.pve_svn, sizeof(pve_data.bpi.pve_svn),
                     &pek_report.body.isv_svn, sizeof(pek_report.body.isv_svn))){
                AESM_DBG_FATAL("fail in memcpy_s");
                return PVE_UNEXPECTED_ERROR;
            }
            if(0!=memcpy_s(&pve_data.bpi.pce_svn, sizeof(pve_data.bpi.pce_svn),
                     &pce_isv_svn, sizeof(pce_isv_svn))){
                AESM_DBG_FATAL("fail in memcpy_s");
                return PVE_UNEXPECTED_ERROR;
            }
        }
        //always use pce_id from PCE enclave
        pve_data.bpi.pce_id = pce_id;
        memset(&pve_data.bpi.fmsp, 0, sizeof(pve_data.bpi.fmsp));
        tlv_status = tlvs_msg2_sub.add_platform_info(pve_data.bpi);
        ret = tlv_error_2_pve_error(tlv_status);
        if(AE_SUCCESS != ret){
            AESM_DBG_ERROR("Fail to generate Platform Info TLV of ProvMsg1 (ae%d)",ret);
            return ret;
        }
        if(pve_data.is_performance_rekey){
            flags_t flags;
            memset(&flags,0,sizeof(flags));
            //set performance rekey flags
            flags.flags[FLAGS_SIZE-1]=1;
            tlv_status = tlvs_msg2_sub.add_flags(&flags);
            ret = tlv_error_2_pve_error(tlv_status);
            if(AE_SUCCESS != ret){
                AESM_DBG_ERROR("Fail to generate FLAGS TLV of ProvMsg1, (ae %d)",ret);
                return ret;
            }
        }

        ret = aesm_read_rand(field2_iv, IV_SIZE);
        if(AE_SUCCESS != ret){
            AESM_DBG_ERROR("Fail to read rand:(ae%d)",ret);
            return ret;
        }
        sgx_cmac_128bit_tag_t ek1;
        se_static_assert(SK_SIZE==sizeof(sgx_cmac_128bit_key_t));
        if((sgx_status = sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(pve_data.sk),
             pve_data.xid, XID_SIZE, &ek1))!=SGX_SUCCESS){
                 AESM_DBG_ERROR("Fail to generate ek1:(sgx%d)",sgx_status);
                 return AE_FAILURE;
        }

        field2 = (uint8_t *)malloc(tlvs_msg2_sub.get_tlv_msg_size());
        if(NULL == field2){
            AESM_DBG_ERROR("Out of memory");
            return AE_OUT_OF_MEMORY_ERROR;
        }


        sgx_status = sgx_rijndael128GCM_encrypt(&ek1,
            tlvs_msg2_sub.get_tlv_msg(), tlvs_msg2_sub.get_tlv_msg_size(),
            field2,field2_iv, IV_SIZE, (const uint8_t *)msg1_header, sizeof(provision_request_header_t),
            (sgx_aes_gcm_128bit_tag_t *)field2_mac);
        if(SGX_SUCCESS != sgx_status){
            ret = sgx_error_to_ae_error(sgx_status);
            AESM_DBG_ERROR("Fail to do AES encrypt (sgx %d)", sgx_status);
            free(field2);
            return ret;
        }

        tlv_status = tlvs_msg1.add_block_cipher_text(field2_iv, field2, tlvs_msg2_sub.get_tlv_msg_size());
        ret = tlv_error_2_pve_error(tlv_status);
        if(AE_SUCCESS!=ret){
            free(field2);
            AESM_DBG_ERROR("Fail to generate field1 TLV of ProvMsg1(ae%d)",ret);
            return ret;
        }

        free(field2);
        tlv_status = tlvs_msg1.add_mac(field2_mac);
        ret = tlv_error_2_pve_error(tlv_status);
        if(AE_SUCCESS!=ret){
            AESM_DBG_ERROR("Fail to create field2 TLV of ProvMsg1:(ae %d)",ret);
            return ret;
        }
        uint32_t size = tlvs_msg1.get_tlv_msg_size();
        if(memcpy_s(msg1+PROVISION_REQUEST_HEADER_SIZE, msg1_size - PROVISION_REQUEST_HEADER_SIZE,
            tlvs_msg1.get_tlv_msg(), size)!=0){
                //The size overflow has been checked in header generation
                AESM_DBG_FATAL("fail in memcpy_s");
                return PVE_UNEXPECTED_ERROR;
        }
    }
    return AE_SUCCESS;
}
Exemple #25
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;
}
Exemple #26
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;
}
ae_error_t ConvertBackendStatus(CertificateProvisioningProtocol& cpp, ae_error_t status)
{
    if (AE_FAILED(status))
    {
        if (PSE_PRS_OK != cpp.GetProtocolResponseStatus())
        {
            SGX_DBGPRINT_ONE_STRING_ONE_INT("Backend ProtocolResponseStatus", cpp.GetProtocolResponseStatus());
            switch (cpp.GetProtocolResponseStatus())
            {
            case PSE_PRS_INVALID_GID:       status = AESM_PSE_PR_BACKEND_INVALID_GID;               break;
            case PSE_PRS_GID_REVOKED:       status = AESM_PSE_PR_BACKEND_GID_REVOKED;               break;
            case PSE_PRS_INVALID_QUOTE:     status = AESM_PSE_PR_BACKEND_INVALID_QUOTE;             break;
            case PSE_PRS_INVALID_REQUEST:   status = AESM_PSE_PR_BACKEND_INVALID_REQUEST;           break;
            default:                        status = AESM_PSE_PR_BACKEND_UNKNOWN_PROTOCOL_RESPONSE; break;
            }
            AESM_DBG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_PROTOCOL_RESPONSE_FAILURE], status);
            AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_PROTOCOL_RESPONSE_FAILURE], status);
        }
        else if (GRS_OK != cpp.GetGeneralResponseStatus())
        {
            SGX_DBGPRINT_ONE_STRING_ONE_INT("Backend GeneralResponseStatus", cpp.GetGeneralResponseStatus());
            switch (cpp.GetGeneralResponseStatus())
            {
            case GRS_SERVER_BUSY:               status = AESM_PSE_PR_BACKEND_SERVER_BUSY;               break;
            case GRS_INTEGRITY_CHECK_FAIL:      status = AESM_PSE_PR_BACKEND_INTEGRITY_CHECK_FAIL;      break;
            case GRS_INCORRECT_SYNTAX:          status = AESM_PSE_PR_BACKEND_INCORRECT_SYNTAX;          break;
            case GRS_INCOMPATIBLE_VERSION:      status = PSW_UPDATE_REQUIRED;                           break;
            case GRS_TRANSACTION_STATE_LOST:    status = AESM_PSE_PR_BACKEND_TRANSACTION_STATE_LOST;    break;
            case GRS_PROTOCOL_ERROR:            status = AESM_PSE_PR_BACKEND_PROTOCOL_ERROR;            break;
            case GRS_INTERNAL_ERROR:            status = AESM_PSE_PR_BACKEND_INTERNAL_ERROR;            break;
            default:                            status = AESM_PSE_PR_BACKEND_UNKNOWN_PROTOCOL_RESPONSE; break;
            }
            AESM_DBG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_GENERAL_RESPONSE_FAILURE], status);
            AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_GENERAL_RESPONSE_FAILURE], status);
        }
        else
        {
            switch (status)
            {
            case OAL_NETWORK_UNAVAILABLE_ERROR:
                {
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_FAILURE]);
                    break;
                }
            case PSE_PAIRING_BLOB_UNSEALING_ERROR:
                {
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_LTP_BLOB_INTEGRITY_ERROR]);
                    break;
                }
            case PSE_PAIRING_BLOB_INVALID_ERROR:
                {
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_LTP_BLOB_INVALID_ERROR]);
                    break;
                }
            case AESM_PSE_PR_BACKEND_MSG4_PLATFORM_INFO_BLOB_SIZE:
                {
                    //
                    // happens if pib returned is not the right size
                    //
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_PROTOCOL_RESPONSE_FAILURE]);
                    break;
                }
            case AE_FAILURE:
                {
                    //
                    // happens if problem with proxy setting
                    //
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_CERT_PROV_FAILURE]);
                    break;
                }
            case AESM_CP_ATTESTATION_FAILURE:
                {
                    AESM_LOG_ERROR(g_event_string_table[SGX_EVENT_PSE_ATTESTATION_ERROR]);
                    break;
                }
            default:
                {
                    AESM_DBG_ERROR("Error in ConvertBackendStatus(status) : status = %d (%xh)", status, status);
                    break;
                }
            }
        }
    }

    return status;
}
//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;
}
Exemple #29
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;
}
Exemple #30
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;
}