1use std::time::{Duration, SystemTime, UNIX_EPOCH};
2
3use base64::Engine;
4use serde_json::Value;
5
6use crate::bridge::{self, Handle};
7use crate::error::{Result, SecurityError};
8use crate::key::{ExternalFormat, ExternalItemType, SignatureAlgorithm};
9
10#[derive(Debug)]
11pub struct PublicKey {
12 handle: Handle,
13}
14
15impl PublicKey {
16 pub(crate) fn from_handle(handle: Handle) -> Self {
17 Self { handle }
18 }
19
20 pub fn attributes(&self) -> Result<Value> {
21 let mut status = 0;
22 let mut error = std::ptr::null_mut();
23 let raw = unsafe {
24 bridge::security_key_copy_attributes(self.handle.as_ptr(), &mut status, &mut error)
25 };
26 bridge::required_json("security_key_copy_attributes", raw, status, error)
27 }
28
29 pub fn verify_signature(
30 &self,
31 algorithm: SignatureAlgorithm,
32 signed_data: &[u8],
33 signature: &[u8],
34 ) -> Result<bool> {
35 let mut status = 0;
36 let mut error = std::ptr::null_mut();
37 let valid = unsafe {
38 bridge::security_public_key_verify_signature(
39 self.handle.as_ptr(),
40 algorithm as u32,
41 signed_data.as_ptr().cast(),
42 bridge::len_to_isize(signed_data.len())?,
43 signature.as_ptr().cast(),
44 bridge::len_to_isize(signature.len())?,
45 &mut status,
46 &mut error,
47 )
48 };
49 if status != 0 {
50 return Err(bridge::status_error(
51 "security_public_key_verify_signature",
52 status,
53 error,
54 )?);
55 }
56 Ok(valid)
57 }
58}
59
60#[derive(Debug)]
61pub struct Certificate {
62 handle: Handle,
63}
64
65impl Certificate {
66 pub(crate) fn from_handle(handle: Handle) -> Self {
67 Self { handle }
68 }
69
70 pub(crate) fn handle(&self) -> &Handle {
71 &self.handle
72 }
73
74 pub fn from_der(der: &[u8]) -> Result<Self> {
75 let mut status = 0;
76 let mut error = std::ptr::null_mut();
77 let raw = unsafe {
78 bridge::security_certificate_from_der(
79 der.as_ptr().cast(),
80 bridge::len_to_isize(der.len())?,
81 &mut status,
82 &mut error,
83 )
84 };
85 bridge::required_handle("security_certificate_from_der", raw, status, error)
86 .map(Self::from_handle)
87 }
88
89 pub fn import_item(
90 data: &[u8],
91 file_name_or_extension: Option<&str>,
92 format: ExternalFormat,
93 item_type: ExternalItemType,
94 ) -> Result<Self> {
95 let file_name_or_extension = file_name_or_extension.map(bridge::cstring).transpose()?;
96 let mut status = 0;
97 let mut error = std::ptr::null_mut();
98 let raw = unsafe {
99 bridge::security_certificate_import_item(
100 data.as_ptr().cast(),
101 bridge::len_to_isize(data.len())?,
102 file_name_or_extension
103 .as_ref()
104 .map_or(std::ptr::null(), |value| value.as_ptr()),
105 format as u32,
106 item_type as u32,
107 &mut status,
108 &mut error,
109 )
110 };
111 bridge::required_handle("security_certificate_import_item", raw, status, error)
112 .map(Self::from_handle)
113 }
114
115 pub fn export_item(&self, format: ExternalFormat, pem_armour: bool) -> Result<Vec<u8>> {
116 let mut status = 0;
117 let mut error = std::ptr::null_mut();
118 let raw = unsafe {
119 bridge::security_certificate_export_item(
120 self.handle.as_ptr(),
121 format as u32,
122 pem_armour,
123 &mut status,
124 &mut error,
125 )
126 };
127 bridge::required_data("security_certificate_export_item", raw, status, error)
128 }
129
130 pub fn from_pem(pem: &[u8]) -> Result<Self> {
131 let pem = std::str::from_utf8(pem).map_err(|error| {
132 SecurityError::InvalidArgument(format!("PEM input was not valid UTF-8: {error}"))
133 })?;
134 let base64 = pem
135 .lines()
136 .filter(|line| !line.starts_with("-----"))
137 .collect::<String>();
138 let der = base64::engine::general_purpose::STANDARD
139 .decode(base64)
140 .map_err(|error| {
141 SecurityError::InvalidArgument(format!("invalid PEM body: {error}"))
142 })?;
143 Self::from_der(&der)
144 }
145
146 pub fn subject_summary(&self) -> Result<Option<String>> {
147 let raw =
148 unsafe { bridge::security_certificate_copy_subject_summary(self.handle.as_ptr()) };
149 bridge::optional_string(raw)
150 }
151
152 pub fn common_name(&self) -> Result<Option<String>> {
153 let mut status = 0;
154 let mut error = std::ptr::null_mut();
155 let raw = unsafe {
156 bridge::security_certificate_copy_common_name(
157 self.handle.as_ptr(),
158 &mut status,
159 &mut error,
160 )
161 };
162 if raw.is_null() && status == 0 {
163 return Ok(None);
164 }
165 bridge::required_string("security_certificate_copy_common_name", raw, status, error)
166 .map(Some)
167 }
168
169 pub fn email_addresses(&self) -> Result<Vec<String>> {
170 let mut status = 0;
171 let mut error = std::ptr::null_mut();
172 let raw = unsafe {
173 bridge::security_certificate_copy_email_addresses(
174 self.handle.as_ptr(),
175 &mut status,
176 &mut error,
177 )
178 };
179 bridge::required_json(
180 "security_certificate_copy_email_addresses",
181 raw,
182 status,
183 error,
184 )
185 }
186
187 pub fn normalized_subject_sequence(&self) -> Result<Vec<u8>> {
188 let mut status = 0;
189 let mut error = std::ptr::null_mut();
190 let raw = unsafe {
191 bridge::security_certificate_copy_normalized_subject_sequence(
192 self.handle.as_ptr(),
193 &mut status,
194 &mut error,
195 )
196 };
197 bridge::required_data(
198 "security_certificate_copy_normalized_subject_sequence",
199 raw,
200 status,
201 error,
202 )
203 }
204
205 pub fn normalized_issuer_sequence(&self) -> Result<Vec<u8>> {
206 let mut status = 0;
207 let mut error = std::ptr::null_mut();
208 let raw = unsafe {
209 bridge::security_certificate_copy_normalized_issuer_sequence(
210 self.handle.as_ptr(),
211 &mut status,
212 &mut error,
213 )
214 };
215 bridge::required_data(
216 "security_certificate_copy_normalized_issuer_sequence",
217 raw,
218 status,
219 error,
220 )
221 }
222
223 pub fn serial_number(&self) -> Result<Vec<u8>> {
224 let mut status = 0;
225 let mut error = std::ptr::null_mut();
226 let raw = unsafe {
227 bridge::security_certificate_copy_serial_number(
228 self.handle.as_ptr(),
229 &mut status,
230 &mut error,
231 )
232 };
233 bridge::required_data(
234 "security_certificate_copy_serial_number",
235 raw,
236 status,
237 error,
238 )
239 }
240
241 pub fn not_valid_before(&self) -> Result<Option<SystemTime>> {
242 let mut status = 0;
243 let mut error = std::ptr::null_mut();
244 let raw = unsafe {
245 bridge::security_certificate_copy_not_valid_before(
246 self.handle.as_ptr(),
247 &mut status,
248 &mut error,
249 )
250 };
251 if raw.is_null() && status == 0 {
252 return Ok(None);
253 }
254 let value: Value = bridge::required_json(
255 "security_certificate_copy_not_valid_before",
256 raw,
257 status,
258 error,
259 )?;
260 decode_date(value).map(Some)
261 }
262
263 pub fn not_valid_after(&self) -> Result<Option<SystemTime>> {
264 let mut status = 0;
265 let mut error = std::ptr::null_mut();
266 let raw = unsafe {
267 bridge::security_certificate_copy_not_valid_after(
268 self.handle.as_ptr(),
269 &mut status,
270 &mut error,
271 )
272 };
273 if raw.is_null() && status == 0 {
274 return Ok(None);
275 }
276 let value: Value = bridge::required_json(
277 "security_certificate_copy_not_valid_after",
278 raw,
279 status,
280 error,
281 )?;
282 decode_date(value).map(Some)
283 }
284
285 pub fn der_data(&self) -> Result<Vec<u8>> {
286 let mut status = 0;
287 let mut error = std::ptr::null_mut();
288 let raw = unsafe {
289 bridge::security_certificate_copy_der(self.handle.as_ptr(), &mut status, &mut error)
290 };
291 bridge::required_data("security_certificate_copy_der", raw, status, error)
292 }
293
294 pub fn public_key(&self) -> Result<PublicKey> {
295 let mut status = 0;
296 let mut error = std::ptr::null_mut();
297 let raw = unsafe {
298 bridge::security_certificate_copy_public_key(
299 self.handle.as_ptr(),
300 &mut status,
301 &mut error,
302 )
303 };
304 bridge::required_handle("security_certificate_copy_public_key", raw, status, error)
305 .map(PublicKey::from_handle)
306 }
307}
308
309fn decode_date(value: Value) -> Result<SystemTime> {
310 let unix =
311 value
312 .get("unix")
313 .and_then(Value::as_f64)
314 .ok_or_else(|| SecurityError::UnexpectedType {
315 operation: "security_certificate_copy_not_valid_date",
316 expected: "date JSON object",
317 })?;
318 let duration = Duration::from_secs_f64(unix.abs());
319 if unix >= 0.0 {
320 Ok(UNIX_EPOCH + duration)
321 } else {
322 UNIX_EPOCH.checked_sub(duration).ok_or_else(|| {
323 SecurityError::InvalidArgument(
324 "certificate date preceded UNIX_EPOCH by too much".to_owned(),
325 )
326 })
327 }
328}