1use crate::ffi;
4use core::fmt;
5use core::mem::MaybeUninit;
6use sgx_isa::{Keyrequest, Report, Targetinfo};
7
8#[repr(align(16))]
9struct Align16<T>(pub T);
10
11#[repr(align(128))]
12struct Align128<T>(pub T);
13
14#[repr(align(512))]
15struct Align512<T>(pub T);
16
17#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
19#[repr(u32)]
20pub enum ECallStatus {
21 InvalidAttribute = ffi::STATUS_INVALID_ATTRIBUTE,
22 InvalidCPUSVN = ffi::STATUS_INVALID_CPUSVN,
23 InvalidISVSVN = ffi::STATUS_INVALID_ISVSVN,
24 InvalidKeyname = ffi::STATUS_INVALID_KEYNAME,
25 Unknown = u32::MAX,
26}
27
28impl From<u32> for ECallStatus {
29 fn from(code: u32) -> Self {
30 match code {
31 ffi::STATUS_INVALID_ATTRIBUTE => ECallStatus::InvalidAttribute,
32 ffi::STATUS_INVALID_CPUSVN => ECallStatus::InvalidCPUSVN,
33 ffi::STATUS_INVALID_ISVSVN => ECallStatus::InvalidISVSVN,
34 ffi::STATUS_INVALID_KEYNAME => ECallStatus::InvalidKeyname,
35 _ => ECallStatus::Unknown,
36 }
37 }
38}
39
40impl fmt::Display for ECallStatus {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 ECallStatus::InvalidAttribute => f.write_str("ENCLU error: Invalid attribute"),
44 ECallStatus::InvalidCPUSVN => f.write_str("ENCLU error: Invalid CPUSVN"),
45 ECallStatus::InvalidISVSVN => f.write_str("ENCLU error: Invalid CPUISVN"),
46 ECallStatus::InvalidKeyname => f.write_str("ENCLU error: Invalid Keyname"),
47 ECallStatus::Unknown => f.write_str("ENCLU error: Unknown"),
48 }
49 }
50}
51
52#[cfg(feature = "std")]
53impl std::error::Error for ECallStatus {}
54
55pub fn egetkey(request: Keyrequest) -> Result<[u8; 16], ECallStatus> {
59 let mut out = MaybeUninit::<Align16<[u8; 16]>>::uninit();
60 unsafe {
61 let error = ffi::do_egetkey(
62 &Align512(request) as *const Align512<_> as *const u8,
63 out.as_mut_ptr() as *mut u8,
64 );
65 match error {
66 ffi::STATUS_SUCCESS => Ok(out.assume_init().0),
67 error => Err(ECallStatus::from(error)),
68 }
69 }
70}
71
72pub fn ereport(targetinfo: Targetinfo, reportdata: [u8; 64]) -> Result<Report, ECallStatus> {
76 let mut out = MaybeUninit::<Align512<Report>>::uninit();
77 unsafe {
78 let error = ffi::do_ereport(
79 &Align512(targetinfo) as *const Align512<_> as *const u8,
80 &Align128(reportdata) as *const Align128<_> as *const u8,
81 out.as_mut_ptr() as *mut u8,
82 );
83 match error {
84 ffi::STATUS_SUCCESS => Ok(out.assume_init().0),
85 error => Err(ECallStatus::from(error)),
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use sgx_isa::*;
94
95 #[test]
96 fn empty_seal_key_request() {
97 let request = Keyrequest {
98 keyname: Keyname::Seal as u16,
99 ..Default::default()
100 };
101 assert!(egetkey(request).is_ok())
102 }
103
104 #[test]
105 fn report_for_self() {
106 assert!(ereport(Default::default(), [0; 64]).is_ok())
107 }
108}