From d8dc2d87563a6c3eadb5ec49d3f750b00cd36105 Mon Sep 17 00:00:00 2001 From: Valentyn Faychuk Date: Sat, 19 Oct 2024 04:17:33 +0300 Subject: [PATCH] /dev/sgx IOCTL codes --- .gitignore | 8 ++ Cargo.toml | 6 ++ README.md | 2 + src/main.rs | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/types.rs | 175 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 411 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 src/main.rs create mode 100644 src/types.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eef6739 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +debug/ +target/ +Cargo.lock + +**/*.rs.bk + +# RustRover +.idea/ diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8f916b8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "occlum-ioctl" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/README.md b/README.md new file mode 100644 index 0000000..8b99f8a --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +A simple app to display Occlum /dev/sgx IOCTL codes and needed types +Doesn't have any dependencies, run with `cargo run` diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..6191c88 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,220 @@ +mod types; + +use types::*; + +fn main() { + println!("Occlum /dev/sgx IOCTL codes:"); + + println!("SGX_CMD_NUM_IS_EDMM_SUPPORTED {:x}", SGX_CMD_NUM_IS_EDMM_SUPPORTED); + println!("SGX_CMD_NUM_GET_EPID_GROUP_ID {:x}", SGX_CMD_NUM_GET_EPID_GROUP_ID); + println!("SGX_CMD_NUM_GEN_EPID_QUOTE {:x}", SGX_CMD_NUM_GEN_EPID_QUOTE); + println!("SGX_CMD_NUM_SELF_TARGET {:x}", SGX_CMD_NUM_SELF_TARGET); + println!("SGX_CMD_NUM_VERIFY_REPORT {:x}", SGX_CMD_NUM_VERIFY_REPORT); + println!("SGX_CMD_NUM_CREATE_REPORT {:x}", SGX_CMD_NUM_CREATE_REPORT); + println!("SGX_CMD_NUM_DETECT_DCAP_DRIVER {:x}", SGX_CMD_NUM_DETECT_DCAP_DRIVER); + println!("SGX_CMD_NUM_GET_DCAP_QUOTE_SIZE {:x}", SGX_CMD_NUM_GET_DCAP_QUOTE_SIZE); + println!("SGX_CMD_NUM_GEN_DCAP_QUOTE {:x}", SGX_CMD_NUM_GEN_DCAP_QUOTE); + println!("SGX_CMD_NUM_GET_DCAP_SUPPLEMENTAL_SIZE {:x}", SGX_CMD_NUM_GET_DCAP_SUPPLEMENTAL_SIZE); + println!("SGX_CMD_NUM_VER_DCAP_QUOTE {:x}", SGX_CMD_NUM_VER_DCAP_QUOTE); + println!("SGX_CMD_NUM_KEY {:x}", SGX_CMD_NUM_KEY); + + //println!("{:x} SGX_CMD_NUM_IS_EDMM_SUPPORTED", SGX_CMD_NUM_IS_EDMM_SUPPORTED); + //println!("{:x} SGX_CMD_NUM_GET_EPID_GROUP_ID", SGX_CMD_NUM_GET_EPID_GROUP_ID); + //println!("{:x} SGX_CMD_NUM_GEN_EPID_QUOTE", SGX_CMD_NUM_GEN_EPID_QUOTE); + //println!("{:x} SGX_CMD_NUM_SELF_TARGET", SGX_CMD_NUM_SELF_TARGET); + //println!("{:x} SGX_CMD_NUM_VERIFY_REPORT", SGX_CMD_NUM_VERIFY_REPORT); + //println!("{:x} SGX_CMD_NUM_CREATE_REPORT", SGX_CMD_NUM_CREATE_REPORT); + //println!("{:x} SGX_CMD_NUM_DETECT_DCAP_DRIVER", SGX_CMD_NUM_DETECT_DCAP_DRIVER); + //println!("{:x} SGX_CMD_NUM_GET_DCAP_QUOTE_SIZE", SGX_CMD_NUM_GET_DCAP_QUOTE_SIZE); + //println!("{:x} SGX_CMD_NUM_GEN_DCAP_QUOTE", SGX_CMD_NUM_GEN_DCAP_QUOTE); + //println!("{:x} SGX_CMD_NUM_GET_DCAP_SUPPLEMENTAL_SIZE", SGX_CMD_NUM_GET_DCAP_SUPPLEMENTAL_SIZE); + //println!("{:x} SGX_CMD_NUM_VER_DCAP_QUOTE", SGX_CMD_NUM_VER_DCAP_QUOTE); + //println!("{:x} SGX_CMD_NUM_KEY", SGX_CMD_NUM_KEY); +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct StructuredIoctlNum { + cmd_id: u8, + magic_char: u8, + arg_size: u16, + arg_type: StructuredIoctlArgType, +} + +impl StructuredIoctlNum { + pub const fn new( + cmd_id: u8, + magic_char: u8, + arg_type: StructuredIoctlArgType, + ) -> StructuredIoctlNum { + // TODO: make sure the size of T is not too big + // assert!(std::mem::size_of::() <= (std::u16::MAX as usize)); + let arg_size = std::mem::size_of::() as u16; + StructuredIoctlNum { + cmd_id, + magic_char, + arg_size, + arg_type, + } + } + + pub fn from_u32(raw_cmd_num: u32) -> StructuredIoctlNum { + // bits: [0, 8) + let cmd_id = (raw_cmd_num >> 0) as u8; + // bits: [8, 16) + let magic_char = (raw_cmd_num >> 8) as u8; + // bits: [16, 30) + let arg_size = ((raw_cmd_num >> 16) as u16) & 0x3FFF_u16; + // bits: [30, 32) + let arg_type = { + let type_bits = ((raw_cmd_num) >> 30) as u8; + StructuredIoctlArgType::from_u8(type_bits) + }; + + if arg_type == StructuredIoctlArgType::Void { + if arg_size != 0 { + panic!("invalid combination between type and size"); + } + } else { + if arg_size == 0 { + panic!("invalid combination between type and size"); + } + } + + StructuredIoctlNum { + cmd_id, + magic_char, + arg_size, + arg_type, + } + } + + pub const fn as_u32(&self) -> u32 { + (self.cmd_id as u32) + | (self.magic_char as u32) << 8 + | (self.arg_size as u32) << 16 + | (self.arg_type as u32) << 30 + } + + pub fn require_arg(&self) -> bool { + self.arg_type != StructuredIoctlArgType::Void + } + + pub fn cmd_id(&self) -> u8 { + self.cmd_id + } + + pub fn magic_char(&self) -> u8 { + self.magic_char + } + + pub fn arg_size(&self) -> usize { + self.arg_size as usize + } + + pub fn arg_type(&self) -> StructuredIoctlArgType { + self.arg_type + } +} + +#[derive(Debug, Copy, Clone, PartialEq)] +#[repr(u8)] +pub enum StructuredIoctlArgType { + Void = 0, + Input = 1, + Output = 2, + InputOutput = 3, +} + +impl StructuredIoctlArgType { + pub fn from_u8(type_bits: u8) -> StructuredIoctlArgType { + if type_bits > StructuredIoctlArgType::InputOutput as u8 { + panic!("invalid bits for StructuredIoctlArgType"); + } + unsafe { core::mem::transmute(type_bits) } + } + + pub fn can_be_input(&self) -> bool { + *self == StructuredIoctlArgType::Input || *self == StructuredIoctlArgType::InputOutput + } + + pub fn can_be_output(&self) -> bool { + *self == StructuredIoctlArgType::Output || *self == StructuredIoctlArgType::InputOutput + } +} + +/// Ioctl to check if EDMM (Enclave Dynamic Memory Management) is supported +pub const SGX_CMD_NUM_IS_EDMM_SUPPORTED: u32 = + StructuredIoctlNum::new::(0, SGX_MAGIC_CHAR, StructuredIoctlArgType::Output).as_u32(); + +/// Ioctl to get the EPID group ID +pub const SGX_CMD_NUM_GET_EPID_GROUP_ID: u32 = StructuredIoctlNum::new::( + 1, + SGX_MAGIC_CHAR, + StructuredIoctlArgType::Output, +) + .as_u32(); + +/// Ioctl to get EPID quote +pub const SGX_CMD_NUM_GEN_EPID_QUOTE: u32 = StructuredIoctlNum::new::( + 2, + SGX_MAGIC_CHAR, + StructuredIoctlArgType::InputOutput, +) + .as_u32(); + +/// Ioctl to get the target info of the current enclave +pub const SGX_CMD_NUM_SELF_TARGET: u32 = + StructuredIoctlNum::new::(3, SGX_MAGIC_CHAR, StructuredIoctlArgType::Output) + .as_u32(); + +/// Ioctl to create a report +pub const SGX_CMD_NUM_CREATE_REPORT: u32 = StructuredIoctlNum::new::( + 4, + SGX_MAGIC_CHAR, + StructuredIoctlArgType::InputOutput, +) + .as_u32(); + +/// Ioctl to verify a report +pub const SGX_CMD_NUM_VERIFY_REPORT: u32 = + StructuredIoctlNum::new::(5, SGX_MAGIC_CHAR, StructuredIoctlArgType::Input) + .as_u32(); + +/// Ioctl to check if DCAP driver is installed on host +pub const SGX_CMD_NUM_DETECT_DCAP_DRIVER: u32 = + StructuredIoctlNum::new::(6, SGX_MAGIC_CHAR, StructuredIoctlArgType::Output).as_u32(); + +/// Ioctl to get DCAP quote size +pub const SGX_CMD_NUM_GET_DCAP_QUOTE_SIZE: u32 = + StructuredIoctlNum::new::(7, SGX_MAGIC_CHAR, StructuredIoctlArgType::Output).as_u32(); // 0x80047307 + +/// Ioctl to get DCAP quote +pub const SGX_CMD_NUM_GEN_DCAP_QUOTE: u32 = StructuredIoctlNum::new::( + 8, + SGX_MAGIC_CHAR, + StructuredIoctlArgType::InputOutput, +) + .as_u32(); // 0xc0187308 + +/// Ioctl to get the verfication supplemental data size +pub const SGX_CMD_NUM_GET_DCAP_SUPPLEMENTAL_SIZE: u32 = + StructuredIoctlNum::new::(9, SGX_MAGIC_CHAR, StructuredIoctlArgType::Output).as_u32(); // 0x80047309 + +/// Ioctl to verify DCAP quote +pub const SGX_CMD_NUM_VER_DCAP_QUOTE: u32 = StructuredIoctlNum::new::( + 10, + SGX_MAGIC_CHAR, + StructuredIoctlArgType::InputOutput, +) + .as_u32(); // 0xc030730a + +/// Ioctl to get the key of the current enclave +pub const SGX_CMD_NUM_KEY: u32 = StructuredIoctlNum::new::( + 11, + SGX_MAGIC_CHAR, + StructuredIoctlArgType::InputOutput, +) + .as_u32(); + +/// A magical number that distinguishes SGX ioctls for other ioctls +const SGX_MAGIC_CHAR: u8 = 's' as u8; diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..2428c78 --- /dev/null +++ b/src/types.rs @@ -0,0 +1,175 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(unused_attributes)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +pub type int8_t = i8; +pub type int16_t = i16; +pub type int32_t = i32; +pub type int64_t = i64; +pub type uint8_t = u8; +pub type uint16_t = u16; +pub type uint32_t = u32; +pub type uint64_t = u64; +pub type size_t = usize; +pub type sgx_epid_group_id_t = [uint8_t; 4]; +pub const SGX_REPORT_DATA_SIZE: size_t = 64; +pub struct sgx_report_data_t { + pub d: [uint8_t; SGX_REPORT_DATA_SIZE], +} +pub struct sgx_spid_t { + pub id: [uint8_t; 16], +} +pub struct sgx_quote_nonce_t { + pub rand: [uint8_t; 16], +} +pub const SGX_HASH_SIZE: size_t = 32; +pub struct sgx_measurement_t { + pub m: [uint8_t; SGX_HASH_SIZE], +} +pub struct sgx_attributes_t { + pub flags: uint64_t, + pub xfrm: uint64_t, +} +pub type sgx_config_svn_t = uint16_t; +pub type sgx_misc_select_t = uint32_t; +pub const SGX_CONFIGID_SIZE: size_t = 64; +pub type sgx_config_id_t = [uint8_t; SGX_CONFIGID_SIZE]; +pub const SGX_TARGET_INFO_RESERVED1_BYTES: size_t = 2; +pub const SGX_TARGET_INFO_RESERVED2_BYTES: size_t = 8; +pub const SGX_TARGET_INFO_RESERVED3_BYTES: size_t = 384; +pub struct sgx_target_info_t { + pub mr_enclave: sgx_measurement_t, + pub attributes: sgx_attributes_t, + pub reserved1: [uint8_t; SGX_TARGET_INFO_RESERVED1_BYTES], + pub config_svn: sgx_config_svn_t, + pub misc_select: sgx_misc_select_t, + pub reserved2: [uint8_t; SGX_TARGET_INFO_RESERVED2_BYTES], + pub config_id: sgx_config_id_t, + pub reserved3: [uint8_t; SGX_TARGET_INFO_RESERVED3_BYTES], +} + +#[repr(u32)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum sgx_quote_sign_type_t { + SGX_UNLINKABLE_SIGNATURE = 0, + SGX_LINKABLE_SIGNATURE = 1, +} +pub const SGX_KEYID_SIZE: size_t = 32; +pub const SGX_CPUSVN_SIZE: size_t = 16; +pub const SGX_KEY_REQUEST_RESERVED2_BYTES: size_t = 434; +pub const SGX_REPORT_BODY_RESERVED1_BYTES: size_t = 12; +pub const SGX_REPORT_BODY_RESERVED2_BYTES: size_t = 32; +pub const SGX_REPORT_BODY_RESERVED3_BYTES: size_t = 32; +pub const SGX_REPORT_BODY_RESERVED4_BYTES: size_t = 42; +pub struct sgx_cpu_svn_t { + pub svn: [uint8_t; SGX_CPUSVN_SIZE], +} +pub const SGX_ISVEXT_PROD_ID_SIZE: size_t = 16; +pub const SGX_ISV_FAMILY_ID_SIZE: size_t = 16; + +pub type sgx_isvext_prod_id_t = [uint8_t; SGX_ISVEXT_PROD_ID_SIZE]; +pub type sgx_isvfamily_id_t = [uint8_t; SGX_ISV_FAMILY_ID_SIZE]; +pub type sgx_prod_id_t = uint16_t; +pub type sgx_isv_svn_t = uint16_t; +pub type sgx_key_128bit_t = [uint8_t; 16]; + +pub struct sgx_report_body_t { + pub cpu_svn: sgx_cpu_svn_t, + pub misc_select: sgx_misc_select_t, + pub reserved1: [uint8_t; SGX_REPORT_BODY_RESERVED1_BYTES], + pub isv_ext_prod_id: sgx_isvext_prod_id_t, + pub attributes: sgx_attributes_t, + pub mr_enclave: sgx_measurement_t, + pub reserved2: [uint8_t; SGX_REPORT_BODY_RESERVED2_BYTES], + pub mr_signer: sgx_measurement_t, + pub reserved3: [uint8_t; SGX_REPORT_BODY_RESERVED3_BYTES], + pub config_id: sgx_config_id_t, + pub isv_prod_id: sgx_prod_id_t, + pub isv_svn: sgx_isv_svn_t, + pub config_svn: sgx_config_svn_t, + pub reserved4: [uint8_t; SGX_REPORT_BODY_RESERVED4_BYTES], + pub isv_family_id: sgx_isvfamily_id_t, + pub report_data: sgx_report_data_t, +} +pub struct sgx_key_id_t { + pub id: [uint8_t; SGX_KEYID_SIZE], +} +pub const SGX_MAC_SIZE: size_t = 16; +pub type sgx_mac_t = [uint8_t; SGX_MAC_SIZE]; + +pub struct sgx_report_t { + pub body: sgx_report_body_t, + pub key_id: sgx_key_id_t, + pub mac: sgx_mac_t, +} +#[repr(u32)] +#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Debug)] +pub enum sgx_ql_qv_result_t { + SGX_QL_QV_RESULT_OK = 0x0000_0000, + // SGX_QL_QV_RESULT_MIN = 0x0000_A001, + SGX_QL_QV_RESULT_CONFIG_NEEDED = 0x0000_A001, + SGX_QL_QV_RESULT_OUT_OF_DATE = 0x0000_A002, + SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED = 0x0000_A003, + SGX_QL_QV_RESULT_INVALID_SIGNATURE = 0x0000_A004, + SGX_QL_QV_RESULT_REVOKED = 0x0000_A005, + SGX_QL_QV_RESULT_UNSPECIFIED = 0x0000_A006, + SGX_QL_QV_RESULT_SW_HARDENING_NEEDED = 0x0000_A007, + SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED = 0x0000_A008, + SGX_QL_QV_RESULT_MAX = 0x0000_A0FF, +} +pub struct sgx_key_request_t { + pub key_name: uint16_t, + pub key_policy: uint16_t, + pub isv_svn: sgx_isv_svn_t, + pub reserved1: uint16_t, + pub cpu_svn: sgx_cpu_svn_t, + pub attribute_mask: sgx_attributes_t, + pub key_id: sgx_key_id_t, + pub misc_mask: sgx_misc_select_t, + pub config_svn: sgx_config_svn_t, + pub reserved2: [uint8_t; SGX_KEY_REQUEST_RESERVED2_BYTES], +} + +#[repr(C)] +pub struct IoctlGenEPIDQuoteArg { + report_data: sgx_report_data_t, // Input + quote_type: sgx_quote_sign_type_t, // Input + spid: sgx_spid_t, // Input + nonce: sgx_quote_nonce_t, // Input + sigrl_ptr: *const u8, // Input (optional) + sigrl_len: u32, // Input (optional) + quote_buf_len: u32, // Input + quote_buf: *mut u8, // Output +} + +#[repr(C)] +pub struct IoctlCreateReportArg { + target_info: *const sgx_target_info_t, // Input (optional) + report_data: *const sgx_report_data_t, // Input (optional) + report: *mut sgx_report_t, // Output +} + +#[repr(C)] +pub struct IoctlGenDCAPQuoteArg { + report_data: *const sgx_report_data_t, // Input + quote_size: *mut u32, // Input/output + quote_buf: *mut u8, // Output +} + +#[repr(C)] +pub struct IoctlVerDCAPQuoteArg { + quote_buf: *const u8, // Input + quote_size: u32, // Input + collateral_expiration_status: *mut u32, // Output + quote_verification_result: *mut sgx_ql_qv_result_t, // Output + supplemental_data_size: u32, // Input (optional) + supplemental_data: *mut u8, // Output (optional) +} + +#[repr(C)] +pub struct IoctlGetKeyArg { + key_request: *const sgx_key_request_t, // Input + key: *mut sgx_key_128bit_t, // Output +}