1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use super::super::{PlatformError, Result};
use libc::*;
use log::debug;
use sgx_crypto::ecc::EcPublicKey;
use sgx_rand::{RdRand, Rng};
use sgx_types::types::*;
use std::ffi::CString;
const SGX_CMD_NUM_GEN_EPID_QUOTE: u64 = (2u32
| ('s' as u32) << 8
| (std::mem::size_of::<IoctlGenEPIDQuoteArg>() as u32) << 16
| 3u32 << 30) as u64;
const IOCTL_MAX_RETRIES: u32 = 20;
const SGXIOC_GET_DCAP_QUOTE_SIZE: u64 = 0x80047307;
const SGXIOC_GEN_DCAP_QUOTE: u64 = 0xc0187308;
#[repr(C)]
pub struct IoctlGenDCAPQuoteArg {
pub report_data: *const ReportData, pub quote_size: *mut u32, pub quote_buf: *mut u8, }
#[repr(C)]
struct IoctlGenEPIDQuoteArg {
report_data: ReportData, quote_type: QuoteSignType, spid: Spid, nonce: QuoteNonce, sigrl_ptr: *const u8, sigrl_len: u32, quote_buf_len: u32, quote_buf: *mut u8, }
fn get_dev_fd() -> libc::c_int {
let path = CString::new("/dev/sgx").unwrap();
let fd = unsafe { libc::open(path.as_ptr(), O_RDONLY) };
if fd > 0 {
fd
} else {
panic!("Open /dev/sgx failed")
}
}
pub(crate) fn create_sgx_report_data(pub_k: EcPublicKey) -> ReportData {
debug!("create_sgx_report_data");
let mut report_data: ReportData = ReportData::default();
let mut pub_k_gx = pub_k.public_key().gx;
pub_k_gx.reverse();
let mut pub_k_gy = pub_k.public_key().gy;
pub_k_gy.reverse();
report_data.d[..32].clone_from_slice(&pub_k_gx);
report_data.d[32..].clone_from_slice(&pub_k_gy);
report_data
}
macro_rules! do_ioctl {
($cmd:expr,$arg:expr) => {
let mut retries = 0;
let mut ret = -1;
let fd = get_dev_fd();
log::debug!("begin do_ioctl {}", stringify!($cmd));
while retries < IOCTL_MAX_RETRIES {
ret = unsafe { libc::ioctl(fd, $cmd, $arg) };
if ret == 0 {
break;
}
std::thread::sleep(std::time::Duration::from_secs(2));
retries += 1;
}
if retries == IOCTL_MAX_RETRIES {
return Err(PlatformError::Ioctl(stringify!($cmd).to_string(), ret));
}
};
}
pub(crate) fn get_sgx_epid_quote(spid: &Spid, report_data: ReportData) -> Result<Vec<u8>> {
let sigrl_ptr: *const u8 = std::ptr::null();
let quote_len: u32 = 4096;
let mut quote = vec![0u8; quote_len as usize];
let mut qe_report_info = QeReportInfo::default();
let mut quote_nonce = QuoteNonce::default();
let mut rng = RdRand::new().map_err(PlatformError::RngError)?;
rng.fill_bytes(&mut quote_nonce.rand);
qe_report_info.nonce = quote_nonce;
debug!("SGX_CMD_NUM_GEN_EPID_QUOTE");
let mut quote_arg = IoctlGenEPIDQuoteArg {
report_data, quote_type: QuoteSignType::Linkable, spid: spid.to_owned(), nonce: quote_nonce, sigrl_ptr, sigrl_len: 0, quote_buf_len: quote_len, quote_buf: quote.as_mut_ptr(), };
do_ioctl!(SGX_CMD_NUM_GEN_EPID_QUOTE, &mut quote_arg);
let sgx_quote = unsafe { &*(quote.as_ptr() as *const Quote) };
let quote_size = std::mem::size_of::<Quote>() + sgx_quote.signature_len as usize;
if quote_size > quote.len() {
return Err(PlatformError::GetQuote("wrong quote size".to_string()));
}
let quote_buf = quote[..quote_size].to_vec();
Ok(quote_buf)
}
pub(crate) fn get_sgx_dcap_quote(_spid: &Spid, report_data: ReportData) -> Result<Vec<u8>> {
let mut quote_len: u32 = 0;
do_ioctl!(SGXIOC_GET_DCAP_QUOTE_SIZE, &mut quote_len);
let mut quote_buf = vec![0; quote_len as usize];
let mut quote_arg: IoctlGenDCAPQuoteArg = IoctlGenDCAPQuoteArg {
report_data: &report_data as _,
quote_size: &mut quote_len,
quote_buf: quote_buf.as_mut_ptr(),
};
do_ioctl!(SGXIOC_GEN_DCAP_QUOTE, &mut quote_arg);
Ok(quote_buf)
}