security_framework/
identity.rs

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