1use std::time::{Duration, SystemTime, UNIX_EPOCH};
2
3use bitflags::bitflags;
4use serde_json::Value;
5
6use crate::bridge;
7use crate::certificate::{Certificate, PublicKey};
8use crate::error::{Result, SecurityError};
9pub use crate::policy::Policy;
10
11bitflags! {
12 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13 pub struct TrustOptions: u32 {
14 const ALLOW_EXPIRED = 0x0000_0001;
15 const LEAF_IS_CA = 0x0000_0002;
16 const FETCH_ISSUER_FROM_NET = 0x0000_0004;
17 const ALLOW_EXPIRED_ROOT = 0x0000_0008;
18 const REQUIRE_REVOCATION_PER_CERT = 0x0000_0010;
19 const USE_TRUST_SETTINGS = 0x0000_0020;
20 const IMPLICIT_ANCHORS = 0x0000_0040;
21 }
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
25#[repr(u32)]
26pub enum TrustResultType {
27 Invalid = 0,
28 Proceed = 1,
29 Confirm = 2,
30 Deny = 3,
31 Unspecified = 4,
32 RecoverableTrustFailure = 5,
33 FatalTrustFailure = 6,
34 OtherError = 7,
35}
36
37impl TrustResultType {
38 fn from_raw(raw: u32) -> Result<Self> {
39 match raw {
40 0 => Ok(Self::Invalid),
41 1 => Ok(Self::Proceed),
42 2 => Ok(Self::Confirm),
43 3 => Ok(Self::Deny),
44 4 => Ok(Self::Unspecified),
45 5 => Ok(Self::RecoverableTrustFailure),
46 6 => Ok(Self::FatalTrustFailure),
47 7 => Ok(Self::OtherError),
48 _ => Err(SecurityError::InvalidArgument(format!(
49 "unexpected trust result type: {raw}"
50 ))),
51 }
52 }
53}
54
55#[derive(Debug)]
56pub struct Trust {
57 handle: bridge::Handle,
58}
59
60impl Trust {
61 pub fn type_id() -> usize {
62 unsafe { bridge::security_trust_get_type_id() }
63 }
64
65 pub fn new(certificate: &Certificate, policies: &[Policy]) -> Result<Self> {
66 Self::from_certificates(std::slice::from_ref(certificate), policies)
67 }
68
69 pub fn from_certificates(certificates: &[Certificate], policies: &[Policy]) -> Result<Self> {
70 let certificate_handles = certificates
71 .iter()
72 .map(Certificate::handle)
73 .collect::<Vec<_>>();
74 let policy_handles = policies.iter().map(Policy::handle).collect::<Vec<_>>();
75 let certificate_pointers = bridge::handle_pointer_array(&certificate_handles);
76 let policy_pointers = bridge::handle_pointer_array(&policy_handles);
77 let mut status = 0;
78 let mut error = std::ptr::null_mut();
79 let raw = unsafe {
80 bridge::security_trust_create(
81 certificate_pointers.as_ptr(),
82 bridge::len_to_isize(certificate_pointers.len())?,
83 policy_pointers.as_ptr(),
84 bridge::len_to_isize(policy_pointers.len())?,
85 &mut status,
86 &mut error,
87 )
88 };
89 bridge::required_handle("security_trust_create", raw, status, error)
90 .map(|handle| Self { handle })
91 }
92
93 pub fn set_policies(&mut self, policies: &[Policy]) -> Result<()> {
94 let policy_handles = policies.iter().map(Policy::handle).collect::<Vec<_>>();
95 let pointers = bridge::handle_pointer_array(&policy_handles);
96 let mut error = std::ptr::null_mut();
97 let status = unsafe {
98 bridge::security_trust_set_policies(
99 self.handle.as_ptr(),
100 pointers.as_ptr(),
101 bridge::len_to_isize(pointers.len())?,
102 &mut error,
103 )
104 };
105 bridge::status_result("security_trust_set_policies", status, error)
106 }
107
108 pub fn policies(&self) -> Result<Value> {
109 let mut status = 0;
110 let mut error = std::ptr::null_mut();
111 let raw = unsafe {
112 bridge::security_trust_copy_policies(self.handle.as_ptr(), &mut status, &mut error)
113 };
114 bridge::required_json("security_trust_copy_policies", raw, status, error)
115 }
116
117 pub fn set_anchor_certificates(&mut self, certificates: &[Certificate]) -> Result<()> {
118 let certificate_handles = certificates
119 .iter()
120 .map(Certificate::handle)
121 .collect::<Vec<_>>();
122 let pointers = bridge::handle_pointer_array(&certificate_handles);
123 let mut error = std::ptr::null_mut();
124 let status = unsafe {
125 bridge::security_trust_set_anchor_certificates(
126 self.handle.as_ptr(),
127 pointers.as_ptr(),
128 bridge::len_to_isize(pointers.len())?,
129 &mut error,
130 )
131 };
132 bridge::status_result("security_trust_set_anchor_certificates", status, error)
133 }
134
135 pub fn custom_anchor_certificates(&self) -> Result<Value> {
136 let mut status = 0;
137 let mut error = std::ptr::null_mut();
138 let raw = unsafe {
139 bridge::security_trust_copy_custom_anchor_certificates(
140 self.handle.as_ptr(),
141 &mut status,
142 &mut error,
143 )
144 };
145 bridge::required_json(
146 "security_trust_copy_custom_anchor_certificates",
147 raw,
148 status,
149 error,
150 )
151 }
152
153 pub fn set_anchor_certificates_only(&mut self, only_anchor_certificates: bool) -> Result<()> {
154 let mut error = std::ptr::null_mut();
155 let status = unsafe {
156 bridge::security_trust_set_anchor_certificates_only(
157 self.handle.as_ptr(),
158 only_anchor_certificates,
159 &mut error,
160 )
161 };
162 bridge::status_result("security_trust_set_anchor_certificates_only", status, error)
163 }
164
165 pub fn set_network_fetch_allowed(&mut self, allowed: bool) -> Result<()> {
166 let mut error = std::ptr::null_mut();
167 let status = unsafe {
168 bridge::security_trust_set_network_fetch_allowed(
169 self.handle.as_ptr(),
170 allowed,
171 &mut error,
172 )
173 };
174 bridge::status_result("security_trust_set_network_fetch_allowed", status, error)
175 }
176
177 pub fn network_fetch_allowed(&self) -> Result<bool> {
178 let mut status = 0;
179 let mut error = std::ptr::null_mut();
180 let allowed = unsafe {
181 bridge::security_trust_get_network_fetch_allowed(
182 self.handle.as_ptr(),
183 &mut status,
184 &mut error,
185 )
186 };
187 if status != 0 {
188 return Err(bridge::status_error(
189 "security_trust_get_network_fetch_allowed",
190 status,
191 error,
192 )?);
193 }
194 Ok(allowed)
195 }
196
197 pub fn set_verify_date(&mut self, verify_date: SystemTime) -> Result<()> {
198 let mut error = std::ptr::null_mut();
199 let status = unsafe {
200 bridge::security_trust_set_verify_date(
201 self.handle.as_ptr(),
202 system_time_to_unix(verify_date),
203 &mut error,
204 )
205 };
206 bridge::status_result("security_trust_set_verify_date", status, error)
207 }
208
209 pub fn verify_time(&self) -> Result<Option<SystemTime>> {
210 let mut status = 0;
211 let mut error = std::ptr::null_mut();
212 let raw = unsafe {
213 bridge::security_trust_get_verify_time(self.handle.as_ptr(), &mut status, &mut error)
214 };
215 if status != 0 {
216 return Err(bridge::status_error(
217 "security_trust_get_verify_time",
218 status,
219 error,
220 )?);
221 }
222 bridge::optional_json::<Value>(raw)?
223 .map_or(Ok(None), |value| decode_trust_date(value).map(Some))
224 }
225
226 pub fn evaluate(&self) -> Result<()> {
227 let mut error = std::ptr::null_mut();
228 let trusted = unsafe { bridge::security_trust_evaluate(self.handle.as_ptr(), &mut error) };
229 if trusted {
230 Ok(())
231 } else {
232 let message = bridge::optional_string(error)?
233 .unwrap_or_else(|| "trust evaluation failed".to_owned());
234 Err(SecurityError::TrustEvaluationFailed(message))
235 }
236 }
237
238 pub fn evaluate_async(&self) -> Result<()> {
239 let mut status = 0;
240 let mut error = std::ptr::null_mut();
241 let trusted = unsafe {
242 bridge::security_trust_evaluate_async(self.handle.as_ptr(), &mut status, &mut error)
243 };
244 if status != 0 {
245 return Err(bridge::status_error(
246 "security_trust_evaluate_async",
247 status,
248 error,
249 )?);
250 }
251 if trusted {
252 Ok(())
253 } else {
254 let message = bridge::optional_string(error)?
255 .unwrap_or_else(|| "trust evaluation failed".to_owned());
256 Err(SecurityError::TrustEvaluationFailed(message))
257 }
258 }
259
260 pub fn trust_result_type(&self) -> Result<TrustResultType> {
261 let mut status = 0;
262 let mut error = std::ptr::null_mut();
263 let raw = unsafe {
264 bridge::security_trust_get_trust_result(self.handle.as_ptr(), &mut status, &mut error)
265 };
266 if status != 0 {
267 return Err(bridge::status_error(
268 "security_trust_get_trust_result",
269 status,
270 error,
271 )?);
272 }
273 TrustResultType::from_raw(raw)
274 }
275
276 pub fn result(&self) -> Result<Value> {
277 let mut status = 0;
278 let mut error = std::ptr::null_mut();
279 let raw = unsafe {
280 bridge::security_trust_copy_result(self.handle.as_ptr(), &mut status, &mut error)
281 };
282 bridge::required_json("security_trust_copy_result", raw, status, error)
283 }
284
285 pub fn key(&self) -> Result<Option<PublicKey>> {
286 let mut status = 0;
287 let mut error = std::ptr::null_mut();
288 let raw = unsafe {
289 bridge::security_trust_copy_key(self.handle.as_ptr(), &mut status, &mut error)
290 };
291 if status != 0 {
292 return Err(bridge::status_error(
293 "security_trust_copy_key",
294 status,
295 error,
296 )?);
297 }
298 Ok(bridge::Handle::from_raw(raw).map(PublicKey::from_handle))
299 }
300
301 pub fn certificate_count(&self) -> usize {
302 usize::try_from(unsafe {
303 bridge::security_trust_get_certificate_count(self.handle.as_ptr())
304 })
305 .unwrap_or_default()
306 }
307
308 pub fn certificate_chain(&self) -> Result<Vec<Certificate>> {
309 let mut status = 0;
310 let mut error = std::ptr::null_mut();
311 let raw = unsafe {
312 bridge::security_trust_copy_certificate_chain(
313 self.handle.as_ptr(),
314 &mut status,
315 &mut error,
316 )
317 };
318 let array_handle =
319 bridge::required_handle("security_trust_copy_certificate_chain", raw, status, error)?;
320 let count = usize::try_from(unsafe {
321 bridge::security_certificate_array_get_count(array_handle.as_ptr())
322 })
323 .unwrap_or_default();
324 let mut certificates = Vec::with_capacity(count);
325 for index in 0..count {
326 let mut status = 0;
327 let mut error = std::ptr::null_mut();
328 let raw = unsafe {
329 bridge::security_certificate_array_copy_item(
330 array_handle.as_ptr(),
331 bridge::len_to_isize(index)?,
332 &mut status,
333 &mut error,
334 )
335 };
336 let handle = bridge::required_handle(
337 "security_certificate_array_copy_item",
338 raw,
339 status,
340 error,
341 )?;
342 certificates.push(Certificate::from_handle(handle));
343 }
344 Ok(certificates)
345 }
346
347 pub fn exceptions(&self) -> Result<Option<Vec<u8>>> {
348 let mut status = 0;
349 let mut error = std::ptr::null_mut();
350 let raw = unsafe {
351 bridge::security_trust_copy_exceptions(self.handle.as_ptr(), &mut status, &mut error)
352 };
353 if status != 0 {
354 return Err(bridge::status_error(
355 "security_trust_copy_exceptions",
356 status,
357 error,
358 )?);
359 }
360 bridge::optional_data(raw)
361 }
362
363 pub fn set_exceptions(&mut self, exceptions: Option<&[u8]>) -> Result<bool> {
364 let mut error = std::ptr::null_mut();
365 let accepted = unsafe {
366 bridge::security_trust_set_exceptions(
367 self.handle.as_ptr(),
368 exceptions.map_or(std::ptr::null(), |value| value.as_ptr().cast()),
369 exceptions.map_or(Ok(0), |value| bridge::len_to_isize(value.len()))?,
370 &mut error,
371 )
372 };
373 if !error.is_null() {
374 return Err(bridge::status_error(
375 "security_trust_set_exceptions",
376 -1,
377 error,
378 )?);
379 }
380 Ok(accepted)
381 }
382
383 pub fn set_ocsp_responses(&mut self, responses: &[Vec<u8>]) -> Result<()> {
384 let responses = bridge::json_cstring(&responses)?;
385 let mut error = std::ptr::null_mut();
386 let status = unsafe {
387 bridge::security_trust_set_ocsp_response(
388 self.handle.as_ptr(),
389 responses.as_ptr(),
390 &mut error,
391 )
392 };
393 bridge::status_result("security_trust_set_ocsp_response", status, error)
394 }
395
396 pub fn set_signed_certificate_timestamps(&mut self, timestamps: &[Vec<u8>]) -> Result<()> {
397 let timestamps = bridge::json_cstring(×tamps)?;
398 let mut error = std::ptr::null_mut();
399 let status = unsafe {
400 bridge::security_trust_set_signed_certificate_timestamps(
401 self.handle.as_ptr(),
402 timestamps.as_ptr(),
403 &mut error,
404 )
405 };
406 bridge::status_result(
407 "security_trust_set_signed_certificate_timestamps",
408 status,
409 error,
410 )
411 }
412
413 pub fn set_options(&mut self, options: TrustOptions) -> Result<()> {
414 let mut error = std::ptr::null_mut();
415 let status = unsafe {
416 bridge::security_trust_set_options(self.handle.as_ptr(), options.bits(), &mut error)
417 };
418 bridge::status_result("security_trust_set_options", status, error)
419 }
420
421 pub fn system_anchor_certificates() -> Result<Value> {
422 let mut status = 0;
423 let mut error = std::ptr::null_mut();
424 let raw =
425 unsafe { bridge::security_trust_copy_anchor_certificates(&mut status, &mut error) };
426 bridge::required_json(
427 "security_trust_copy_anchor_certificates",
428 raw,
429 status,
430 error,
431 )
432 }
433}
434
435fn decode_trust_date(value: Value) -> Result<SystemTime> {
436 let unix =
437 value
438 .get("unix")
439 .and_then(Value::as_f64)
440 .ok_or_else(|| SecurityError::UnexpectedType {
441 operation: "security_trust_get_verify_time",
442 expected: "date JSON object",
443 })?;
444 let duration = Duration::from_secs_f64(unix.abs());
445 if unix >= 0.0 {
446 Ok(UNIX_EPOCH + duration)
447 } else {
448 UNIX_EPOCH.checked_sub(duration).ok_or_else(|| {
449 SecurityError::InvalidArgument(
450 "trust verify time preceded UNIX_EPOCH by too much".to_owned(),
451 )
452 })
453 }
454}
455
456fn system_time_to_unix(time: SystemTime) -> f64 {
457 match time.duration_since(UNIX_EPOCH) {
458 Ok(duration) => duration.as_secs_f64(),
459 Err(error) => -error.duration().as_secs_f64(),
460 }
461}