1use std::fmt;
2use std::hash::{Hash, Hasher};
3
4use crate::Error;
5
6#[derive(Clone, Hash)]
13pub struct Certificate<'a> {
14 der: CertDer<'a>,
15}
16
17#[derive(Clone)]
18enum CertDer<'a> {
19 Borrowed(&'a [u8]),
20 Owned(Vec<u8>),
21 Rustls(rustls_pki_types::CertificateDer<'static>),
22}
23
24impl Hash for CertDer<'_> {
25 fn hash<H: Hasher>(&self, state: &mut H) {
26 core::mem::discriminant(self).hash(state);
27 self.as_ref().hash(state)
28 }
29}
30
31impl<'a> AsRef<[u8]> for CertDer<'a> {
32 fn as_ref(&self) -> &[u8] {
33 match self {
34 CertDer::Borrowed(v) => v,
35 CertDer::Owned(v) => v,
36 CertDer::Rustls(v) => v,
37 }
38 }
39}
40
41impl<'a> Certificate<'a> {
42 pub fn from_der(der: &'a [u8]) -> Self {
47 let der = CertDer::Borrowed(der);
48 Certificate { der }
49 }
50
51 pub fn from_pem(pem: &'a [u8]) -> Result<Certificate<'static>, Error> {
58 let item = parse_pem(pem)
59 .find(|p| matches!(p, Err(_) | Ok(PemItem::Certificate(_))))
60 .ok_or(Error::Tls("No pem encoded cert found"))??;
62
63 let PemItem::Certificate(cert) = item else {
64 unreachable!("matches! above for Certificate");
65 };
66
67 Ok(cert)
68 }
69
70 pub fn der(&self) -> &[u8] {
72 self.der.as_ref()
73 }
74
75 pub fn to_owned(&self) -> Certificate<'static> {
77 Certificate {
78 der: CertDer::Owned(self.der.as_ref().to_vec()),
79 }
80 }
81}
82
83#[derive(Hash)]
90pub struct PrivateKey<'a> {
91 kind: KeyKind,
92 der: PrivateKeyDer<'a>,
93}
94
95enum PrivateKeyDer<'a> {
96 Borrowed(&'a [u8]),
97 Owned(Vec<u8>),
98 Rustls(rustls_pki_types::PrivateKeyDer<'static>),
99}
100
101impl Hash for PrivateKeyDer<'_> {
102 fn hash<H: Hasher>(&self, state: &mut H) {
103 core::mem::discriminant(self).hash(state);
104 match self {
105 PrivateKeyDer::Borrowed(v) => v.hash(state),
106 PrivateKeyDer::Owned(v) => v.hash(state),
107 PrivateKeyDer::Rustls(v) => v.secret_der().as_ref().hash(state),
108 }
109 }
110}
111
112impl<'a> AsRef<[u8]> for PrivateKey<'a> {
113 fn as_ref(&self) -> &[u8] {
114 match &self.der {
115 PrivateKeyDer::Borrowed(v) => v,
116 PrivateKeyDer::Owned(v) => v,
117 PrivateKeyDer::Rustls(v) => v.secret_der(),
118 }
119 }
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
127#[non_exhaustive]
128pub enum KeyKind {
129 Pkcs1,
131 Pkcs8,
135 Sec1,
137}
138
139impl<'a> PrivateKey<'a> {
140 pub fn from_der(kind: KeyKind, der: &'a [u8]) -> Self {
145 let der = PrivateKeyDer::Borrowed(der);
146 PrivateKey { kind, der }
147 }
148
149 pub fn from_pem(pem: &'a [u8]) -> Result<PrivateKey<'static>, Error> {
156 let item = parse_pem(pem)
157 .find(|p| matches!(p, Err(_) | Ok(PemItem::PrivateKey(_))))
158 .ok_or(Error::Tls("No pem encoded private key found"))??;
160
161 let PemItem::PrivateKey(key) = item else {
162 unreachable!("matches! above for PrivateKey");
163 };
164
165 Ok(key)
166 }
167
168 pub fn kind(&self) -> KeyKind {
170 self.kind
171 }
172
173 pub fn der(&self) -> &[u8] {
175 self.as_ref()
176 }
177
178 pub fn to_owned(&self) -> PrivateKey<'static> {
180 PrivateKey {
181 kind: self.kind,
182 der: match &self.der {
183 PrivateKeyDer::Borrowed(v) => PrivateKeyDer::Owned(v.to_vec()),
184 PrivateKeyDer::Owned(v) => PrivateKeyDer::Owned(v.to_vec()),
185 PrivateKeyDer::Rustls(v) => PrivateKeyDer::Rustls(v.clone_key()),
186 },
187 }
188 }
189}
190
191pub fn parse_pem(pem: &[u8]) -> impl Iterator<Item = Result<PemItem<'static>, Error>> + '_ {
196 PemIter(pem)
197}
198
199#[non_exhaustive]
201pub enum PemItem<'a> {
202 Certificate(Certificate<'a>),
204
205 PrivateKey(PrivateKey<'a>),
207}
208
209struct PemIter<'a>(&'a [u8]);
210
211impl<'a> Iterator for PemIter<'a> {
212 type Item = Result<PemItem<'static>, Error>;
213
214 fn next(&mut self) -> Option<Self::Item> {
215 loop {
216 match rustls_pemfile::read_one_from_slice(self.0) {
217 Ok(Some((cert, rest))) => {
218 self.0 = rest;
220
221 match cert {
222 rustls_pemfile::Item::X509Certificate(der) => {
223 return Some(Ok(Certificate {
224 der: CertDer::Rustls(der),
225 }
226 .into()));
227 }
228 rustls_pemfile::Item::Pkcs1Key(der) => {
229 return Some(Ok(PrivateKey {
230 kind: KeyKind::Pkcs1,
231 der: PrivateKeyDer::Rustls(der.into()),
232 }
233 .into()));
234 }
235 rustls_pemfile::Item::Pkcs8Key(der) => {
236 return Some(Ok(PrivateKey {
237 kind: KeyKind::Pkcs8,
238 der: PrivateKeyDer::Rustls(der.into()),
239 }
240 .into()));
241 }
242 rustls_pemfile::Item::Sec1Key(der) => {
243 return Some(Ok(PrivateKey {
244 kind: KeyKind::Sec1,
245 der: PrivateKeyDer::Rustls(der.into()),
246 }
247 .into()));
248 }
249
250 _ => continue,
252 }
253 }
254
255 Ok(None) => return None,
257
258 Err(e) => {
259 return Some(Err(Error::Pem(e)));
260 }
261 }
262 }
263 }
264}
265
266impl<'a> From<Certificate<'a>> for PemItem<'a> {
267 fn from(value: Certificate<'a>) -> Self {
268 PemItem::Certificate(value)
269 }
270}
271
272impl<'a> From<PrivateKey<'a>> for PemItem<'a> {
273 fn from(value: PrivateKey<'a>) -> Self {
274 PemItem::PrivateKey(value)
275 }
276}
277
278impl<'a> fmt::Debug for Certificate<'a> {
279 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280 f.debug_struct("Certificate").finish()
281 }
282}
283
284impl<'a> fmt::Debug for PrivateKey<'a> {
285 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
286 f.debug_struct("PrivateKey")
287 .field("kind", &self.kind)
288 .finish()
289 }
290}