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    /// Wraps the corresponding `SecTrustRef` operation.
80    pub fn type_id() -> usize {
81        unsafe { bridge::security_trust_get_type_id() }
82    }
83
84    /// Wraps the corresponding `SecTrustRef` operation.
85    pub fn new(certificate: &Certificate, policies: &[Policy]) -> Result<Self> {
86        Self::from_certificates(std::slice::from_ref(certificate), policies)
87    }
88
89    /// Wraps the corresponding `SecTrustRef` operation.
90    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    /// Wraps the corresponding `SecTrustRef` operation.
115    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    /// Wraps the corresponding `SecTrustRef` operation.
131    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    /// Wraps the corresponding `SecTrustRef` operation.
141    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    /// Wraps the corresponding `SecTrustRef` operation.
160    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    /// Wraps the corresponding `SecTrustRef` operation.
179    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    /// Wraps the corresponding `SecTrustRef` operation.
192    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    /// Wraps the corresponding `SecTrustRef` operation.
205    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    /// Wraps the corresponding `SecTrustRef` operation.
226    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    /// Wraps the corresponding `SecTrustRef` operation.
239    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    /// Wraps the corresponding `SecTrustRef` operation.
257    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    /// Wraps the corresponding `SecTrustRef` operation.
270    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    /// Wraps the corresponding `SecTrustRef` operation.
293    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    /// Wraps the corresponding `SecTrustRef` operation.
310    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    /// Wraps the corresponding `SecTrustRef` operation.
320    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    /// Wraps the corresponding `SecTrustRef` operation.
337    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    /// Wraps the corresponding `SecTrustRef` operation.
345    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    /// Wraps the corresponding `SecTrustRef` operation.
385    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    /// Wraps the corresponding `SecTrustRef` operation.
402    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    /// Wraps the corresponding `SecTrustRef` operation.
423    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    /// Wraps the corresponding `SecTrustRef` operation.
437    pub fn set_signed_certificate_timestamps(&mut self, timestamps: &[Vec<u8>]) -> Result<()> {
438        let timestamps = bridge::json_cstring(&timestamps)?;
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    /// Wraps the corresponding `SecTrustRef` operation.
455    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    /// Wraps the corresponding `SecTrustRef` operation.
464    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}