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    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(&timestamps)?;
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}