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 pub fn type_id() -> usize {
81 unsafe { bridge::security_trust_get_type_id() }
82 }
83
84 pub fn new(certificate: &Certificate, policies: &[Policy]) -> Result<Self> {
86 Self::from_certificates(std::slice::from_ref(certificate), policies)
87 }
88
89 pub fn from_certificates(certificates: &[Certificate], policies: &[Policy]) -> Result<Self> {
91 let certificate_handles = certificates
92 .iter()
93 .map(Certificate::handle)
94 .collect::<Vec<_>>();
95 let policy_handles = policies.iter().map(Policy::handle).collect::<Vec<_>>();
96 let certificate_pointers = bridge::handle_pointer_array(&certificate_handles);
97 let policy_pointers = bridge::handle_pointer_array(&policy_handles);
98 let mut status = 0;
99 let mut error = std::ptr::null_mut();
100 let raw = unsafe {
101 bridge::security_trust_create(
102 certificate_pointers.as_ptr(),
103 bridge::len_to_isize(certificate_pointers.len())?,
104 policy_pointers.as_ptr(),
105 bridge::len_to_isize(policy_pointers.len())?,
106 &mut status,
107 &mut error,
108 )
109 };
110 bridge::required_handle("security_trust_create", raw, status, error)
111 .map(|handle| Self { handle })
112 }
113
114 pub fn set_policies(&mut self, policies: &[Policy]) -> Result<()> {
116 let policy_handles = policies.iter().map(Policy::handle).collect::<Vec<_>>();
117 let pointers = bridge::handle_pointer_array(&policy_handles);
118 let mut error = std::ptr::null_mut();
119 let status = unsafe {
120 bridge::security_trust_set_policies(
121 self.handle.as_ptr(),
122 pointers.as_ptr(),
123 bridge::len_to_isize(pointers.len())?,
124 &mut error,
125 )
126 };
127 bridge::status_result("security_trust_set_policies", status, error)
128 }
129
130 pub fn policies(&self) -> Result<Value> {
132 let mut status = 0;
133 let mut error = std::ptr::null_mut();
134 let raw = unsafe {
135 bridge::security_trust_copy_policies(self.handle.as_ptr(), &mut status, &mut error)
136 };
137 bridge::required_json("security_trust_copy_policies", raw, status, error)
138 }
139
140 pub fn set_anchor_certificates(&mut self, certificates: &[Certificate]) -> Result<()> {
142 let certificate_handles = certificates
143 .iter()
144 .map(Certificate::handle)
145 .collect::<Vec<_>>();
146 let pointers = bridge::handle_pointer_array(&certificate_handles);
147 let mut error = std::ptr::null_mut();
148 let status = unsafe {
149 bridge::security_trust_set_anchor_certificates(
150 self.handle.as_ptr(),
151 pointers.as_ptr(),
152 bridge::len_to_isize(pointers.len())?,
153 &mut error,
154 )
155 };
156 bridge::status_result("security_trust_set_anchor_certificates", status, error)
157 }
158
159 pub fn custom_anchor_certificates(&self) -> Result<Value> {
161 let mut status = 0;
162 let mut error = std::ptr::null_mut();
163 let raw = unsafe {
164 bridge::security_trust_copy_custom_anchor_certificates(
165 self.handle.as_ptr(),
166 &mut status,
167 &mut error,
168 )
169 };
170 bridge::required_json(
171 "security_trust_copy_custom_anchor_certificates",
172 raw,
173 status,
174 error,
175 )
176 }
177
178 pub fn set_anchor_certificates_only(&mut self, only_anchor_certificates: bool) -> Result<()> {
180 let mut error = std::ptr::null_mut();
181 let status = unsafe {
182 bridge::security_trust_set_anchor_certificates_only(
183 self.handle.as_ptr(),
184 only_anchor_certificates,
185 &mut error,
186 )
187 };
188 bridge::status_result("security_trust_set_anchor_certificates_only", status, error)
189 }
190
191 pub fn set_network_fetch_allowed(&mut self, allowed: bool) -> Result<()> {
193 let mut error = std::ptr::null_mut();
194 let status = unsafe {
195 bridge::security_trust_set_network_fetch_allowed(
196 self.handle.as_ptr(),
197 allowed,
198 &mut error,
199 )
200 };
201 bridge::status_result("security_trust_set_network_fetch_allowed", status, error)
202 }
203
204 pub fn network_fetch_allowed(&self) -> Result<bool> {
206 let mut status = 0;
207 let mut error = std::ptr::null_mut();
208 let allowed = unsafe {
209 bridge::security_trust_get_network_fetch_allowed(
210 self.handle.as_ptr(),
211 &mut status,
212 &mut error,
213 )
214 };
215 if status != 0 {
216 return Err(bridge::status_error(
217 "security_trust_get_network_fetch_allowed",
218 status,
219 error,
220 )?);
221 }
222 Ok(allowed)
223 }
224
225 pub fn set_verify_date(&mut self, verify_date: SystemTime) -> Result<()> {
227 let mut error = std::ptr::null_mut();
228 let status = unsafe {
229 bridge::security_trust_set_verify_date(
230 self.handle.as_ptr(),
231 system_time_to_unix(verify_date),
232 &mut error,
233 )
234 };
235 bridge::status_result("security_trust_set_verify_date", status, error)
236 }
237
238 pub fn verify_time(&self) -> Result<Option<SystemTime>> {
240 let mut status = 0;
241 let mut error = std::ptr::null_mut();
242 let raw = unsafe {
243 bridge::security_trust_get_verify_time(self.handle.as_ptr(), &mut status, &mut error)
244 };
245 if status != 0 {
246 return Err(bridge::status_error(
247 "security_trust_get_verify_time",
248 status,
249 error,
250 )?);
251 }
252 bridge::optional_json::<Value>(raw)?
253 .map_or(Ok(None), |value| decode_trust_date(value).map(Some))
254 }
255
256 pub fn evaluate(&self) -> Result<()> {
258 let mut error = std::ptr::null_mut();
259 let trusted = unsafe { bridge::security_trust_evaluate(self.handle.as_ptr(), &mut error) };
260 if trusted {
261 Ok(())
262 } else {
263 let message = bridge::optional_string(error)?
264 .unwrap_or_else(|| "trust evaluation failed".to_owned());
265 Err(SecurityError::TrustEvaluationFailed(message))
266 }
267 }
268
269 pub fn evaluate_async(&self) -> Result<()> {
271 let mut status = 0;
272 let mut error = std::ptr::null_mut();
273 let trusted = unsafe {
274 bridge::security_trust_evaluate_async(self.handle.as_ptr(), &mut status, &mut error)
275 };
276 if status != 0 {
277 return Err(bridge::status_error(
278 "security_trust_evaluate_async",
279 status,
280 error,
281 )?);
282 }
283 if trusted {
284 Ok(())
285 } else {
286 let message = bridge::optional_string(error)?
287 .unwrap_or_else(|| "trust evaluation failed".to_owned());
288 Err(SecurityError::TrustEvaluationFailed(message))
289 }
290 }
291
292 pub fn trust_result_type(&self) -> Result<TrustResultType> {
294 let mut status = 0;
295 let mut error = std::ptr::null_mut();
296 let raw = unsafe {
297 bridge::security_trust_get_trust_result(self.handle.as_ptr(), &mut status, &mut error)
298 };
299 if status != 0 {
300 return Err(bridge::status_error(
301 "security_trust_get_trust_result",
302 status,
303 error,
304 )?);
305 }
306 TrustResultType::from_raw(raw)
307 }
308
309 pub fn result(&self) -> Result<Value> {
311 let mut status = 0;
312 let mut error = std::ptr::null_mut();
313 let raw = unsafe {
314 bridge::security_trust_copy_result(self.handle.as_ptr(), &mut status, &mut error)
315 };
316 bridge::required_json("security_trust_copy_result", raw, status, error)
317 }
318
319 pub fn key(&self) -> Result<Option<PublicKey>> {
321 let mut status = 0;
322 let mut error = std::ptr::null_mut();
323 let raw = unsafe {
324 bridge::security_trust_copy_key(self.handle.as_ptr(), &mut status, &mut error)
325 };
326 if status != 0 {
327 return Err(bridge::status_error(
328 "security_trust_copy_key",
329 status,
330 error,
331 )?);
332 }
333 Ok(bridge::Handle::from_raw(raw).map(PublicKey::from_handle))
334 }
335
336 pub fn certificate_count(&self) -> usize {
338 usize::try_from(unsafe {
339 bridge::security_trust_get_certificate_count(self.handle.as_ptr())
340 })
341 .unwrap_or_default()
342 }
343
344 pub fn certificate_chain(&self) -> Result<Vec<Certificate>> {
346 let mut status = 0;
347 let mut error = std::ptr::null_mut();
348 let raw = unsafe {
349 bridge::security_trust_copy_certificate_chain(
350 self.handle.as_ptr(),
351 &mut status,
352 &mut error,
353 )
354 };
355 let array_handle =
356 bridge::required_handle("security_trust_copy_certificate_chain", raw, status, error)?;
357 let count = usize::try_from(unsafe {
358 bridge::security_certificate_array_get_count(array_handle.as_ptr())
359 })
360 .unwrap_or_default();
361 let mut certificates = Vec::with_capacity(count);
362 for index in 0..count {
363 let mut status = 0;
364 let mut error = std::ptr::null_mut();
365 let raw = unsafe {
366 bridge::security_certificate_array_copy_item(
367 array_handle.as_ptr(),
368 bridge::len_to_isize(index)?,
369 &mut status,
370 &mut error,
371 )
372 };
373 let handle = bridge::required_handle(
374 "security_certificate_array_copy_item",
375 raw,
376 status,
377 error,
378 )?;
379 certificates.push(Certificate::from_handle(handle));
380 }
381 Ok(certificates)
382 }
383
384 pub fn exceptions(&self) -> Result<Option<Vec<u8>>> {
386 let mut status = 0;
387 let mut error = std::ptr::null_mut();
388 let raw = unsafe {
389 bridge::security_trust_copy_exceptions(self.handle.as_ptr(), &mut status, &mut error)
390 };
391 if status != 0 {
392 return Err(bridge::status_error(
393 "security_trust_copy_exceptions",
394 status,
395 error,
396 )?);
397 }
398 bridge::optional_data(raw)
399 }
400
401 pub fn set_exceptions(&mut self, exceptions: Option<&[u8]>) -> Result<bool> {
403 let mut error = std::ptr::null_mut();
404 let accepted = unsafe {
405 bridge::security_trust_set_exceptions(
406 self.handle.as_ptr(),
407 exceptions.map_or(std::ptr::null(), |value| value.as_ptr().cast()),
408 exceptions.map_or(Ok(0), |value| bridge::len_to_isize(value.len()))?,
409 &mut error,
410 )
411 };
412 if !error.is_null() {
413 return Err(bridge::status_error(
414 "security_trust_set_exceptions",
415 -1,
416 error,
417 )?);
418 }
419 Ok(accepted)
420 }
421
422 pub fn set_ocsp_responses(&mut self, responses: &[Vec<u8>]) -> Result<()> {
424 let responses = bridge::json_cstring(&responses)?;
425 let mut error = std::ptr::null_mut();
426 let status = unsafe {
427 bridge::security_trust_set_ocsp_response(
428 self.handle.as_ptr(),
429 responses.as_ptr(),
430 &mut error,
431 )
432 };
433 bridge::status_result("security_trust_set_ocsp_response", status, error)
434 }
435
436 pub fn set_signed_certificate_timestamps(&mut self, timestamps: &[Vec<u8>]) -> Result<()> {
438 let timestamps = bridge::json_cstring(×tamps)?;
439 let mut error = std::ptr::null_mut();
440 let status = unsafe {
441 bridge::security_trust_set_signed_certificate_timestamps(
442 self.handle.as_ptr(),
443 timestamps.as_ptr(),
444 &mut error,
445 )
446 };
447 bridge::status_result(
448 "security_trust_set_signed_certificate_timestamps",
449 status,
450 error,
451 )
452 }
453
454 pub fn set_options(&mut self, options: TrustOptions) -> Result<()> {
456 let mut error = std::ptr::null_mut();
457 let status = unsafe {
458 bridge::security_trust_set_options(self.handle.as_ptr(), options.bits(), &mut error)
459 };
460 bridge::status_result("security_trust_set_options", status, error)
461 }
462
463 pub fn system_anchor_certificates() -> Result<Value> {
465 let mut status = 0;
466 let mut error = std::ptr::null_mut();
467 let raw =
468 unsafe { bridge::security_trust_copy_anchor_certificates(&mut status, &mut error) };
469 bridge::required_json(
470 "security_trust_copy_anchor_certificates",
471 raw,
472 status,
473 error,
474 )
475 }
476}
477
478fn decode_trust_date(value: Value) -> Result<SystemTime> {
479 let unix =
480 value
481 .get("unix")
482 .and_then(Value::as_f64)
483 .ok_or_else(|| SecurityError::UnexpectedType {
484 operation: "security_trust_get_verify_time",
485 expected: "date JSON object",
486 })?;
487 let duration = Duration::from_secs_f64(unix.abs());
488 if unix >= 0.0 {
489 Ok(UNIX_EPOCH + duration)
490 } else {
491 UNIX_EPOCH.checked_sub(duration).ok_or_else(|| {
492 SecurityError::InvalidArgument(
493 "trust verify time preceded UNIX_EPOCH by too much".to_owned(),
494 )
495 })
496 }
497}
498
499fn system_time_to_unix(time: SystemTime) -> f64 {
500 match time.duration_since(UNIX_EPOCH) {
501 Ok(duration) => duration.as_secs_f64(),
502 Err(error) => -error.duration().as_secs_f64(),
503 }
504}