Skip to main content

security/
identity.rs

1use serde_json::Value;
2
3use crate::bridge;
4use crate::certificate::Certificate;
5use crate::error::Result;
6use crate::key::PrivateKey;
7
8#[derive(Debug)]
9pub struct Identity {
10    handle: bridge::Handle,
11}
12
13impl Identity {
14    pub(crate) fn from_handle(handle: bridge::Handle) -> Self {
15        Self { handle }
16    }
17
18    pub(crate) fn handle(&self) -> &bridge::Handle {
19        &self.handle
20    }
21
22    pub fn type_id() -> usize {
23        unsafe { bridge::security_identity_get_type_id() }
24    }
25
26    pub fn import_pkcs12_first(data: &[u8], password: &str) -> Result<Self> {
27        let password = bridge::cstring(password)?;
28        let mut status = 0;
29        let mut error = std::ptr::null_mut();
30        let raw = unsafe {
31            bridge::security_identity_import_pkcs12_first(
32                data.as_ptr().cast(),
33                bridge::len_to_isize(data.len())?,
34                password.as_ptr(),
35                &mut status,
36                &mut error,
37            )
38        };
39        bridge::required_handle("security_identity_import_pkcs12_first", raw, status, error)
40            .map(Self::from_handle)
41    }
42
43    pub fn from_certificate_and_private_key(
44        certificate: &Certificate,
45        private_key: &PrivateKey,
46    ) -> Result<Self> {
47        let mut status = 0;
48        let mut error = std::ptr::null_mut();
49        let raw = unsafe {
50            bridge::security_identity_create(
51                certificate.handle().as_ptr(),
52                private_key.handle().as_ptr(),
53                &mut status,
54                &mut error,
55            )
56        };
57        bridge::required_handle("security_identity_create", raw, status, error)
58            .map(Self::from_handle)
59    }
60
61    pub fn with_certificate(certificate: &Certificate) -> Result<Self> {
62        let mut status = 0;
63        let mut error = std::ptr::null_mut();
64        let raw = unsafe {
65            bridge::security_identity_create_with_certificate(
66                certificate.handle().as_ptr(),
67                &mut status,
68                &mut error,
69            )
70        };
71        bridge::required_handle(
72            "security_identity_create_with_certificate",
73            raw,
74            status,
75            error,
76        )
77        .map(Self::from_handle)
78    }
79
80    pub fn preferred(
81        name: &str,
82        key_usage: &[&str],
83        valid_issuers: &[Vec<u8>],
84    ) -> Result<Option<Self>> {
85        let name = bridge::cstring(name)?;
86        let key_usage = (!key_usage.is_empty())
87            .then(|| bridge::json_cstring(&key_usage))
88            .transpose()?;
89        let valid_issuers = (!valid_issuers.is_empty())
90            .then(|| bridge::json_cstring(&valid_issuers))
91            .transpose()?;
92        let mut status = 0;
93        let mut error = std::ptr::null_mut();
94        let raw = unsafe {
95            bridge::security_identity_copy_preferred(
96                name.as_ptr(),
97                key_usage
98                    .as_ref()
99                    .map_or(std::ptr::null(), |value| value.as_ptr()),
100                valid_issuers
101                    .as_ref()
102                    .map_or(std::ptr::null(), |value| value.as_ptr()),
103                &mut status,
104                &mut error,
105            )
106        };
107        if raw.is_null() && status == 0 {
108            Ok(None)
109        } else {
110            bridge::required_handle("security_identity_copy_preferred", raw, status, error)
111                .map(Self::from_handle)
112                .map(Some)
113        }
114    }
115
116    pub fn set_preferred(identity: Option<&Self>, name: &str, key_usage: &[&str]) -> Result<()> {
117        let name = bridge::cstring(name)?;
118        let key_usage = (!key_usage.is_empty())
119            .then(|| bridge::json_cstring(&key_usage))
120            .transpose()?;
121        let mut error = std::ptr::null_mut();
122        let status = unsafe {
123            bridge::security_identity_set_preferred(
124                identity.map_or(std::ptr::null_mut(), |value| value.handle.as_ptr()),
125                name.as_ptr(),
126                key_usage
127                    .as_ref()
128                    .map_or(std::ptr::null(), |value| value.as_ptr()),
129                &mut error,
130            )
131        };
132        bridge::status_result("security_identity_set_preferred", status, error)
133    }
134
135    pub fn copy_system_identity(domain: &str) -> Result<Self> {
136        let domain = bridge::cstring(domain)?;
137        let mut status = 0;
138        let mut error = std::ptr::null_mut();
139        let raw = unsafe {
140            bridge::security_identity_copy_system_identity(domain.as_ptr(), &mut status, &mut error)
141        };
142        bridge::required_handle("security_identity_copy_system_identity", raw, status, error)
143            .map(Self::from_handle)
144    }
145
146    pub fn set_system_identity(domain: &str, identity: Option<&Self>) -> Result<()> {
147        let domain = bridge::cstring(domain)?;
148        let mut error = std::ptr::null_mut();
149        let status = unsafe {
150            bridge::security_identity_set_system_identity(
151                domain.as_ptr(),
152                identity.map_or(std::ptr::null_mut(), |value| value.handle.as_ptr()),
153                &mut error,
154            )
155        };
156        bridge::status_result("security_identity_set_system_identity", status, error)
157    }
158
159    pub fn actual_domain(&self) -> Result<Option<String>> {
160        let raw = unsafe { bridge::security_identity_copy_actual_domain(self.handle.as_ptr()) };
161        bridge::optional_string(raw)
162    }
163
164    pub fn label(&self) -> Result<Option<String>> {
165        let raw = unsafe { bridge::security_identity_copy_label(self.handle.as_ptr()) };
166        bridge::optional_string(raw)
167    }
168
169    pub fn chain_count(&self) -> usize {
170        usize::try_from(unsafe { bridge::security_identity_get_chain_count(self.handle.as_ptr()) })
171            .unwrap_or_default()
172    }
173
174    pub fn certificate(&self) -> Result<Certificate> {
175        let mut status = 0;
176        let mut error = std::ptr::null_mut();
177        let raw = unsafe {
178            bridge::security_identity_copy_certificate(
179                self.handle.as_ptr(),
180                &mut status,
181                &mut error,
182            )
183        };
184        bridge::required_handle("security_identity_copy_certificate", raw, status, error)
185            .map(Certificate::from_handle)
186    }
187
188    pub fn private_key_attributes(&self) -> Result<Value> {
189        let mut status = 0;
190        let mut error = std::ptr::null_mut();
191        let raw = unsafe {
192            bridge::security_identity_copy_private_key_attributes(
193                self.handle.as_ptr(),
194                &mut status,
195                &mut error,
196            )
197        };
198        bridge::required_json(
199            "security_identity_copy_private_key_attributes",
200            raw,
201            status,
202            error,
203        )
204    }
205}