1#![doc = include_str!("../README.md")]
4
5use mc_sgx_core_types::{ConfigId, ConfigSvn, Error, TargetInfo};
6use mc_sgx_urts_sys::{
7 sgx_create_enclave_from_buffer_ex, sgx_destroy_enclave, sgx_get_target_info,
8};
9use mc_sgx_urts_sys_types::{
10 sgx_enclave_id_t, sgx_kss_config_t, MAX_EX_FEATURES_COUNT, SGX_CREATE_ENCLAVE_EX_KSS,
11 SGX_CREATE_ENCLAVE_EX_KSS_BIT_IDX, SGX_CREATE_ENCLAVE_EX_PCL,
12 SGX_CREATE_ENCLAVE_EX_PCL_BIT_IDX,
13};
14use mc_sgx_util::ResultInto;
15use std::{ffi::c_void, fs::File, io::Read, os::raw::c_int, path::Path, ptr};
16
17#[repr(transparent)]
19#[derive(Debug, Clone, Hash, PartialEq, Eq, Default)]
20pub struct KssConfig(sgx_kss_config_t);
21
22impl KssConfig {
23 pub fn new(config_id: ConfigId, config_svn: ConfigSvn) -> KssConfig {
24 KssConfig(sgx_kss_config_t {
25 config_id: config_id.into(),
26 config_svn: config_svn.into(),
27 })
28 }
29}
30
31impl From<KssConfig> for sgx_kss_config_t {
32 fn from(input: KssConfig) -> sgx_kss_config_t {
33 input.0
34 }
35}
36
37impl From<sgx_kss_config_t> for KssConfig {
38 fn from(input: sgx_kss_config_t) -> KssConfig {
39 KssConfig(input)
40 }
41}
42
43#[derive(Debug, PartialEq, Eq)]
50pub struct Enclave {
51 id: sgx_enclave_id_t,
53}
54
55pub struct EnclaveBuilder {
57 bytes: Vec<u8>,
59
60 debug: bool,
62
63 pcl_key: Option<Vec<u8>>,
65
66 kss_config: Option<KssConfig>,
68}
69
70impl EnclaveBuilder {
71 pub fn new(path: impl AsRef<Path>) -> std::io::Result<EnclaveBuilder> {
78 let file = File::open(path)?;
79 file.try_into()
80 }
81
82 #[must_use]
84 pub fn debug(mut self) -> EnclaveBuilder {
85 self.debug = true;
86 self
87 }
88
89 #[must_use]
95 pub fn pcl(mut self, key: Vec<u8>) -> EnclaveBuilder {
96 self.pcl_key = Some(key);
97 self
98 }
99
100 #[must_use]
106 pub fn kss(mut self, config: KssConfig) -> EnclaveBuilder {
107 self.kss_config = Some(config);
108 self
109 }
110
111 pub fn create(mut self) -> Result<Enclave, Error> {
117 let mut enclave_id: sgx_enclave_id_t = 0;
118 let mut ex_features = 0;
119 let mut ex_features_p: [*const c_void; MAX_EX_FEATURES_COUNT] =
120 [ptr::null(); MAX_EX_FEATURES_COUNT];
121
122 if let Some(pcl_key) = self.pcl_key {
123 ex_features |= SGX_CREATE_ENCLAVE_EX_PCL;
124 ex_features_p[SGX_CREATE_ENCLAVE_EX_PCL_BIT_IDX] = pcl_key.as_ptr() as *const c_void;
125 }
126
127 if let Some(kss_config) = self.kss_config {
128 ex_features |= SGX_CREATE_ENCLAVE_EX_KSS;
129 ex_features_p[SGX_CREATE_ENCLAVE_EX_KSS_BIT_IDX] =
130 &kss_config.into() as *const sgx_kss_config_t as *const c_void;
131 }
132
133 unsafe {
134 sgx_create_enclave_from_buffer_ex(
151 self.bytes.as_mut_ptr(),
152 self.bytes.len(),
153 self.debug as c_int,
154 &mut enclave_id,
155 ptr::null_mut(),
156 ex_features,
157 &mut ex_features_p as *mut *const c_void,
158 )
159 }
160 .into_result()
161 .map(|_| Enclave { id: enclave_id })
162 }
163}
164
165impl From<Vec<u8>> for EnclaveBuilder {
166 fn from(bytes: Vec<u8>) -> EnclaveBuilder {
167 EnclaveBuilder {
168 bytes,
169 debug: false,
170 pcl_key: None,
171 kss_config: None,
172 }
173 }
174}
175
176impl From<&[u8]> for EnclaveBuilder {
177 fn from(input: &[u8]) -> EnclaveBuilder {
178 input.to_vec().into()
179 }
180}
181
182impl<const N: usize> From<&[u8; N]> for EnclaveBuilder {
183 fn from(input: &[u8; N]) -> EnclaveBuilder {
184 input.to_vec().into()
185 }
186}
187
188impl TryFrom<File> for EnclaveBuilder {
189 type Error = std::io::Error;
190 fn try_from(mut input: File) -> std::io::Result<EnclaveBuilder> {
191 let mut bytes = vec![];
192 input.read_to_end(&mut bytes)?;
193 Ok(EnclaveBuilder {
194 bytes,
195 debug: false,
196 pcl_key: None,
197 kss_config: None,
198 })
199 }
200}
201
202impl Enclave {
203 pub fn target_info(&self) -> Result<TargetInfo, Error> {
205 let mut target_info = TargetInfo::default().into();
206 unsafe { sgx_get_target_info(self.id, &mut target_info) }.into_result()?;
207 Ok(target_info.into())
208 }
209
210 pub fn id(&self) -> &sgx_enclave_id_t {
214 &self.id
215 }
216}
217
218impl Drop for Enclave {
219 fn drop(&mut self) {
223 unsafe { sgx_destroy_enclave(self.id) };
229 }
230}
231
232#[cfg(test)]
233mod tests {
234 use super::*;
235
236 #[test]
237 fn fail_to_create_enclave_with_bogus_bytes() {
238 let builder = EnclaveBuilder::from(b"garbage bytes");
239 assert_eq!(builder.create(), Err(Error::InvalidEnclave));
240 }
241
242 #[test]
243 fn default_debug_flag_is_0() {
244 let builder = EnclaveBuilder::from(b"");
248 assert_eq!(builder.debug as c_int, 0);
249 }
250
251 #[test]
252 fn when_debug_flag_is_true_it_is_1() {
253 let builder = EnclaveBuilder::from(b"").debug();
254 assert_eq!(builder.debug as c_int, 1);
255 }
256}