apple_security_framework/os/macos/
identity.rs1use std::ptr;
3
4use core_foundation::{array::CFArray, base::TCFType};
5use security_framework_sys::identity::SecIdentityCreateWithCertificate;
6
7use crate::{
8 base::Result, certificate::SecCertificate, cvt, identity::SecIdentity,
9 os::macos::keychain::SecKeychain,
10};
11
12pub trait SecIdentityExt {
14 fn with_certificate(
21 keychains: &[SecKeychain],
22 certificate: &SecCertificate,
23 ) -> Result<SecIdentity>;
24}
25
26impl SecIdentityExt for SecIdentity {
27 fn with_certificate(keychains: &[SecKeychain], certificate: &SecCertificate) -> Result<Self> {
28 let keychains = CFArray::from_CFTypes(keychains);
29 unsafe {
30 let mut identity = ptr::null_mut();
31 cvt(SecIdentityCreateWithCertificate(
32 if keychains.len() > 0 {
33 keychains.as_CFTypeRef()
34 } else {
35 ptr::null()
36 },
37 certificate.as_concrete_TypeRef(),
38 &mut identity,
39 ))?;
40 Ok(Self::wrap_under_create_rule(identity))
41 }
42 }
43}
44
45#[cfg(test)]
46mod test {
47 use tempfile::tempdir;
48
49 use super::*;
50 use crate::{
51 identity::SecIdentity,
52 os::macos::{
53 certificate::SecCertificateExt, import_export::ImportOptions, keychain::CreateOptions,
54 test::identity,
55 },
56 test,
57 };
58
59 #[test]
60 fn certificate() {
61 let dir = p!(tempdir());
62 let identity = identity(dir.path());
63 let certificate = p!(identity.certificate());
64 assert_eq!("foobar.com", p!(certificate.common_name()));
65 }
66
67 #[test]
68 fn private_key() {
69 let dir = p!(tempdir());
70 let identity = identity(dir.path());
71 p!(identity.private_key());
72 }
73
74 #[test]
75 fn with_certificate() {
76 let dir = p!(tempdir());
77
78 let keychain = p!(CreateOptions::new()
79 .password("foobar")
80 .create(dir.path().join("test.keychain")));
81
82 let key = include_bytes!("../../../test/server.key");
83 p!(ImportOptions::new()
84 .filename("server.key")
85 .keychain(&keychain)
86 .import(key));
87
88 let cert = test::certificate();
89 p!(SecIdentity::with_certificate(&[keychain], &cert));
90 }
91}