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 {
15 const ALLOW_EXPIRED = 0x0000_0001;
17 const LEAF_IS_CA = 0x0000_0002;
19 const FETCH_ISSUER_FROM_NET = 0x0000_0004;
21 const ALLOW_EXPIRED_ROOT = 0x0000_0008;
23 const REQUIRE_REVOCATION_PER_CERT = 0x0000_0010;
25 const USE_TRUST_SETTINGS = 0x0000_0020;
27 const IMPLICIT_ANCHORS = 0x0000_0040;
29 }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33#[repr(u32)]
34pub enum TrustResultType {
36 Invalid = 0,
38 Proceed = 1,
40 Confirm = 2,
42 Deny = 3,
44 Unspecified = 4,
46 RecoverableTrustFailure = 5,
48 FatalTrustFailure = 6,
50 OtherError = 7,
52}
53
54impl TrustResultType {
55 fn from_raw(raw: u32) -> Result<Self> {
56 match raw {
57 0 => Ok(Self::Invalid),
58 1 => Ok(Self::Proceed),
59 2 => Ok(Self::Confirm),
60 3 => Ok(Self::Deny),
61 4 => Ok(Self::Unspecified),
62 5 => Ok(Self::RecoverableTrustFailure),
63 6 => Ok(Self::FatalTrustFailure),
64 7 => Ok(Self::OtherError),
65 _ => Err(SecurityError::InvalidArgument(format!(
66 "unexpected trust result type: {raw}"
67 ))),
68 }
69 }
70}
71
72#[derive(Debug)]
73pub struct Trust {
75 handle: bridge::Handle,
76}
77
78impl Trust {
79 #[cfg(feature = "async")]
80 pub(crate) fn as_ptr(&self) -> *mut std::ffi::c_void {
81 self.handle.as_ptr()
82 }
83
84 pub fn type_id() -> usize {
86 unsafe { bridge::security_trust_get_type_id() }
87 }
88
89 pub fn new(certificate: &Certificate, policies: &[Policy]) -> Result<Self> {
91 Self::from_certificates(std::slice::from_ref(certificate), policies)
92 }
93
94 pub fn from_certificates(certificates: &[Certificate], policies: &[Policy]) -> Result<Self> {
96 let certificate_handles = certificates
97 .iter()
98 .map(Certificate::handle)
99 .collect::<Vec<_>>();
100 let policy_handles = policies.iter().map(Policy::handle).collect::<Vec<_>>();
101 let certificate_pointers = bridge::handle_pointer_array(&certificate_handles);
102 let policy_pointers = bridge::handle_pointer_array(&policy_handles);
103 let mut status = 0;
104 let mut error = std::ptr::null_mut();
105 let raw = unsafe {
106 bridge::security_trust_create(
107 certificate_pointers.as_ptr(),
108 bridge::len_to_isize(certificate_pointers.len())?,
109 policy_pointers.as_ptr(),
110 bridge::len_to_isize(policy_pointers.len())?,
111 &mut status,
112 &mut error,
113 )
114 };
115 bridge::required_handle("security_trust_create", raw, status, error)
116 .map(|handle| Self { handle })
117 }
118
119 pub fn set_policies(&mut self, policies: &[Policy]) -> Result<()> {
121 let policy_handles = policies.iter().map(Policy::handle).collect::<Vec<_>>();
122 let pointers = bridge::handle_pointer_array(&policy_handles);
123 let mut error = std::ptr::null_mut();
124 let status = unsafe {
125 bridge::security_trust_set_policies(
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_policies", status, error)
133 }
134
135 pub fn policies(&self) -> Result<Value> {
137 let mut status = 0;
138 let mut error = std::ptr::null_mut();
139 let raw = unsafe {
140 bridge::security_trust_copy_policies(self.handle.as_ptr(), &mut status, &mut error)
141 };
142 bridge::required_json("security_trust_copy_policies", raw, status, error)
143 }
144
145 pub fn set_anchor_certificates(&mut self, certificates: &[Certificate]) -> Result<()> {
147 let certificate_handles = certificates
148 .iter()
149 .map(Certificate::handle)
150 .collect::<Vec<_>>();
151 let pointers = bridge::handle_pointer_array(&certificate_handles);
152 let mut error = std::ptr::null_mut();
153 let status = unsafe {
154 bridge::security_trust_set_anchor_certificates(
155 self.handle.as_ptr(),
156 pointers.as_ptr(),
157 bridge::len_to_isize(pointers.len())?,
158 &mut error,
159 )
160 };
161 bridge::status_result("security_trust_set_anchor_certificates", status, error)
162 }
163
164 pub fn custom_anchor_certificates(&self) -> Result<Value> {
166 let mut status = 0;
167 let mut error = std::ptr::null_mut();
168 let raw = unsafe {
169 bridge::security_trust_copy_custom_anchor_certificates(
170 self.handle.as_ptr(),
171 &mut status,
172 &mut error,
173 )
174 };
175 bridge::required_json(
176 "security_trust_copy_custom_anchor_certificates",
177 raw,
178 status,
179 error,
180 )
181 }
182
183 pub fn set_anchor_certificates_only(&mut self, only_anchor_certificates: bool) -> Result<()> {
185 let mut error = std::ptr::null_mut();
186 let status = unsafe {
187 bridge::security_trust_set_anchor_certificates_only(
188 self.handle.as_ptr(),
189 only_anchor_certificates,
190 &mut error,
191 )
192 };
193 bridge::status_result("security_trust_set_anchor_certificates_only", status, error)
194 }
195
196 pub fn set_network_fetch_allowed(&mut self, allowed: bool) -> Result<()> {
198 let mut error = std::ptr::null_mut();
199 let status = unsafe {
200 bridge::security_trust_set_network_fetch_allowed(
201 self.handle.as_ptr(),
202 allowed,
203 &mut error,
204 )
205 };
206 bridge::status_result("security_trust_set_network_fetch_allowed", status, error)
207 }
208
209 pub fn network_fetch_allowed(&self) -> Result<bool> {
211 let mut status = 0;
212 let mut error = std::ptr::null_mut();
213 let allowed = unsafe {
214 bridge::security_trust_get_network_fetch_allowed(
215 self.handle.as_ptr(),
216 &mut status,
217 &mut error,
218 )
219 };
220 if status != 0 {
221 return Err(bridge::status_error(
222 "security_trust_get_network_fetch_allowed",
223 status,
224 error,
225 )?);
226 }
227 Ok(allowed)
228 }
229
230 pub fn set_verify_date(&mut self, verify_date: SystemTime) -> Result<()> {
232 let mut error = std::ptr::null_mut();
233 let status = unsafe {
234 bridge::security_trust_set_verify_date(
235 self.handle.as_ptr(),
236 system_time_to_unix(verify_date),
237 &mut error,
238 )
239 };
240 bridge::status_result("security_trust_set_verify_date", status, error)
241 }
242
243 pub fn verify_time(&self) -> Result<Option<SystemTime>> {
245 let mut status = 0;
246 let mut error = std::ptr::null_mut();
247 let raw = unsafe {
248 bridge::security_trust_get_verify_time(self.handle.as_ptr(), &mut status, &mut error)
249 };
250 if status != 0 {
251 return Err(bridge::status_error(
252 "security_trust_get_verify_time",
253 status,
254 error,
255 )?);
256 }
257 bridge::optional_json::<Value>(raw)?
258 .map_or(Ok(None), |value| decode_trust_date(value).map(Some))
259 }
260
261 pub fn evaluate(&self) -> Result<()> {
263 let mut error = std::ptr::null_mut();
264 let trusted = unsafe { bridge::security_trust_evaluate(self.handle.as_ptr(), &mut error) };
265 if trusted {
266 Ok(())
267 } else {
268 let message = bridge::optional_string(error)?
269 .unwrap_or_else(|| "trust evaluation failed".to_owned());
270 Err(SecurityError::TrustEvaluationFailed(message))
271 }
272 }
273
274 pub fn evaluate_async(&self) -> Result<()> {
276 let mut status = 0;
277 let mut error = std::ptr::null_mut();
278 let trusted = unsafe {
279 bridge::security_trust_evaluate_async(self.handle.as_ptr(), &mut status, &mut error)
280 };
281 if status != 0 {
282 return Err(bridge::status_error(
283 "security_trust_evaluate_async",
284 status,
285 error,
286 )?);
287 }
288 if trusted {
289 Ok(())
290 } else {
291 let message = bridge::optional_string(error)?
292 .unwrap_or_else(|| "trust evaluation failed".to_owned());
293 Err(SecurityError::TrustEvaluationFailed(message))
294 }
295 }
296
297 pub fn trust_result_type(&self) -> Result<TrustResultType> {
299 let mut status = 0;
300 let mut error = std::ptr::null_mut();
301 let raw = unsafe {
302 bridge::security_trust_get_trust_result(self.handle.as_ptr(), &mut status, &mut error)
303 };
304 if status != 0 {
305 return Err(bridge::status_error(
306 "security_trust_get_trust_result",
307 status,
308 error,
309 )?);
310 }
311 TrustResultType::from_raw(raw)
312 }
313
314 pub fn result(&self) -> Result<Value> {
316 let mut status = 0;
317 let mut error = std::ptr::null_mut();
318 let raw = unsafe {
319 bridge::security_trust_copy_result(self.handle.as_ptr(), &mut status, &mut error)
320 };
321 bridge::required_json("security_trust_copy_result", raw, status, error)
322 }
323
324 pub fn key(&self) -> Result<Option<PublicKey>> {
326 let mut status = 0;
327 let mut error = std::ptr::null_mut();
328 let raw = unsafe {
329 bridge::security_trust_copy_key(self.handle.as_ptr(), &mut status, &mut error)
330 };
331 if status != 0 {
332 return Err(bridge::status_error(
333 "security_trust_copy_key",
334 status,
335 error,
336 )?);
337 }
338 Ok(bridge::Handle::from_raw(raw).map(PublicKey::from_handle))
339 }
340
341 pub fn certificate_count(&self) -> usize {
343 usize::try_from(unsafe {
344 bridge::security_trust_get_certificate_count(self.handle.as_ptr())
345 })
346 .unwrap_or_default()
347 }
348
349 pub fn certificate_chain(&self) -> Result<Vec<Certificate>> {
351 let mut status = 0;
352 let mut error = std::ptr::null_mut();
353 let raw = unsafe {
354 bridge::security_trust_copy_certificate_chain(
355 self.handle.as_ptr(),
356 &mut status,
357 &mut error,
358 )
359 };
360 let array_handle =
361 bridge::required_handle("security_trust_copy_certificate_chain", raw, status, error)?;
362 let count = usize::try_from(unsafe {
363 bridge::security_certificate_array_get_count(array_handle.as_ptr())
364 })
365 .unwrap_or_default();
366 let mut certificates = Vec::with_capacity(count);
367 for index in 0..count {
368 let mut status = 0;
369 let mut error = std::ptr::null_mut();
370 let raw = unsafe {
371 bridge::security_certificate_array_copy_item(
372 array_handle.as_ptr(),
373 bridge::len_to_isize(index)?,
374 &mut status,
375 &mut error,
376 )
377 };
378 let handle = bridge::required_handle(
379 "security_certificate_array_copy_item",
380 raw,
381 status,
382 error,
383 )?;
384 certificates.push(Certificate::from_handle(handle));
385 }
386 Ok(certificates)
387 }
388
389 pub fn exceptions(&self) -> Result<Option<Vec<u8>>> {
391 let mut status = 0;
392 let mut error = std::ptr::null_mut();
393 let raw = unsafe {
394 bridge::security_trust_copy_exceptions(self.handle.as_ptr(), &mut status, &mut error)
395 };
396 if status != 0 {
397 return Err(bridge::status_error(
398 "security_trust_copy_exceptions",
399 status,
400 error,
401 )?);
402 }
403 bridge::optional_data(raw)
404 }
405
406 pub fn set_exceptions(&mut self, exceptions: Option<&[u8]>) -> Result<bool> {
408 let mut error = std::ptr::null_mut();
409 let accepted = unsafe {
410 bridge::security_trust_set_exceptions(
411 self.handle.as_ptr(),
412 exceptions.map_or(std::ptr::null(), |value| value.as_ptr().cast()),
413 exceptions.map_or(Ok(0), |value| bridge::len_to_isize(value.len()))?,
414 &mut error,
415 )
416 };
417 if !error.is_null() {
418 return Err(bridge::status_error(
419 "security_trust_set_exceptions",
420 -1,
421 error,
422 )?);
423 }
424 Ok(accepted)
425 }
426
427 pub fn set_ocsp_responses(&mut self, responses: &[Vec<u8>]) -> Result<()> {
429 let responses = bridge::json_cstring(&responses)?;
430 let mut error = std::ptr::null_mut();
431 let status = unsafe {
432 bridge::security_trust_set_ocsp_response(
433 self.handle.as_ptr(),
434 responses.as_ptr(),
435 &mut error,
436 )
437 };
438 bridge::status_result("security_trust_set_ocsp_response", status, error)
439 }
440
441 pub fn set_signed_certificate_timestamps(&mut self, timestamps: &[Vec<u8>]) -> Result<()> {
443 let timestamps = bridge::json_cstring(×tamps)?;
444 let mut error = std::ptr::null_mut();
445 let status = unsafe {
446 bridge::security_trust_set_signed_certificate_timestamps(
447 self.handle.as_ptr(),
448 timestamps.as_ptr(),
449 &mut error,
450 )
451 };
452 bridge::status_result(
453 "security_trust_set_signed_certificate_timestamps",
454 status,
455 error,
456 )
457 }
458
459 pub fn set_options(&mut self, options: TrustOptions) -> Result<()> {
461 let mut error = std::ptr::null_mut();
462 let status = unsafe {
463 bridge::security_trust_set_options(self.handle.as_ptr(), options.bits(), &mut error)
464 };
465 bridge::status_result("security_trust_set_options", status, error)
466 }
467
468 pub fn system_anchor_certificates() -> Result<Value> {
470 let mut status = 0;
471 let mut error = std::ptr::null_mut();
472 let raw =
473 unsafe { bridge::security_trust_copy_anchor_certificates(&mut status, &mut error) };
474 bridge::required_json(
475 "security_trust_copy_anchor_certificates",
476 raw,
477 status,
478 error,
479 )
480 }
481}
482
483fn decode_trust_date(value: Value) -> Result<SystemTime> {
484 let unix =
485 value
486 .get("unix")
487 .and_then(Value::as_f64)
488 .ok_or_else(|| SecurityError::UnexpectedType {
489 operation: "security_trust_get_verify_time",
490 expected: "date JSON object",
491 })?;
492 let duration = Duration::from_secs_f64(unix.abs());
493 if unix >= 0.0 {
494 Ok(UNIX_EPOCH + duration)
495 } else {
496 UNIX_EPOCH.checked_sub(duration).ok_or_else(|| {
497 SecurityError::InvalidArgument(
498 "trust verify time preceded UNIX_EPOCH by too much".to_owned(),
499 )
500 })
501 }
502}
503
504fn system_time_to_unix(time: SystemTime) -> f64 {
505 match time.duration_since(UNIX_EPOCH) {
506 Ok(duration) => duration.as_secs_f64(),
507 Err(error) => -error.duration().as_secs_f64(),
508 }
509}
510
511#[cfg(test)]
512mod tests {
513 use serde_json::json;
514
515 use super::*;
516
517 #[test]
518 fn trust_result_type_from_raw_maps_known_values() {
519 assert_eq!(
520 TrustResultType::from_raw(0).unwrap(),
521 TrustResultType::Invalid
522 );
523 assert_eq!(
524 TrustResultType::from_raw(7).unwrap(),
525 TrustResultType::OtherError
526 );
527 }
528
529 #[test]
530 fn trust_result_type_from_raw_rejects_unknown_values() {
531 assert_eq!(
532 TrustResultType::from_raw(99).unwrap_err(),
533 SecurityError::InvalidArgument("unexpected trust result type: 99".to_owned())
534 );
535 }
536
537 #[test]
538 fn system_time_to_unix_preserves_times_after_epoch() {
539 let time = UNIX_EPOCH + Duration::from_secs_f64(42.5);
540
541 assert!((system_time_to_unix(time) - 42.5).abs() < f64::EPSILON);
542 }
543
544 #[test]
545 fn system_time_to_unix_preserves_times_before_epoch() {
546 let time = UNIX_EPOCH - Duration::from_secs_f64(12.5);
547
548 assert!((system_time_to_unix(time) + 12.5).abs() < f64::EPSILON);
549 }
550
551 #[test]
552 fn decode_trust_date_parses_positive_unix_seconds() {
553 let time = decode_trust_date(json!({ "unix": 42.5 })).unwrap();
554
555 assert_eq!(time, UNIX_EPOCH + Duration::from_secs_f64(42.5));
556 }
557
558 #[test]
559 fn decode_trust_date_parses_negative_unix_seconds() {
560 let time = decode_trust_date(json!({ "unix": -12.5 })).unwrap();
561
562 assert_eq!(time, UNIX_EPOCH - Duration::from_secs_f64(12.5));
563 }
564
565 #[test]
566 fn decode_trust_date_requires_unix_field() {
567 assert!(matches!(
568 decode_trust_date(json!({ "seconds": 1 })).unwrap_err(),
569 SecurityError::UnexpectedType {
570 operation: "security_trust_get_verify_time",
571 expected: "date JSON object",
572 }
573 ));
574 }
575}