security/certificate/
mod.rs1use 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};
8
9#[derive(Debug)]
10pub struct PublicKey {
11 handle: Handle,
12}
13
14impl PublicKey {
15 pub(crate) fn from_handle(handle: Handle) -> Self {
16 Self { handle }
17 }
18
19 pub fn attributes(&self) -> Result<Value> {
20 let mut status = 0;
21 let mut error = std::ptr::null_mut();
22 let raw = unsafe {
23 bridge::security_key_copy_attributes(self.handle.as_ptr(), &mut status, &mut error)
24 };
25 bridge::required_json("security_key_copy_attributes", raw, status, error)
26 }
27}
28
29#[derive(Debug)]
30pub struct Certificate {
31 handle: Handle,
32}
33
34impl Certificate {
35 pub(crate) fn from_handle(handle: Handle) -> Self {
36 Self { handle }
37 }
38
39 pub(crate) fn handle(&self) -> &Handle {
40 &self.handle
41 }
42
43 pub fn from_der(der: &[u8]) -> Result<Self> {
44 let mut status = 0;
45 let mut error = std::ptr::null_mut();
46 let raw = unsafe {
47 bridge::security_certificate_from_der(
48 der.as_ptr().cast(),
49 bridge::len_to_isize(der.len())?,
50 &mut status,
51 &mut error,
52 )
53 };
54 bridge::required_handle("security_certificate_from_der", raw, status, error)
55 .map(Self::from_handle)
56 }
57
58 pub fn from_pem(pem: &[u8]) -> Result<Self> {
59 let pem = std::str::from_utf8(pem).map_err(|error| {
60 SecurityError::InvalidArgument(format!("PEM input was not valid UTF-8: {error}"))
61 })?;
62 let base64 = pem
63 .lines()
64 .filter(|line| !line.starts_with("-----"))
65 .collect::<String>();
66 let der = base64::engine::general_purpose::STANDARD
67 .decode(base64)
68 .map_err(|error| SecurityError::InvalidArgument(format!("invalid PEM body: {error}")))?;
69 Self::from_der(&der)
70 }
71
72 pub fn subject_summary(&self) -> Result<Option<String>> {
73 let raw = unsafe { bridge::security_certificate_copy_subject_summary(self.handle.as_ptr()) };
74 bridge::optional_string(raw)
75 }
76
77 pub fn common_name(&self) -> Result<Option<String>> {
78 let mut status = 0;
79 let mut error = std::ptr::null_mut();
80 let raw = unsafe {
81 bridge::security_certificate_copy_common_name(self.handle.as_ptr(), &mut status, &mut error)
82 };
83 if raw.is_null() && status == 0 {
84 return Ok(None);
85 }
86 bridge::required_string("security_certificate_copy_common_name", raw, status, error)
87 .map(Some)
88 }
89
90 pub fn email_addresses(&self) -> Result<Vec<String>> {
91 let mut status = 0;
92 let mut error = std::ptr::null_mut();
93 let raw = unsafe {
94 bridge::security_certificate_copy_email_addresses(
95 self.handle.as_ptr(),
96 &mut status,
97 &mut error,
98 )
99 };
100 bridge::required_json("security_certificate_copy_email_addresses", raw, status, error)
101 }
102
103 pub fn normalized_subject_sequence(&self) -> Result<Vec<u8>> {
104 let mut status = 0;
105 let mut error = std::ptr::null_mut();
106 let raw = unsafe {
107 bridge::security_certificate_copy_normalized_subject_sequence(
108 self.handle.as_ptr(),
109 &mut status,
110 &mut error,
111 )
112 };
113 bridge::required_data(
114 "security_certificate_copy_normalized_subject_sequence",
115 raw,
116 status,
117 error,
118 )
119 }
120
121 pub fn normalized_issuer_sequence(&self) -> Result<Vec<u8>> {
122 let mut status = 0;
123 let mut error = std::ptr::null_mut();
124 let raw = unsafe {
125 bridge::security_certificate_copy_normalized_issuer_sequence(
126 self.handle.as_ptr(),
127 &mut status,
128 &mut error,
129 )
130 };
131 bridge::required_data(
132 "security_certificate_copy_normalized_issuer_sequence",
133 raw,
134 status,
135 error,
136 )
137 }
138
139 pub fn serial_number(&self) -> Result<Vec<u8>> {
140 let mut status = 0;
141 let mut error = std::ptr::null_mut();
142 let raw = unsafe {
143 bridge::security_certificate_copy_serial_number(
144 self.handle.as_ptr(),
145 &mut status,
146 &mut error,
147 )
148 };
149 bridge::required_data("security_certificate_copy_serial_number", raw, status, error)
150 }
151
152 pub fn not_valid_before(&self) -> Result<Option<SystemTime>> {
153 let mut status = 0;
154 let mut error = std::ptr::null_mut();
155 let raw = unsafe {
156 bridge::security_certificate_copy_not_valid_before(
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 let value: Value = bridge::required_json(
166 "security_certificate_copy_not_valid_before",
167 raw,
168 status,
169 error,
170 )?;
171 decode_date(value).map(Some)
172 }
173
174 pub fn not_valid_after(&self) -> Result<Option<SystemTime>> {
175 let mut status = 0;
176 let mut error = std::ptr::null_mut();
177 let raw = unsafe {
178 bridge::security_certificate_copy_not_valid_after(
179 self.handle.as_ptr(),
180 &mut status,
181 &mut error,
182 )
183 };
184 if raw.is_null() && status == 0 {
185 return Ok(None);
186 }
187 let value: Value = bridge::required_json(
188 "security_certificate_copy_not_valid_after",
189 raw,
190 status,
191 error,
192 )?;
193 decode_date(value).map(Some)
194 }
195
196 pub fn der_data(&self) -> Result<Vec<u8>> {
197 let mut status = 0;
198 let mut error = std::ptr::null_mut();
199 let raw = unsafe {
200 bridge::security_certificate_copy_der(self.handle.as_ptr(), &mut status, &mut error)
201 };
202 bridge::required_data("security_certificate_copy_der", raw, status, error)
203 }
204
205 pub fn public_key(&self) -> Result<PublicKey> {
206 let mut status = 0;
207 let mut error = std::ptr::null_mut();
208 let raw = unsafe {
209 bridge::security_certificate_copy_public_key(self.handle.as_ptr(), &mut status, &mut error)
210 };
211 bridge::required_handle("security_certificate_copy_public_key", raw, status, error)
212 .map(PublicKey::from_handle)
213 }
214}
215
216fn decode_date(value: Value) -> Result<SystemTime> {
217 let unix = value
218 .get("unix")
219 .and_then(Value::as_f64)
220 .ok_or_else(|| SecurityError::UnexpectedType {
221 operation: "security_certificate_copy_not_valid_date",
222 expected: "date JSON object",
223 })?;
224 let duration = Duration::from_secs_f64(unix.abs());
225 if unix >= 0.0 {
226 Ok(UNIX_EPOCH + duration)
227 } else {
228 UNIX_EPOCH.checked_sub(duration).ok_or_else(|| {
229 SecurityError::InvalidArgument("certificate date preceded UNIX_EPOCH by too much".to_owned())
230 })
231 }
232}