#![allow(dead_code)]
use std::marker::PhantomData;
use iocuddle::*;
use sgx::page::{SecInfo, Secs};
use sgx::signature::Signature;
const SGX: Group = Group::new(0xA4);
pub const ENCLAVE_CREATE: Ioctl<Write, &Create<'_>> = unsafe { SGX.write(0x00) };
pub const ENCLAVE_ADD_PAGES: Ioctl<WriteRead, &AddPages<'_>> = unsafe { SGX.write_read(0x01) };
pub const ENCLAVE_INIT: Ioctl<Write, &Init<'_>> = unsafe { SGX.write(0x02) };
pub const ENCLAVE_SET_ATTRIBUTE: Ioctl<Write, &SetAttribute<'_>> = unsafe { SGX.write(0x03) };
pub const ENCLAVE_RELAX_PERMISSIONS: Ioctl<WriteRead, &RelaxPermissions<'_>> =
unsafe { SGX.write_read(0x05) };
pub const ENCLAVE_RESTRICT_PERMISSIONS: Ioctl<WriteRead, &RestrictPermissions<'_>> =
unsafe { SGX.write_read(0x06) };
#[repr(C)]
#[derive(Debug)]
pub struct Create<'a>(u64, PhantomData<&'a ()>);
impl<'a> Create<'a> {
pub fn new(secs: &'a Secs) -> Self {
Create(secs as *const _ as _, PhantomData)
}
}
#[repr(C)]
#[derive(Debug)]
pub struct AddPages<'a> {
src: u64,
offset: u64,
length: u64,
secinfo: u64,
flags: u64,
count: u64,
phantom: PhantomData<&'a ()>,
}
impl<'a> AddPages<'a> {
pub fn new(bytes: &'a [u8], offset: usize, secinfo: &'a SecInfo, measure: bool) -> Self {
const MEASURE: u64 = 1 << 0;
let flags = match measure {
true => MEASURE,
false => 0,
};
Self {
src: bytes.as_ptr() as _,
offset: offset as _,
length: bytes.len() as _,
secinfo: secinfo as *const _ as _,
flags,
count: 0,
phantom: PhantomData,
}
}
#[allow(dead_code)]
pub fn count(&self) -> u64 {
self.count
}
}
#[repr(C)]
#[derive(Debug)]
pub struct Init<'a>(u64, PhantomData<&'a ()>);
impl<'a> Init<'a> {
pub fn new(sig: &'a Signature) -> Self {
Init(sig as *const _ as _, PhantomData)
}
}
#[repr(C)]
#[derive(Debug)]
pub struct SetAttribute<'a>(u64, PhantomData<&'a ()>);
impl<'a> SetAttribute<'a> {
#[allow(dead_code)]
pub fn new(fd: &'a impl std::os::unix::io::AsRawFd) -> Self {
SetAttribute(fd.as_raw_fd() as _, PhantomData)
}
}
#[repr(C)]
#[derive(Debug)]
pub struct RelaxPermissions<'a> {
offset: u64,
length: u64,
secinfo: u64,
count: u64,
phantom: PhantomData<&'a ()>,
}
impl<'a> RelaxPermissions<'a> {
pub fn new(offset: usize, length: usize, secinfo: &'a SecInfo) -> Self {
Self {
offset: offset as _,
length: length as _,
secinfo: secinfo as *const _ as _,
count: 0,
phantom: PhantomData,
}
}
pub fn count(&self) -> u64 {
self.count
}
}
#[repr(C)]
#[derive(Debug)]
pub struct RestrictPermissions<'a> {
offset: u64,
length: u64,
secinfo: u64,
result: u64,
count: u64,
phantom: PhantomData<&'a ()>,
}
impl<'a> RestrictPermissions<'a> {
pub fn new(offset: usize, length: usize, secinfo: &'a SecInfo) -> Self {
Self {
offset: offset as _,
length: length as _,
secinfo: secinfo as *const _ as _,
result: 0,
count: 0,
phantom: PhantomData,
}
}
pub fn result(&self) -> u64 {
self.count
}
pub fn count(&self) -> u64 {
self.count
}
}
#[cfg(all(test, host_can_test_sgx))]
mod tests {
use super::*;
#[test]
fn relax_permissions() {
use sgx::page::{Flags, SecInfo};
use std::fs::OpenOptions;
let mut device_file = OpenOptions::new()
.read(true)
.write(true)
.open("/dev/sgx_enclave")
.unwrap();
let secinfo = SecInfo::reg(Flags::empty());
let mut parameters = RelaxPermissions::new(0, 0, &secinfo);
let ret = match ENCLAVE_RELAX_PERMISSIONS.ioctl(&mut device_file, &mut parameters) {
Ok(_) => 0,
Err(err) => err.raw_os_error().unwrap(),
};
assert_eq!(ret, libc::EINVAL);
}
#[test]
fn restrict_permissions() {
use sgx::page::{Flags, SecInfo};
use std::fs::OpenOptions;
let mut device_file = OpenOptions::new()
.read(true)
.write(true)
.open("/dev/sgx_enclave")
.unwrap();
let secinfo = SecInfo::reg(Flags::empty());
let mut parameters = RestrictPermissions::new(0, 0, &secinfo);
let ret = match ENCLAVE_RESTRICT_PERMISSIONS.ioctl(&mut device_file, &mut parameters) {
Ok(_) => 0,
Err(err) => err.raw_os_error().unwrap(),
};
assert_eq!(ret, libc::EINVAL);
}
}