apple_security_framework/
identity.rs

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