Example #1
0
// Returns the pointer to the Enclave instance on success.
uintptr_t _ECREATE(page_info_t* pi)
{
    secs_t* secs = reinterpret_cast<secs_t*>(pi->src_page);

    // Enclave size must be at least 2 pages and a power of 2.
    GP_ON(!is_power_of_two((size_t)secs->size));
    GP_ON(secs->size < (SE_PAGE_SIZE << 1));

    CEnclaveSim* ce = new CEnclaveSim(secs);
    void*   addr;

    // `ce' is not checked against NULL, since it is not
    // allocated with new(std::no_throw).
    addr = se_virtual_alloc(NULL, (size_t)secs->size, MEM_COMMIT);
    if (addr == NULL) {
        delete ce;
        return 0;
    }

    // Mark all the memory inaccessible.
    se_virtual_protect(addr, (size_t)secs->size, SGX_PROT_NONE);
    ce->get_secs()->base = addr;

    CEnclaveMngr::get_instance()->add(ce);
    return reinterpret_cast<uintptr_t>(ce);
}
Example #2
0
int add_enclave_page(sgx_enclave_id_t enclave_id,
                     void             *source,
                     size_t           offset,
                     const sec_info_t &secinfo,
                     uint32_t         attr)
{
    sec_info_t   sinfo;
    page_info_t  pinfo;
    CEnclaveMngr *mngr;
    CEnclaveSim  *ce;

    UNUSED(attr);

    mngr = CEnclaveMngr::get_instance();
    ce = mngr->get_enclave(enclave_id);
    if (ce == NULL) {
        SE_TRACE(SE_TRACE_DEBUG,
                 "enclave (id = %llu) not found.\n",
                 enclave_id);
        return SGX_ERROR_INVALID_ENCLAVE_ID;
    }
    memset(&sinfo, 0, sizeof(sec_info_t));
    sinfo.flags = secinfo.flags;
    if(memcmp(&sinfo, &secinfo, sizeof(sec_info_t)))
        return SGX_ERROR_UNEXPECTED;

    memset(&pinfo, 0, sizeof(pinfo));
    pinfo.secs     = ce->get_secs();
    pinfo.lin_addr = (char*)ce->get_secs()->base + offset;
    pinfo.src_page = source;
    pinfo.sec_info = &sinfo;

    /* Passing NULL here when there is no EPC mgmt. */
    return (int)DoEADD_SW(&pinfo, GET_PTR(void, ce->get_secs()->base, offset));
}
Example #3
0
/* Allocate linear address space. */
int create_enclave(secs_t           *secs,
                   sgx_enclave_id_t *enclave_id,
                   void             **start_addr)
{
    CEnclaveSim   *ce;
    sec_info_t    sinfo;
    page_info_t   pinfo;

    BUG_ON(secs == NULL, SGX_ERROR_UNEXPECTED);
    BUG_ON(enclave_id == NULL, SGX_ERROR_UNEXPECTED);
    BUG_ON(start_addr == NULL, SGX_ERROR_UNEXPECTED);

    memset(&sinfo, 0, sizeof(sinfo));
    sinfo.flags = SI_FLAGS_SECS;

    memset(&pinfo, 0, sizeof(pinfo));
    pinfo.src_page = secs;
    pinfo.sec_info = &sinfo;

    ce = reinterpret_cast<CEnclaveSim*>(DoECREATE_SW(&pinfo));
    if (ce == NULL) {
        SE_TRACE(SE_TRACE_DEBUG, "out of memory.\n");
        return SGX_ERROR_OUT_OF_MEMORY;
    }

    *start_addr = ce->get_secs()->base;
    *enclave_id = ce->get_enclave_id();
    secs->base = *start_addr;

    return SGX_SUCCESS;
}
Example #4
0
uintptr_t _EREMOVE(const void *epc_lin_addr)
{
    CEnclaveMngr *mngr = CEnclaveMngr::get_instance();
    CEnclaveSim *ce = mngr->get_enclave(epc_lin_addr);

    GP_ON(!ce);
    GP_ON(!IS_PAGE_ALIGNED(epc_lin_addr));

    return ce->remove_page(epc_lin_addr) ? 0 : -1;
}
Example #5
0
uintptr_t _EINIT(secs_t* secs, enclave_css_t *css, token_t *launch)
{
    CEnclaveMngr *mngr = CEnclaveMngr::get_instance();
    assert(mngr != NULL);

    CEnclaveSim* ce = mngr->get_enclave(secs);
    GP_ON(ce == NULL);

    GP_ON((ce->get_secs()->attributes.flags & SGX_FLAGS_INITTED) != 0);

    // Fill MREnclave, MRSigner, ISVPRODID, ISVSVN
    secs_t* this_secs = ce->get_secs();
    if (css != NULL) {
        // Check signature
        if ((css->body.attribute_mask.xfrm & this_secs->attributes.xfrm)
            != (css->body.attribute_mask.xfrm & css->body.attributes.xfrm))
        {
            SE_TRACE(SE_TRACE_DEBUG,
                "SECS attributes.xfrm does NOT match signature attributes.xfrm\n");
            return SGX_ERROR_INVALID_ATTRIBUTE;
        }

        if ((css->body.attribute_mask.flags & this_secs->attributes.flags)
            != (css->body.attribute_mask.flags & css->body.attributes.flags))
        {
            SE_TRACE(SE_TRACE_DEBUG,
                "SECS attributes.flag does NOT match signature attributes.flag\n");
            return SGX_ERROR_INVALID_ATTRIBUTE;
        }

        mcp_same_size(&this_secs->mr_enclave, &css->body.enclave_hash, sizeof(sgx_measurement_t));
        this_secs->isv_prod_id = css->body.isv_prod_id;
        this_secs->isv_svn = css->body.isv_svn;

        ippsHashMessage(css->key.modulus, SE_KEY_SIZE, (Ipp8u*)&this_secs->mr_signer, IPP_ALG_HASH_SHA256);
    }

    // Check launch token
    if (launch != NULL && launch->body.valid) {
        if (memcmp(&launch->body.attributes, &this_secs->attributes, sizeof(sgx_attributes_t)))
        {
            SE_TRACE(SE_TRACE_DEBUG,
                "SECS attributes does NOT match launch token attribuets\n");
            return SGX_ERROR_INVALID_ATTRIBUTE;
        }
    }

    // Mark it initialized
    this_secs->attributes.flags |= SGX_FLAGS_INITTED;

    return SGX_SUCCESS;
}
Example #6
0
int init_enclave(sgx_enclave_id_t  enclave_id,
                 enclave_css_t     *enclave_css,
                 token_t           *launch)
{
    CEnclaveMngr* mngr = CEnclaveMngr::get_instance();
    CEnclaveSim* ce = mngr->get_enclave(enclave_id);

    if (ce == NULL) {
        SE_TRACE(SE_TRACE_DEBUG,
                 "enclave (id = %llu) not found.\n",
                 enclave_id);
        return SGX_ERROR_INVALID_ENCLAVE_ID;
    }

    return (int)DoEINIT_SW(ce->get_secs(), enclave_css, launch);
}
Example #7
0
int destroy_enclave(sgx_enclave_id_t enclave_id)
{
    CEnclaveMngr* mngr = CEnclaveMngr::get_instance();
    CEnclaveSim* ce = mngr->get_enclave(enclave_id);
    if (ce == NULL) {
        SE_TRACE(SE_TRACE_DEBUG,
                 "enclave (id = %llu) not found.\n",
                 enclave_id);
        return SGX_ERROR_INVALID_ENCLAVE_ID;
    }

    /* In simulation mode, all allocated pages will be freed upon the later
       `delete ce'.  Just remove the first page here. */
    DoEREMOVE_SW(0, ce->get_secs()->base);

    mngr->remove(ce);
    delete ce;

    return SGX_SUCCESS;
}
Example #8
0
uintptr_t _EADD(page_info_t* pi, void *epc_lin_addr)
{
    void     *src_page = pi->src_page;
    CEnclaveMngr *mngr = CEnclaveMngr::get_instance();
    CEnclaveSim    *ce = mngr->get_enclave(pi->lin_addr);

    if (ce == NULL) {
        SE_TRACE(SE_TRACE_DEBUG, "failed to get enclave instance\n");
        return SGX_ERROR_UNEXPECTED;
    }

    GP_ON(!IS_PAGE_ALIGNED(epc_lin_addr));
    GP_ON((ce->get_secs()->attributes.flags & SGX_FLAGS_INITTED) != 0);

    // Make the page writable before doing memcpy()
    se_virtual_protect(epc_lin_addr, SE_PAGE_SIZE, SI_FLAGS_RW);

    mcp_same_size(epc_lin_addr, src_page, SE_PAGE_SIZE);

    se_virtual_protect(epc_lin_addr, SE_PAGE_SIZE, (uint32_t)pi->sec_info->flags);

    GP_ON(!ce->add_page(pi->lin_addr, pi->sec_info->flags));
    return SGX_SUCCESS;
}
Example #9
0
void _SE3(uintptr_t xax, uintptr_t xbx,
          uintptr_t xcx, uintptr_t xdx,
          uintptr_t xsi, uintptr_t xdi)
{
    UNUSED(xdx);

    switch (xax)
    {
    case SE_EENTER:
        uintptr_t     xip;
        void        * enclave_base_addr;
        se_pt_regs_t* p_pt_regs;
        tcs_t*        tcs;
        tcs_sim_t*    tcs_sim;
        ssa_gpr_t*    p_ssa_gpr;
        secs_t*       secs;
        CEnclaveMngr* mngr;
        CEnclaveSim*    ce;

        // xbx contains the address of a TCS
        tcs = reinterpret_cast<tcs_t*>(xbx);

        // Is TCS pointer page-aligned?
        GP_ON_EENTER(!IS_PAGE_ALIGNED(tcs));

        mngr = CEnclaveMngr::get_instance();
        assert(mngr != NULL);

        // Is it really a TCS?
        ce = mngr->get_enclave(tcs);
        GP_ON_EENTER(ce == NULL);
        GP_ON_EENTER(!ce->is_tcs_page(tcs));

        // Check the EntryReason
        tcs_sim = reinterpret_cast<tcs_sim_t *>(tcs->reserved);
        GP_ON_EENTER(tcs_sim->tcs_state != TCS_STATE_INACTIVE);
        GP_ON_EENTER(tcs->cssa >= tcs->nssa);

        secs = ce->get_secs();
        enclave_base_addr = secs->base;

        p_ssa_gpr = reinterpret_cast<ssa_gpr_t*>(reinterpret_cast<uintptr_t>(enclave_base_addr) + static_cast<size_t>(tcs->ossa)
                + secs->ssa_frame_size * SE_PAGE_SIZE
                - sizeof(ssa_gpr_t));

        tcs_sim->saved_aep = xcx;

        p_pt_regs = reinterpret_cast<se_pt_regs_t*>(get_bp());
        p_ssa_gpr->REG(bp_u) = p_pt_regs->xbp;

        p_ssa_gpr->REG(sp_u) = reinterpret_cast<uintptr_t>(p_pt_regs + 1);
        xcx = p_pt_regs->xip;

        xip = reinterpret_cast<uintptr_t>(enclave_base_addr);
        GP_ON_EENTER(xip == 0);

        //set the _tls_array to point to the self_addr of TLS section inside the enclave
        GP_ON_EENTER(td_mngr_set_td(enclave_base_addr, tcs) == false);
 
        // Destination depends on STATE
        xip += (uintptr_t)tcs->oentry;
        tcs_sim->tcs_state = TCS_STATE_ACTIVE;

        // Link the TCS to the thread
        GP_ON_EENTER((secs->attributes.flags & SGX_FLAGS_INITTED) == 0);

        // Replace the return address on the stack with the enclave entry,
        // so that when we return from this function, we'll enter the enclave.
        enclu_regs_t regs;
        regs.xax = tcs->cssa;
        regs.xbx = reinterpret_cast<uintptr_t>(tcs);
        regs.xcx = xcx;
        regs.xdx = 0;
        regs.xsi = xsi;
        regs.xdi = xdi;
        regs.xbp = p_ssa_gpr->REG(bp_u);
        regs.xsp = p_ssa_gpr->REG(sp_u);
        regs.xip = xip;

        load_regs(&regs);

        // Returning from this function enters the enclave
        return;
    default:
        // There's only 1 ring 3 instruction outside the enclave: EENTER.
        GP();
    }
}