apple_security/
identity.rs

1//! Identity support.
2
3use core_foundation::base::TCFType;
4use core_foundation::base::ToVoid;
5use core_foundation::dictionary::CFMutableDictionary;
6use apple_security_sys::base::SecIdentityRef;
7use apple_security_sys::identity::{SecIdentityCopyCertificate, SecIdentityCopyPrivateKey, SecIdentityGetTypeID};
8use apple_security_sys::item::kSecValueRef;
9use apple_security_sys::keychain_item::SecItemDelete;
10use std::fmt;
11use std::ptr;
12
13use crate::base::Error;
14use crate::base::Result;
15use crate::certificate::SecCertificate;
16use crate::cvt;
17use crate::key::SecKey;
18
19declare_TCFType! {
20    /// A type representing an identity.
21    ///
22    /// Identities are a certificate paired with the corresponding private key.
23    SecIdentity, SecIdentityRef
24}
25impl_TCFType!(SecIdentity, SecIdentityRef, SecIdentityGetTypeID);
26
27unsafe impl Sync for SecIdentity {}
28unsafe impl Send for SecIdentity {}
29
30impl fmt::Debug for SecIdentity {
31    #[cold]
32    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
33        let mut builder = fmt.debug_struct("SecIdentity");
34        if let Ok(cert) = self.certificate() {
35            builder.field("certificate", &cert);
36        }
37        if let Ok(key) = self.private_key() {
38            builder.field("private_key", &key);
39        }
40        builder.finish()
41    }
42}
43
44impl SecIdentity {
45    /// Returns the certificate corresponding to this identity.
46    pub fn certificate(&self) -> Result<SecCertificate> {
47        unsafe {
48            let mut certificate = ptr::null_mut();
49            cvt(SecIdentityCopyCertificate(self.0, &mut certificate))?;
50            Ok(SecCertificate::wrap_under_create_rule(certificate))
51        }
52    }
53
54    /// Returns the private key corresponding to this identity.
55    pub fn private_key(&self) -> Result<SecKey> {
56        unsafe {
57            let mut key = ptr::null_mut();
58            cvt(SecIdentityCopyPrivateKey(self.0, &mut key))?;
59            Ok(SecKey::wrap_under_create_rule(key))
60        }
61    }
62
63    /// Translates to `SecItemDelete`, passing in the `SecIdentityRef`
64    pub fn delete(&self) -> Result<(), Error> {
65        let query = CFMutableDictionary::from_CFType_pairs(&[(
66            unsafe { kSecValueRef }.to_void(),
67            self.to_void(),
68        )]);
69
70        cvt(unsafe { SecItemDelete(query.as_concrete_TypeRef()) })
71    }
72}
73
74#[cfg(test)]
75mod test {
76    use super::SecIdentity;
77
78    #[test]
79    fn identity_has_send_bound() {
80        fn assert_send<T: Send>() {}
81        assert_send::<SecIdentity>();
82    }
83}