Skip to main content

security/trust/
mod.rs

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    /// Mirrors `SecTrustOptionFlags`.
14    pub struct TrustOptions: u32 {
15        /// Mirrors a `SecTrustOptionFlags` bit.
16        const ALLOW_EXPIRED = 0x0000_0001;
17        /// Mirrors a `SecTrustOptionFlags` bit.
18        const LEAF_IS_CA = 0x0000_0002;
19        /// Mirrors a `SecTrustOptionFlags` bit.
20        const FETCH_ISSUER_FROM_NET = 0x0000_0004;
21        /// Mirrors a `SecTrustOptionFlags` bit.
22        const ALLOW_EXPIRED_ROOT = 0x0000_0008;
23        /// Mirrors a `SecTrustOptionFlags` bit.
24        const REQUIRE_REVOCATION_PER_CERT = 0x0000_0010;
25        /// Mirrors a `SecTrustOptionFlags` bit.
26        const USE_TRUST_SETTINGS = 0x0000_0020;
27        /// Mirrors a `SecTrustOptionFlags` bit.
28        const IMPLICIT_ANCHORS = 0x0000_0040;
29    }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33#[repr(u32)]
34/// Mirrors `SecTrustResultType`.
35pub enum TrustResultType {
36    /// Mirrors a `SecTrustResultType` constant.
37    Invalid = 0,
38    /// Mirrors a `SecTrustResultType` constant.
39    Proceed = 1,
40    /// Mirrors a `SecTrustResultType` constant.
41    Confirm = 2,
42    /// Mirrors a `SecTrustResultType` constant.
43    Deny = 3,
44    /// Mirrors a `SecTrustResultType` constant.
45    Unspecified = 4,
46    /// Mirrors a `SecTrustResultType` constant.
47    RecoverableTrustFailure = 5,
48    /// Mirrors a `SecTrustResultType` constant.
49    FatalTrustFailure = 6,
50    /// Mirrors a `SecTrustResultType` constant.
51    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)]
73/// Wraps `SecTrustRef`.
74pub 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    /// Wraps the corresponding `SecTrustRef` operation.
85    pub fn type_id() -> usize {
86        unsafe { bridge::security_trust_get_type_id() }
87    }
88
89    /// Wraps the corresponding `SecTrustRef` operation.
90    pub fn new(certificate: &Certificate, policies: &[Policy]) -> Result<Self> {
91        Self::from_certificates(std::slice::from_ref(certificate), policies)
92    }
93
94    /// Wraps the corresponding `SecTrustRef` operation.
95    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    /// Wraps the corresponding `SecTrustRef` operation.
120    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    /// Wraps the corresponding `SecTrustRef` operation.
136    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    /// Wraps the corresponding `SecTrustRef` operation.
146    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    /// Wraps the corresponding `SecTrustRef` operation.
165    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    /// Wraps the corresponding `SecTrustRef` operation.
184    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    /// Wraps the corresponding `SecTrustRef` operation.
197    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    /// Wraps the corresponding `SecTrustRef` operation.
210    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    /// Wraps the corresponding `SecTrustRef` operation.
231    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    /// Wraps the corresponding `SecTrustRef` operation.
244    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    /// Wraps the corresponding `SecTrustRef` operation.
262    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    /// Wraps the corresponding `SecTrustRef` operation.
275    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    /// Wraps the corresponding `SecTrustRef` operation.
298    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    /// Wraps the corresponding `SecTrustRef` operation.
315    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    /// Wraps the corresponding `SecTrustRef` operation.
325    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    /// Wraps the corresponding `SecTrustRef` operation.
342    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    /// Wraps the corresponding `SecTrustRef` operation.
350    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    /// Wraps the corresponding `SecTrustRef` operation.
390    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    /// Wraps the corresponding `SecTrustRef` operation.
407    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    /// Wraps the corresponding `SecTrustRef` operation.
428    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    /// Wraps the corresponding `SecTrustRef` operation.
442    pub fn set_signed_certificate_timestamps(&mut self, timestamps: &[Vec<u8>]) -> Result<()> {
443        let timestamps = bridge::json_cstring(&timestamps)?;
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    /// Wraps the corresponding `SecTrustRef` operation.
460    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    /// Wraps the corresponding `SecTrustRef` operation.
469    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}