1use crate::prelude::*;
2
3use bincode::{deserialize, serialize};
4use std::ffi::{c_char, c_int, c_uchar, CStr};
5use std::slice::{from_raw_parts, from_raw_parts_mut};
6
7const STR_REALM_CHALLENGE: &str = "Realm challenge";
8const STR_REALM_INITIAL_MEASUREMENT: &str = "Realm initial measurement";
9const STR_USER_DATA: &str = "User data";
10const STR_PLAT_PROFILE: &str = "Profile";
11
12#[allow(non_camel_case_types)]
13#[repr(C)]
14pub enum islet_status_t {
15 ISLET_SUCCESS = 0,
16 ISLET_FAILURE = -1,
17 ISLET_ERROR_INPUT = -2,
18 ISLET_ERROR_WRONG_REPORT = -3,
19 ISLET_ERROR_WRONG_CLAIMS = -4,
20 ISLET_ERROR_FEATURE_NOT_SUPPORTED = -5,
21}
22
23#[no_mangle]
30pub unsafe extern "C" fn islet_attest(
31 user_data: *const c_uchar,
32 user_data_len: c_int,
33 report_out: *mut c_uchar,
34 report_out_len: *mut c_int,
35) -> islet_status_t {
36 if user_data_len > 64 {
37 return islet_status_t::ISLET_ERROR_INPUT;
38 }
39
40 let do_attest = || -> Result<(), Error> {
41 let user_data = from_raw_parts(user_data as *const u8, user_data_len as usize);
42 let report = attest(user_data)?;
43 let encoded = serialize(&report).or(Err(Error::Serialize))?;
44 *report_out_len = encoded.len() as c_int;
45 let out = from_raw_parts_mut(report_out, encoded.len());
46 out.copy_from_slice(&encoded[..]);
47 Ok(())
48 };
49
50 match do_attest() {
51 Ok(()) => islet_status_t::ISLET_SUCCESS,
52 Err(_) => islet_status_t::ISLET_FAILURE,
53 }
54}
55
56#[no_mangle]
58pub unsafe extern "C" fn islet_verify(
59 report: *const c_uchar,
60 report_len: c_int,
61 claims_out: *mut c_uchar,
62 claims_out_len: *mut c_int,
63) -> islet_status_t {
64 let do_verify = || -> Result<(), Error> {
65 let encoded = from_raw_parts(report as *const u8, report_len as usize);
66 let decoded: Report = deserialize(encoded).or(Err(Error::Report))?;
67
68 let _claims = verify(&decoded)?;
69
70 let out = std::slice::from_raw_parts_mut(claims_out, encoded.len());
73 out.copy_from_slice(&encoded[..]);
74 *claims_out_len = out.len() as c_int;
75 Ok(())
76 };
77
78 match do_verify() {
79 Ok(()) => islet_status_t::ISLET_SUCCESS,
80 Err(Error::Report) => islet_status_t::ISLET_ERROR_WRONG_REPORT,
81 Err(_) => islet_status_t::ISLET_FAILURE,
82 }
83}
84
85#[no_mangle]
87pub unsafe extern "C" fn islet_parse(
88 title: *const c_char,
89 claims: *const c_uchar,
90 claims_len: c_int,
91 value_out: *mut c_uchar,
92 value_out_len: *mut c_int,
93) -> islet_status_t {
94 let do_parse = || -> Result<(), Error> {
95 let encoded = from_raw_parts(claims as *const u8, claims_len as usize);
98 let decoded: Report = deserialize(encoded).or(Err(Error::Report))?;
99
100 let claims = verify(&decoded)?;
101 let title = CStr::from_ptr(title).to_str().or(Err(Error::Decoding))?;
102
103 let (realm_claims, plat_claims) = parse(&claims)?;
104 let value = if title == STR_USER_DATA || title == STR_REALM_CHALLENGE {
105 Ok(realm_claims.challenge.clone())
106 } else if title == STR_REALM_INITIAL_MEASUREMENT {
107 Ok(realm_claims.rim.clone())
108 } else if title == STR_PLAT_PROFILE {
109 Ok(plat_claims.profile.as_bytes().to_vec())
110 } else {
111 Err(Error::NotSupported)
112 }?;
113 *value_out_len = value.len() as c_int;
114 let out = from_raw_parts_mut(value_out, value.len());
115 out.copy_from_slice(&value[..]);
116
117 Ok(())
118 };
119
120 match do_parse() {
121 Ok(()) => islet_status_t::ISLET_SUCCESS,
122 Err(Error::Claims) => islet_status_t::ISLET_ERROR_WRONG_CLAIMS,
123 Err(_) => islet_status_t::ISLET_FAILURE,
124 }
125}
126
127#[no_mangle]
129pub unsafe extern "C" fn islet_print_claims(claims: *const c_uchar, claims_len: c_int) {
130 let encoded = from_raw_parts(claims as *const u8, claims_len as usize);
133 let decoded: Result<Report, Error> = deserialize(encoded).or(Err(Error::Report));
134 if decoded.is_err() {
135 println!("Wrong claims.");
136 }
137
138 match verify(&decoded.unwrap()) {
139 Ok(claims) => crate::parser::print_claims(&claims),
140 Err(error) => println!("Wrong claims {:?}", error),
141 }
142}
143
144#[no_mangle]
150pub unsafe extern "C" fn islet_seal(
151 plaintext: *const c_uchar,
152 plaintext_len: c_int,
153 sealed_out: *mut c_uchar,
154 sealed_out_len: *mut c_int,
155) -> islet_status_t {
156 let do_seal = || -> Result<(), Error> {
157 let plaintext = from_raw_parts(plaintext as *const u8, plaintext_len as usize);
158 let sealed = seal(plaintext)?;
159 *sealed_out_len = sealed.len() as c_int;
160 let out = from_raw_parts_mut(sealed_out, sealed.len());
161 out.copy_from_slice(&sealed[..]);
162 Ok(())
163 };
164
165 match do_seal() {
166 Ok(()) => islet_status_t::ISLET_SUCCESS,
167 Err(_) => islet_status_t::ISLET_FAILURE,
168 }
169}
170
171#[no_mangle]
177pub unsafe extern "C" fn islet_unseal(
178 sealed: *const c_uchar,
179 sealed_len: c_int,
180 plaintext_out: *mut c_uchar,
181 plaintext_out_len: *mut c_int,
182) -> islet_status_t {
183 let do_unseal = || -> Result<(), Error> {
184 let sealed = from_raw_parts(sealed as *const u8, sealed_len as usize);
185 let plaintext = unseal(sealed)?;
186 *plaintext_out_len = plaintext.len() as c_int;
187 let out = from_raw_parts_mut(plaintext_out, plaintext.len());
188 out.copy_from_slice(&plaintext[..]);
189 Ok(())
190 };
191
192 match do_unseal() {
193 Ok(()) => islet_status_t::ISLET_SUCCESS,
194 Err(_) => islet_status_t::ISLET_FAILURE,
195 }
196}