extern "C" bool read_cpusvn_file(const char *config_path, sgx_cpu_svn_t *cpusvn_ptr) { if(config_path == NULL || cpusvn_ptr == NULL) return false; FILE *fp = NULL; long fsize = 0; sgx_cpu_svn_t temp_cpusvn = {{0}}; size_t result = 0; if(NULL == (fp = fopen(config_path, "rb"))) { SE_TRACE(SE_TRACE_DEBUG, "Couldn't find/open the configuration file %s.\n", config_path); memcpy_s(cpusvn_ptr, sizeof(sgx_cpu_svn_t), &DEFAULT_CPUSVN, sizeof(DEFAULT_CPUSVN)); return true; } //check and read configure file format if(fseek(fp, 0, SEEK_END)) { memcpy_s(&temp_cpusvn, sizeof(temp_cpusvn), &DEFAULT_CPUSVN, sizeof(DEFAULT_CPUSVN)); goto clean_return; } fsize = ftell(fp); rewind(fp); if(fsize != sizeof(sgx_cpu_svn_t)) { SE_TRACE(SE_TRACE_DEBUG, "The configuration file format is not correct. Using default CPUSVN value.\n"); memcpy_s(&temp_cpusvn, sizeof(temp_cpusvn), &DEFAULT_CPUSVN, sizeof(DEFAULT_CPUSVN)); goto clean_return; } result = fread(&temp_cpusvn, 1, fsize, fp); if(result != (size_t)fsize) { SE_TRACE(SE_TRACE_DEBUG, "Failed to read configuration file. Using default CPUSVN value.\n"); memcpy_s(&temp_cpusvn, sizeof(temp_cpusvn), &DEFAULT_CPUSVN, sizeof(DEFAULT_CPUSVN)); goto clean_return; } if(memcmp(&temp_cpusvn, &DEFAULT_CPUSVN, sizeof(DEFAULT_CPUSVN)) && memcmp(&temp_cpusvn, &UPGRADED_CPUSVN, sizeof(UPGRADED_CPUSVN)) && memcmp(&temp_cpusvn, &DOWNGRADED_CPUSVN, sizeof(DOWNGRADED_CPUSVN))) { SE_TRACE(SE_TRACE_DEBUG, "The configuration file format is not correct. Using default CPUSVN value.\n"); memcpy_s(&temp_cpusvn, sizeof(temp_cpusvn), &DEFAULT_CPUSVN, sizeof(DEFAULT_CPUSVN)); goto clean_return; } clean_return: fclose(fp); memcpy_s(cpusvn_ptr, sizeof(*cpusvn_ptr), &temp_cpusvn, sizeof(temp_cpusvn)); return true; }
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; }
static long int set_regset(pid_t pid, void* addr, void* data) { int ret = 0; unsigned long type = (unsigned long)addr; if(!data) return -1; struct user_regs_struct regs; if(-1 == (ret = g_sys_ptrace(PTRACE_GETREGS, pid, 0, ®s))) return -1; if(is_eresume(pid, ®s)) { if(NT_X86_XSTATE != type) { SE_TRACE(SE_TRACE_WARNING, "unexpected type for PTRACE_SETREGSET\n"); return -1; } struct iovec *iov = (struct iovec *)data; if(iov->iov_base && iov->iov_len && set_ssa_xstate(pid, regs.REG(bx), iov->iov_len, (char *)iov->iov_base)) { return 0; } else return -1; } else { return g_sys_ptrace(PTRACE_SETREGSET, pid, addr, data); } }
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)); }
/* 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; }
int EnclaveCreatorHW::error_api2urts(uint32_t api_error) { int ret = SGX_ERROR_UNEXPECTED; switch(api_error) { case ENCLAVE_ERROR_SUCCESS: ret = SGX_SUCCESS; break; case ENCLAVE_NOT_SUPPORTED: ret = SGX_ERROR_NO_DEVICE; break; case ENCLAVE_INVALID_SIG_STRUCT: case ENCLAVE_INVALID_SIGNATURE: ret = SGX_ERROR_INVALID_SIGNATURE; break; case ENCLAVE_INVALID_ATTRIBUTE: ret = SGX_ERROR_INVALID_ATTRIBUTE; break; case ENCLAVE_NOT_AUTHORIZED: ret = SGX_ERROR_SERVICE_INVALID_PRIVILEGE; break; case ENCLAVE_INVALID_MEASUREMENT: ret = SE_ERROR_INVALID_MEASUREMENT; break; case ENCLAVE_INVALID_ENCLAVE: ret = SGX_ERROR_INVALID_ENCLAVE; break; case ENCLAVE_LOST: ret = SGX_ERROR_ENCLAVE_LOST; break; case ENCLAVE_INVALID_PARAMETER: ret = SGX_ERROR_INVALID_PARAMETER; break; case ENCLAVE_OUT_OF_MEMORY: case ENCLAVE_DEVICE_NO_RESOURCES: ret = SGX_ERROR_OUT_OF_MEMORY; break; case ENCLAVE_SERVICE_TIMEOUT: ret = SGX_ERROR_SERVICE_TIMEOUT; break; default: SE_TRACE(SE_TRACE_WARNING, "unexpected error %#x from enclave common api, should be uRTS/driver bug\n", api_error); ret = SGX_ERROR_UNEXPECTED; break; } return ret; }
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); }
int EnclaveCreatorHW::mktcs(uint64_t tcs_addr) { sgx_range params; memset(¶ms, 0 ,sizeof(sgx_range)); params.start_addr = (unsigned long)tcs_addr; params.nr_pages = 1; int ret = ioctl(m_hdevice, SGX_IOC_ENCLAVE_MKTCS, ¶ms); if (ret) { SE_TRACE(SE_TRACE_ERROR, "MODIFY_TYPE failed %d\n", errno); return error_driver2urts(ret); } return SGX_SUCCESS; }
int EnclaveCreatorHW::emodpr(uint64_t addr, uint64_t size, uint64_t flag) { sgx_modification_param params; memset(¶ms, 0 ,sizeof(sgx_modification_param)); params.range.start_addr = (unsigned long)addr; params.range.nr_pages = (unsigned int)(size/SE_PAGE_SIZE); params.flags = (unsigned long)flag; int ret = ioctl(m_hdevice, SGX_IOC_ENCLAVE_EMODPR, ¶ms); if (ret) { SE_TRACE(SE_TRACE_ERROR, "SGX_IOC_ENCLAVE_EMODPR failed %d\n", errno); return error_driver2urts(ret); } return SGX_SUCCESS; }
int EnclaveCreatorHW::trim_range(uint64_t fromaddr, uint64_t toaddr) { sgx_range params; memset(¶ms, 0 ,sizeof(sgx_range)); params.start_addr = (unsigned long)fromaddr; params.nr_pages = (unsigned int)((toaddr - fromaddr)/SE_PAGE_SIZE); int ret= ioctl(m_hdevice, SGX_IOC_ENCLAVE_TRIM, ¶ms); if (ret) { SE_TRACE(SE_TRACE_ERROR, "SGX_IOC_ENCLAVE_TRIM failed %d\n", errno); return error_driver2urts(ret); } return SGX_SUCCESS; }
int EnclaveCreatorHW::error_driver2urts(int driver_error) { int ret = SGX_ERROR_UNEXPECTED; switch(driver_error) { case SGX_INVALID_ATTRIBUTE: ret = SGX_ERROR_INVALID_ATTRIBUTE; break; case SGX_INVALID_PRIVILEGE: ret = SGX_ERROR_SERVICE_INVALID_PRIVILEGE; break; case SGX_INVALID_MEASUREMENT: ret = SE_ERROR_INVALID_MEASUREMENT; break; case SGX_INVALID_SIG_STRUCT: case SGX_INVALID_SIGNATURE: ret = SGX_ERROR_INVALID_SIGNATURE; break; case SGX_INVALID_LICENSE: ret = SE_ERROR_INVALID_LAUNCH_TOKEN; break; case SGX_INVALID_CPUSVN: ret = SGX_ERROR_INVALID_CPUSVN; break; case SGX_INVALID_ISVSVN: ret = SGX_ERROR_INVALID_ISVSVN; break; case SGX_UNMASKED_EVENT: ret = SGX_ERROR_DEVICE_BUSY; break; case (int)SGX_POWER_LOST_ENCLAVE: // [-Wc++11-narrowing] ret = SGX_ERROR_ENCLAVE_LOST; break; case (int)SGX_LE_ROLLBACK: ret = SE_ERROR_INVALID_ISVSVNLE; break; default: SE_TRACE(SE_TRACE_WARNING, "unexpected error %#x from driver, should be uRTS/driver bug\n", driver_error); ret = SGX_ERROR_UNEXPECTED; break; } return ret; }
int EnclaveCreatorHW::trim_accept(uint64_t addr) { sgx_range params; memset(¶ms, 0 ,sizeof(sgx_range)); params.start_addr = (unsigned long)addr; params.nr_pages = 1; int ret = ioctl(m_hdevice, SGX_IOC_ENCLAVE_NOTIFY_ACCEPT, ¶ms); if (ret) { SE_TRACE(SE_TRACE_ERROR, "TRIM_RANGE_COMMIT failed %d\n", errno); return error_driver2urts(ret); } return SGX_SUCCESS; }
extern "C" sgx_status_t __sgx_create_enclave_ex(const char *file_name, const int debug, sgx_launch_token_t *launch_token, int *launch_token_updated, sgx_enclave_id_t *enclave_id, sgx_misc_attribute_t *misc_attr, const uint32_t ex_features, const void* ex_features_p[32]) { sgx_status_t ret = SGX_SUCCESS; //Only true or false is valid if(TRUE != debug && FALSE != debug) return SGX_ERROR_INVALID_PARAMETER; if (!_check_ex_params_(ex_features, ex_features_p)) { return SGX_ERROR_INVALID_PARAMETER; } int fd = open(file_name, O_RDONLY); if(-1 == fd) { SE_TRACE(SE_TRACE_ERROR, "Couldn't open the enclave file, error = %d\n", errno); return SGX_ERROR_ENCLAVE_FILE_ACCESS; } se_file_t file = {NULL, 0, false}; char resolved_path[PATH_MAX]; file.name = realpath(file_name, resolved_path); file.name_len = (uint32_t)strlen(resolved_path); ret = _create_enclave_ex(!!debug, fd, file, NULL, launch_token, launch_token_updated, enclave_id, misc_attr, ex_features, ex_features_p); if(SGX_SUCCESS != ret && misc_attr) { sgx_misc_attribute_t plat_cap; memset(&plat_cap, 0, sizeof(plat_cap)); get_enclave_creator()->get_plat_cap(&plat_cap); memcpy_s(misc_attr, sizeof(sgx_misc_attribute_t), &plat_cap, sizeof(sgx_misc_attribute_t)); } close(fd); return ret; }
int EnclaveCreatorHW::remove_range(uint64_t fromaddr, uint64_t numpages) { int ret = -1; uint64_t i; unsigned long start; for (i = 0; i < numpages; i++) { start = (unsigned long)fromaddr + (unsigned long)(i << SE_PAGE_SHIFT); ret = ioctl(m_hdevice, SGX_IOC_ENCLAVE_PAGE_REMOVE, &start); if (ret) { SE_TRACE(SE_TRACE_ERROR, "PAGE_REMOVE failed %d\n", errno); return error_driver2urts(ret); } } return SGX_SUCCESS; }
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; }
extern "C" int get_cpusvn(sgx_cpu_svn_t *cpu_svn) { if( cpu_svn == NULL) return SGX_ERROR_INVALID_PARAMETER; sgx_cpu_svn_t temp_cpusvn = {{0}}; char config_path[MAX_FILE_PATH]; memset(config_path, 0, MAX_FILE_PATH); if((get_file_path(config_path, MAX_FILE_PATH)) == false) { SE_TRACE(SE_TRACE_DEBUG, "Get configuration file path failed. Using default CPUSVN value\n"); memcpy_s(cpu_svn, sizeof(*cpu_svn), &DEFAULT_CPUSVN, sizeof(DEFAULT_CPUSVN)); return SGX_SUCCESS; } bool r = read_cpusvn_file(config_path, &temp_cpusvn); (void)r, assert (r); memcpy_s(cpu_svn, sizeof(*cpu_svn), &temp_cpusvn, sizeof(temp_cpusvn)); return SGX_SUCCESS; }
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; }
void dump_ssa_gregs(ssa_gpr_t* gpr) { SE_TRACE(SE_TRACE_DEBUG, "ssa generic registers:\n"); SE_TRACE(SE_TRACE_DEBUG, "xbx = %#lx\t", gpr->REG(bx)); SE_TRACE(SE_TRACE_DEBUG, "xcx = %#lx\t", gpr->REG(cx)); SE_TRACE(SE_TRACE_DEBUG, "xdx = %#lx\t", gpr->REG(dx)); SE_TRACE(SE_TRACE_DEBUG, "xsi = %#lx\t", gpr->REG(si)); SE_TRACE(SE_TRACE_DEBUG, "xdi = %#lx\t", gpr->REG(di)); SE_TRACE(SE_TRACE_DEBUG, "xbp = %#lx\t", gpr->REG(bp)); SE_TRACE(SE_TRACE_DEBUG, "xax = %#lx\t", gpr->REG(ax)); SE_TRACE(SE_TRACE_DEBUG, "xip = %#lx\t", gpr->REG(ip)); SE_TRACE(SE_TRACE_DEBUG, "xflags = %#lx\t", gpr->REG(flags)); SE_TRACE(SE_TRACE_DEBUG, "xsp = %#lx\t", gpr->REG(sp)); }
void dump_regs(struct user_regs_struct *regs) { SE_TRACE(SE_TRACE_DEBUG, "user regisers:\n"); SE_TRACE(SE_TRACE_DEBUG, "xbx = %#x\t", regs->REG(bx)); SE_TRACE(SE_TRACE_DEBUG, "xcx = %#x\t", regs->REG(cx)); SE_TRACE(SE_TRACE_DEBUG, "xdx = %#x\t", regs->REG(dx)); SE_TRACE(SE_TRACE_DEBUG, "xsi = %#x\t", regs->REG(si)); SE_TRACE(SE_TRACE_DEBUG, "xdi = %#x\t", regs->REG(di)); SE_TRACE(SE_TRACE_DEBUG, "xbp = %#x\t", regs->REG(bp)); SE_TRACE(SE_TRACE_DEBUG, "xax = %#x\t", regs->REG(ax)); SE_TRACE(SE_TRACE_DEBUG, "xip = %#x\t", regs->REG(ip)); SE_TRACE(SE_TRACE_DEBUG, "xflags = %#x\t", regs->eflags); SE_TRACE(SE_TRACE_DEBUG, "xsp = %#x\t", regs->REG(sp)); }