aboutsummaryrefslogtreecommitdiff
path: root/src/sgx.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sgx.rs')
-rw-r--r--src/sgx.rs351
1 files changed, 351 insertions, 0 deletions
diff --git a/src/sgx.rs b/src/sgx.rs
new file mode 100644
index 0000000..e611620
--- /dev/null
+++ b/src/sgx.rs
@@ -0,0 +1,351 @@
+//! Program x86 enclaves.
+
+/// Execute an enclave system function of specified leaf number.
+///
+/// # Safety
+/// * Function needs to be executed in ring 0.
+macro_rules! encls {
+ ($rax:expr, $rbx:expr)
+ => ( $crate::sgx::encls2($rax as u64, $rbx as u64) );
+
+ ($rax:expr, $rbx:expr, $rcx:expr)
+ => ( $crate::sgx::encls3($rax as u64, $rbx as u64, $rcx as u64) );
+
+ ($rax:expr, $rbx:expr, $rcx:expr, $rdx:expr)
+ => ( $crate::sgx::encls4($rax as u64, $rbx as u64, $rcx as u64, $rdx as u64) );
+}
+
+/// encls with two arguments -- consider calling the encls! macro instead!
+unsafe fn encls2(rax: u64, rbx: u64) -> (u32, u64) {
+ let eax: u32;
+ let out_rbx: u64;
+ asm!("encls" : "={eax}" (eax), "={rbx}" (out_rbx)
+ : "{rax}" (rax), "{rbx}" (rbx));
+ (eax, out_rbx)
+}
+
+/// encls with three arguments -- consider calling the encls! macro instead!
+unsafe fn encls3(rax: u64, rbx: u64, rcx: u64) -> (u32, u64) {
+ let eax: u32;
+ let out_rbx: u64;
+ asm!("encls" : "={eax}" (eax), "={rbx}" (out_rbx)
+ : "{rax}" (rax), "{rbx}" (rbx), "{rcx}" (rcx));
+ (eax, out_rbx)
+}
+
+/// encls with four arguments -- consider calling the encls! macro instead!
+unsafe fn encls4(rax: u64, rbx: u64, rcx: u64, rdx: u64) -> (u32, u64) {
+ let eax: u32;
+ let out_rbx: u64;
+ asm!("encls" : "={eax}" (eax), "={rbx}" (out_rbx)
+ : "{rax}" (rax), "{rbx}" (rbx), "{rcx}" (rcx), "{rdx}" (rdx));
+ (eax, out_rbx)
+}
+
+enum EnclsCommand {
+ EADD = 0x01,
+ EAUG = 0x0D,
+ EBLOCK = 0x09,
+ ECREATE = 0x00,
+ EDBGRD = 0x04,
+ EDBGWR = 0x05,
+ EEXTEND = 0x06,
+ EINIT = 0x02,
+ ELDB = 0x07,
+ ELDU = 0x08,
+ EMODPR = 0x0E,
+ EMODT = 0x0F,
+ EPA = 0x0A,
+ EREMOVE = 0x03,
+ ETRACK = 0x0C,
+ EWB = 0x0B
+}
+
+
+/// Add a Page to an Uninitialized Enclave.
+///
+/// # Arguments
+/// * Address of a PAGEINFO.
+/// * Address of the destination EPC page.
+pub unsafe fn encls_eadd(pageinfo: u64, epc_page: u64) {
+ encls!(EnclsCommand::EADD as u64, pageinfo, epc_page);
+}
+
+/// Add a Page to an Initialized Enclave.
+///
+/// # Arguments
+/// * Address of a SECINFO
+/// * Address of the destination EPC page
+pub unsafe fn encls_eaug(secinfo_address: u64, epc_page: u64) {
+ encls!(EnclsCommand::EAUG as u64, secinfo_address, epc_page);
+}
+
+/// Mark a page in EPC as Blocked.
+///
+/// # Arguments
+/// * Effective address of the EPC page
+pub unsafe fn encls_eblock(epc_page: u64) -> u32 {
+ encls!(EnclsCommand::EBLOCK as u64, epc_page).0
+}
+
+/// Create an SECS page in the Enclave Page Cache
+///
+/// # Arguments
+/// * Address of a PAGEINFO
+/// * Address of the destination SECS page
+///
+pub unsafe fn encls_create(pageinfo: u64, secs_page: u64) {
+ encls!(EnclsCommand::ECREATE as u64, pageinfo, secs_page);
+}
+
+/// Read From a Debug Enclave.
+///
+/// # Return
+/// Data read from a debug enclave.
+///
+/// # Arguments
+/// * Address of source memory in the EPC
+///
+pub unsafe fn encls_edbgrd(source_address: u64) -> u64 {
+ encls!(EnclsCommand::EDBGRD as u64, source_address).1
+}
+
+/// Write to a Debug Enclave.
+///
+/// # Arguments
+/// * Data to be written to a debug enclave
+/// * Address of Target memory in the EPC
+///
+pub unsafe fn encls_edbgwr(data: u64, target_address: u64) {
+ encls!(EnclsCommand::EDBGWR as u64, data, target_address);
+}
+
+/// Extend Uninitialized Enclave Measurement by 256 Bytes
+///
+/// # Arguments
+/// * Effective address of the SECS of the data chunk
+/// * Effective address of a 256-byte chunk in the EPC
+pub unsafe fn encls_eextend(secs_chunk: u64, epc_chunk: u64) {
+ encls!(EnclsCommand::EEXTEND as u64, secs_chunk, epc_chunk);
+}
+
+/// Initialize an Enclave for Execution
+///
+/// # Arguments
+/// * Address of SIGSTRUCT
+/// * Address of SECS
+/// * Address of EINITTOKEN
+///
+pub unsafe fn encls_einit(sigstruct: u64, secs: u64, einittoken: u64) -> u32 {
+ encls!(EnclsCommand::EINIT as u64, sigstruct, secs, einittoken).0
+}
+
+/// Loads and verifies an EPC page and marks the page as blocked.
+///
+/// # Arguments
+/// * Address of the PAGEINFO
+/// * Address of the EPC page
+/// * Address of the version-array slot
+///
+pub unsafe fn encls_eldb(pageinfo: u64, epc_page: u64, verion_array_slot: u64) -> u32 {
+ encls!(EnclsCommand::ELDB as u64, pageinfo, epc_page, verion_array_slot).0
+}
+
+/// Loads, verifies an EPC page and marks the page as unblocked.
+///
+/// # Arguments
+/// * Address of the PAGEINFO
+/// * Address of the EPC page
+/// * Address of the version-array slot
+///
+pub unsafe fn encls_eldu(pageinfo: u64, epc_page: u64, verion_array_slot: u64) -> u32 {
+ encls!(EnclsCommand::ELDU as u64, pageinfo, epc_page, verion_array_slot).0
+}
+
+/// Restrict the Permissions of an EPC Page.
+///
+/// # Arguments
+/// * Address of a SECINFO
+/// * Address of the destination EPC page
+///
+pub unsafe fn encls_emodpr(secinfo: u64, epc_page: u64) -> u32 {
+ encls!(EnclsCommand::EMODPR as u64, secinfo, epc_page).0
+}
+
+/// Change the Type of an EPC Page.
+///
+/// # Arguments
+/// * Address of a SECINFO
+/// * Address of the destination EPC page
+///
+pub unsafe fn encls_emodt(secinfo: u64, epc_page: u64) -> u32 {
+ encls!(EnclsCommand::EMODT as u64, secinfo, epc_page).0
+}
+
+/// Add Version Array.
+///
+/// # Arguments
+/// * PT_VA Constant
+/// * Effective address of the EPC page
+///
+pub unsafe fn encls_epa(pt_va: u64, epc_page: u64) {
+ encls!(EnclsCommand::EPA as u64, pt_va, epc_page);
+}
+
+/// Remove a page from the EPC.
+///
+/// # Arguments
+/// * Effective address of the EPC page
+///
+pub unsafe fn encls_eremove(epc_page: u64) {
+ encls!(EnclsCommand::EREMOVE as u64, epc_page);
+}
+
+/// Activates EBLOCK Checks.
+///
+/// # Arguments
+/// * Pointer to the SECS of the EPC page.
+///
+pub unsafe fn encls_etrack(secs_pointer: u64) -> u32 {
+ encls!(EnclsCommand::ETRACK as u64, secs_pointer).0
+}
+
+/// Invalidate an EPC Page and Write out to Main Memory.
+///
+/// # Arguments
+/// * Address of the EPC page.
+/// * Address of a VA slot.
+///
+pub unsafe fn encls_ewb(pageinfo: u64, epc_page: u64, va_slot: u64) -> u32 {
+ encls!(EnclsCommand::EWB as u64, pageinfo, epc_page, va_slot).0
+}
+
+/// Execute an enclave user function of specified leaf number.
+///
+/// # Safety
+/// * Function needs to be executed in ring 3.
+macro_rules! enclu {
+ ($rax:expr, $rbx:expr, $rcx:expr)
+ => ( $crate::sgx::enclu3($rax as u64, $rbx as u64, $rcx as u64) );
+
+ ($rax:expr, $rbx:expr, $rcx:expr, $rdx:expr)
+ => ( $crate::sgx::enclu4($rax as u64, $rbx as u64, $rcx as u64, $rdx as u64) );
+}
+
+/// enclu with three arguments -- consider calling the enclu! macro instead!
+unsafe fn enclu3(rax: u64, rbx: u64, rcx: u64) -> (u32, u64) {
+ let eax: u32;
+ let out_rcx: u64;
+ asm!("enclu" : "={eax}" (eax), "={rcx}" (out_rcx)
+ : "{rax}" (rax), "{rbx}" (rbx), "{rcx}" (rcx));
+ (eax, out_rcx)
+}
+
+/// enclu with four arguments -- consider calling the enclu! macro instead!
+unsafe fn enclu4(rax: u64, rbx: u64, rcx: u64, rdx: u64) -> (u32, u64) {
+ let eax: u32;
+ let out_rcx: u64;
+ asm!("enclu" : "={eax}" (eax), "={rcx}" (out_rcx)
+ : "{rax}" (rax), "{rbx}" (rbx), "{rcx}" (rcx), "{rdx}" (rdx));
+ (eax, out_rcx)
+}
+
+enum EncluCommand {
+ EACCEPT = 0x05,
+ EACCEPTCOPY = 0x07,
+ EENTER = 0x02,
+ EEXIT = 0x04,
+ EGETKEY = 0x01,
+ EMODEPE = 0x06,
+ EREPORT = 0x00,
+ ERESUME = 0x03,
+}
+
+/// Accept Changes to an EPC Page.
+///
+/// # Arguments
+/// * Address of a SECINFO.
+/// * Address of the destination EPC page.
+///
+/// Returns an error code.
+///
+pub unsafe fn enclu_eaccept(secinfo: u64, epc_page: u64) -> u32 {
+ enclu!(EncluCommand::EACCEPT as u64, secinfo, epc_page).0
+}
+
+/// Initialize a Pending Page.
+///
+/// # Arguments
+/// * Address of a SECINFO.
+/// * Address of the destination EPC page.
+/// * Address of the source EPC page.
+///
+/// Returns an error code.
+///
+pub unsafe fn enclu_eacceptcopy(secinfo: u64, destination_epc_page: u64, source_epc_page: u64) -> u32 {
+ enclu!(EncluCommand::EACCEPTCOPY as u64, secinfo, destination_epc_page, source_epc_page).0
+}
+
+/// Enters an Enclave.
+///
+/// # Arguments
+/// * Address of a TCS.
+/// * Address of AEP.
+/// * Address of IP following EENTER.
+///
+/// Returns content of RBX.CSSA and Address of IP following EENTER.
+///
+pub unsafe fn enclu_eenter(tcs: u64, aep: u64) -> (u32, u64) {
+ enclu!(EncluCommand::EENTER as u64, tcs, aep)
+}
+
+/// Exits an Enclave.
+///
+/// # Arguments
+/// * Target address outside the enclave
+/// * Address of the current AEP
+///
+pub unsafe fn enclu_eexit(ip: u64, aep: u64) {
+ enclu!(EncluCommand::EEXIT as u64, ip, aep);
+}
+
+/// Retrieves a Cryptographic Key.
+///
+/// # Arguments
+/// * Address to a KEYREQUEST
+/// * Address of the OUTPUTDATA
+///
+pub unsafe fn enclu_egetkey(keyrequest: u64, outputdata: u64) {
+ enclu!(EncluCommand::EGETKEY as u64, keyrequest, outputdata);
+}
+
+/// Extend an EPC Page Permissions.
+///
+/// # Arguments
+/// * Address of a SECINFO
+/// * Address of the destination EPC page
+///
+pub unsafe fn enclu_emodepe(secinfo: u64, epc_page: u64) {
+ enclu!(EncluCommand::EMODEPE as u64, secinfo, epc_page);
+}
+
+/// Create a Cryptographic Report of the Enclave.
+///
+/// # Arguments
+/// * Address of TARGETINFO
+/// * Address of REPORTDATA
+/// * Address where the REPORT is written to in an OUTPUTDATA
+///
+pub unsafe fn enclu_ereport(targetinfo: u64, reportdata: u64, outputdata: u64) {
+ enclu!(EncluCommand::EREPORT as u64, targetinfo, reportdata, outputdata);
+}
+
+/// Re-Enters an Enclave.
+///
+/// # Arguments
+/// * Address of a TCS.
+/// * Address of AEP.
+///
+pub unsafe fn enclu_eresume(tcs: u64, aep: u64) {
+ enclu!(EncluCommand::ERESUME as u64, tcs, aep);
+}