SealedData Source Code Analysis

DRM_enclave.edl

DRM_enclave.edl import sgx_tae_service.edl and add six trusted functions.

enclave {
	from "sgx_tae_service.edl" import *;
    trusted {
        /* define ECALLs here. */
        public uint32_t create_sealed_policy([out, size=sealed_log_size]
            uint8_t* sealed_log, uint32_t sealed_log_size );
        public uint32_t perform_sealed_policy([in, size=sealed_log_size]
            const uint8_t* sealed_log, uint32_t sealed_log_size);
        public uint32_t update_sealed_policy([in,out, size=sealed_log_size]
            uint8_t* sealed_log, uint32_t sealed_log_size);
        public uint32_t delete_sealed_policy([in, size=sealed_log_size]
            const uint8_t* sealed_log, uint32_t sealed_log_size);
        public uint32_t create_time_based_policy([out, size=sealed_log_size]
            uint8_t* sealed_log, uint32_t sealed_log_size );
        public uint32_t perform_time_based_policy([in, size=sealed_log_size]
            const uint8_t* sealed_log, uint32_t sealed_log_size );
    };
};

sgx_tae_service.edl

enclave{
    from "sgx_tstdc.edl" import *;
    untrusted {
        sgx_status_t create_session_ocall([out] uint32_t* sid,
                                 [size = dh_msg1_size, out] uint8_t* dh_msg1,
                                 uint32_t dh_msg1_size,
                                 uint32_t timeout);

        sgx_status_t exchange_report_ocall(uint32_t sid,
                                 [size = dh_msg2_size, in] uint8_t* dh_msg2, uint32_t dh_msg2_size,
                                 [size = dh_msg3_size, out] uint8_t* dh_msg3, uint32_t dh_msg3_size,
                                 uint32_t timeout);

        sgx_status_t close_session_ocall(uint32_t sid, uint32_t timeout);

        sgx_status_t invoke_service_ocall([size = pse_message_req_size, in] uint8_t* pse_message_req,
                                 uint32_t pse_message_req_size,
                                 [size = pse_message_resp_size, out] uint8_t* pse_message_resp, uint32_t pse_message_resp_size,
                                 uint32_t timeout);
   };
};

sgx_tstdc.edl

sgx_tstdc.edl defines 5 untrusted functions. cdecl调用约定是C标准的默认方式,OCALLs的函数调用约定.

enclave {
    untrusted {
        [cdecl] void sgx_oc_cpuidex([out] int cpuinfo[4], int leaf, int subleaf);
        
        /* Go outside and wait on my untrusted event */
        [cdecl] int sgx_thread_wait_untrusted_event_ocall([user_check] const void *self);

        /* Wake a thread waiting on its untrusted event */
        [cdecl] int sgx_thread_set_untrusted_event_ocall([user_check] const void *waiter);

        /* Wake a thread waiting on its untrusted event, and wait on my untrusted event */
        [cdecl] int sgx_thread_setwait_untrusted_events_ocall([user_check] const void *waiter, [user_check] const void *self);

        /* Wake multiple threads waiting on their untrusted events */
        [cdecl] int sgx_thread_set_multiple_untrusted_events_ocall([in, count = total] const void **waiters, size_t total);
    };
};

DRM_app.cpp

DRM_app.cpp calls 5 functions start with test_.

#define _T(x) x
int main(int argc, char* argv[])
{
    (void)argc; /* unused parameter */
    (void)argv; /* unused parameter */

    /* normal operation */
    test_replay_protected_drm_operation();
    /* trigger update limitation */
    test_replay_protected_drm_update_limitation();
    /* replay attack */
    test_replay_protected_drm_replay_attack_protection();
    /* normal operation */
    test_time_based_policy_operation();
    /* trigger expiration */
    test_time_based_policy_expiration();
    
    printf("Enter a character before exit ...\n");
    getchar();
    return 0;
}

test_replay_protected_drm_operation

The function test_replay_protected_drm_operation introduces ReplayProtectedDRM.

uint32_t test_replay_protected_drm_operation()
{
    cout<<endl<<"\tReplay Protected DRM operation:"<<endl;
    uint32_t result = 0;
    ReplayProtectedDRM DRM;
    result = DRM.init();
    if(result)
    {
        cerr<<"Initialization the DRM failed."<<endl;
        return result;
    }
    else 
        cout<<"Successfully initialized the DRM."<<endl;

    do{
        result = DRM.perform_function();
        if(result)
        {
            cerr<<"Performing the DRM functions failed."<<endl;
            break;
        }
        else
            cout<<"Successfully performed the DRM functions."<<endl;

        result = DRM.update_secret();
        if(result)
        {
            cerr<<"Updating the DRM secret failed."<<endl;
            break;
        }
        else
            cout<<"Successfully updated the DRM secret."<<endl;

        result = DRM.perform_function();
        if(result)
        {
            cerr<<"Performing the DRM functions failed."<<endl;
            break;
        }
        else
            cout<<"Successfully performed the DRM functions."<<endl;

    }while(0);

    if(DRM.delete_secret())
    {
        cerr<<"Deleting the DRM secret failed."<<endl;
        return result;
    }
    else
        cout<<"Successfully deleted the DRM secret."<<endl;
    return result;
}
The constructor of ReplayProtectedDRM.
ReplayProtectedDRM::ReplayProtectedDRM(): enclave_id(0)
{
    sgx_status_t sgx_ret = SGX_ERROR_UNEXPECTED;
    sgx_ret = sgx_create_enclave(ENCLAVE_NAME, SGX_DEBUG_FLAG,
        NULL, NULL, &enclave_id, NULL);
    if (sgx_ret)
    {
        cerr<<"cannot create enclave, error code = 0x"<< hex<< sgx_ret <<endl;
    }
}
At first, it calls result = DRM.init();
   #define SEALED_REPLAY_PROTECTED_PAY_LOAD_SIZE 620
    static const uint32_t sealed_activity_log_length = SEALED_REPLAY_PROTECTED_PAY_LOAD_SIZE;
    uint8_t  sealed_activity_log[sealed_activity_log_length];
    
uint32_t ReplayProtectedDRM:: init()
{
    return init(sealed_activity_log);
}

init(uint8_t* stored_sealed_activity_log)
uint32_t ReplayProtectedDRM:: init(uint8_t*  stored_sealed_activity_log)
{
    sgx_status_t sgx_ret = SGX_ERROR_UNEXPECTED;
    sgx_ps_cap_t ps_cap;
    memset(&ps_cap, 0, sizeof(sgx_ps_cap_t));
    sgx_ret = sgx_get_ps_cap(&ps_cap);
    if (sgx_ret)
    {
        cerr<<"cannot get platform service capability, error code = 0x"<< hex
            << sgx_ret <<endl;
        return sgx_ret;
    }
    if (!SGX_IS_MONOTONIC_COUNTER_AVAILABLE(ps_cap))
    {
        cerr<<"monotonic counter is not supported"<<endl;
        return SGX_ERROR_SERVICE_UNAVAILABLE;
    }
    uint32_t enclave_ret = 0;
    sgx_ret = create_sealed_policy(enclave_id, &enclave_ret,
        (uint8_t *)stored_sealed_activity_log, sealed_activity_log_length);
    if (sgx_ret)
    {
        cerr<<"call create_sealed_policy fail, error code = 0x"<< hex<< sgx_ret
            <<endl;
        return sgx_ret;
    } 
    if (enclave_ret)
    {
        cerr<<"cannot create_sealed_policy, function return fail, error code ="
            "0x"<< hex<< enclave_ret <<endl;
        return enclave_ret;
    }
    return 0;
}
call sgx_get_ps_cap from sgx_uae_service.h
/**
 * Get the platform service capabilities
 *
 * @param sgx_ps_cap Platform capabilities reported by AESM.
 * @return if OK, return SGX_SUCCESS
 */
sgx_status_t SGXAPI sgx_get_ps_cap(sgx_ps_cap_t* p_sgx_ps_cap);
create_sealed_policy defines in DRM_enclave.edl, implemented in DRM_enclave.cpp
uint32_t create_sealed_policy(uint8_t* sealed_log, uint32_t sealed_log_size )
{
    uint32_t ret = 0;
    int busy_retry_times = 2;
    replay_protected_pay_load data2seal;
    memset(&data2seal, 0, sizeof(data2seal));
    uint32_t size = sgx_calc_sealed_data_size(0,
        sizeof(replay_protected_pay_load));
    if(sealed_log_size != size) 
        return SGX_ERROR_INVALID_PARAMETER;
    do{
        ret = sgx_create_pse_session();
    }while (ret == SGX_ERROR_BUSY && busy_retry_times--);
    if (ret != SGX_SUCCESS)
        return ret;
    do
    {
        ret = sgx_create_monotonic_counter(&data2seal.mc,&data2seal.mc_value);
        if(ret != SGX_SUCCESS)
        {
            switch(ret)
            {
            case SGX_ERROR_SERVICE_UNAVAILABLE:
                /* Architecture Enclave Service Manager is not installed or not
                working properly.*/
                break;
            case SGX_ERROR_SERVICE_TIMEOUT:
                /* retry the operation later*/
                break;
            case SGX_ERROR_BUSY:
                /* retry the operation later*/
                break;
            case SGX_ERROR_MC_OVER_QUOTA:
                /* SGX Platform Service enforces a quota scheme on the Monotonic
                Counters a SGX app can maintain. the enclave has reached the
                quota.*/
                break;
            case SGX_ERROR_MC_USED_UP:
                /* the Monotonic Counter has been used up and cannot create
                Monotonic Counter anymore.*/
                break;
            default:
                /*other errors*/
                break;
            }
            break;
        }

        /* secret should be provisioned into enclave after the enclave attests to
        the secret owner.
        For example, the server that delivers the encrypted DRM content.
        In this sample code, a random number is used to represent the secret */ 
        ret = sgx_read_rand(data2seal.secret, REPLAY_PROTECTED_SECRET_SIZE);
        if(ret != SGX_SUCCESS)
            break;
        data2seal.log.release_version = 0;
        /* the secret can be updated for 5 times */
        data2seal.log.max_release_version = 
            REPLAY_PROTECTED_PAY_LOAD_MAX_RELEASE_VERSION;

        /*sealing the plaintext to ciphertext. The ciphertext can be delivered
        outside of enclave.*/
        ret = sgx_seal_data(0, NULL,sizeof(data2seal),(uint8_t*)&data2seal,
            sealed_log_size, (sgx_sealed_data_t*)sealed_log);
    } while (0);
    
    /* remember to clear secret data after been used by memset_s */
    memset_s(&data2seal, sizeof(replay_protected_pay_load), 0,
        sizeof(replay_protected_pay_load));
    sgx_close_pse_session();
    return ret;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值