1use crate::x509::{AlgorithmIdentifier, BasicConstraints, Certificate, KeyUsage, oiddb::rfc5912};
2use crate::{
3 ecdsa_p256::{EcdsaP256DerSignature, EcdsaP256PublicKey, EcdsaP256VerifyingKey},
4 ecdsa_p384::{EcdsaP384DerSignature, EcdsaP384PublicKey, EcdsaP384VerifyingKey},
5 rsa::{RS256PublicKey, RS256Signature, RS256VerifyingKey, RS384VerifyingKey},
6 s256::{Sha256, Sha256Output},
7 traits::{Digest, Verifier, hazmat::PrehashVerifier},
8};
9use der::Encode;
10use der::referenced::OwnedToRef;
11use std::time::{Duration, SystemTime};
12use tracing::{debug, error, trace, warn};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum X509VerificationError {
16 InvalidSystemTime,
17 BasicConstraintsNotPresent,
18 LeafMustNotBeCA,
19 KeyUsageNotValid,
20 ExtensionFailure,
21 NotBefore,
22 NotAfter,
23 NoMatchingIssuer,
24 InvalidIssuer,
25 ExcessivePathLength,
26 CaNotMarkedAsSuch,
27 PathLengthExceeded,
28 SignatureAlgorithmMismatch,
29 SignatureAlgorithmNotImplemented,
30 DerSignatureInvalid,
31 VerifyingKeyFromSpki,
32 SignatureVerificationFailed,
33 CertificateSerialisation,
34 KeyUsageNotPresent,
35 SubjectPublicKeyInformationInvalid,
36}
37
38pub struct X509Store {
39 store: Vec<Certificate>,
40 leaf_basic_constraints_required: bool,
41}
42
43impl X509Store {
44 pub fn new(ca_roots: &[Certificate]) -> Self {
45 Self {
46 store: ca_roots.iter().map(|c| (*c).clone()).collect(),
47 leaf_basic_constraints_required: true,
48 }
49 }
50
51 pub fn leaf_basic_constraints_required(&mut self, enable: bool) {
52 self.leaf_basic_constraints_required = enable;
53 }
54
55 pub fn verify(
56 &self,
57 leaf: &Certificate,
58 intermediates: &[Certificate],
59 current_time: SystemTime,
60 ) -> Result<&Certificate, X509VerificationError> {
61 let current_time_unix = current_time
76 .duration_since(SystemTime::UNIX_EPOCH)
77 .map_err(|_| X509VerificationError::InvalidSystemTime)?;
78
79 let mut certificate_to_validate = leaf;
80 self.validate_leaf(certificate_to_validate, current_time_unix)?;
81
82 let mut path_length = 0;
84
85 for intermediate in intermediates {
86 self.validate_pair(
90 certificate_to_validate,
91 intermediate,
92 current_time_unix,
93 path_length,
94 )?;
95
96 certificate_to_validate = intermediate;
98
99 path_length = path_length
101 .checked_add(1)
102 .ok_or(X509VerificationError::ExcessivePathLength)?;
103 }
104
105 let authority_cert = self.locate_authority_certificate(certificate_to_validate)?;
113
114 self.validate_pair(
115 certificate_to_validate,
116 authority_cert,
117 current_time_unix,
118 path_length,
119 )?;
120
121 Ok(authority_cert)
126 }
127
128 fn validate_leaf(
129 &self,
130 certificate_to_validate: &Certificate,
131 current_time: Duration,
132 ) -> Result<(), X509VerificationError> {
133 let maybe_basic_constraints = certificate_to_validate
137 .tbs_certificate()
138 .get_extension::<BasicConstraints>()
139 .map_err(|_err| X509VerificationError::ExtensionFailure)?;
140 if let Some((_critical, basic_constraints)) = maybe_basic_constraints {
144 if basic_constraints.ca {
145 return Err(X509VerificationError::LeafMustNotBeCA);
146 }
147 } else if self.leaf_basic_constraints_required {
148 return Err(X509VerificationError::BasicConstraintsNotPresent);
149 };
150
151 let maybe_keyusage = certificate_to_validate
152 .tbs_certificate()
153 .get_extension::<KeyUsage>()
154 .map_err(|_err| X509VerificationError::ExtensionFailure)?;
155
156 if let Some((_critical, key_usage)) = maybe_keyusage {
157 if !key_usage.digital_signature() {
160 return Err(X509VerificationError::KeyUsageNotValid);
161 }
162 }
163
164 let not_before = certificate_to_validate
166 .tbs_certificate()
167 .validity()
168 .not_before
169 .to_unix_duration();
170
171 if not_before > current_time {
172 trace!(?not_before, ?current_time);
173 return Err(X509VerificationError::NotBefore);
174 }
175
176 let not_after = certificate_to_validate
177 .tbs_certificate()
178 .validity()
179 .not_after
180 .to_unix_duration();
181
182 if current_time > not_after {
183 debug!(?current_time, ?not_after);
184 return Err(X509VerificationError::NotAfter);
185 }
186
187 Ok(())
188 }
189
190 fn validate_pair(
191 &self,
192 certificate_to_validate: &Certificate,
193 authority: &Certificate,
194 current_time: Duration,
195 path_length: u8,
196 ) -> Result<(), X509VerificationError> {
197 if authority.tbs_certificate().subject()
198 != certificate_to_validate.tbs_certificate().issuer()
199 {
200 return Err(X509VerificationError::InvalidIssuer);
201 }
202
203 let (_critical, basic_constraints) = authority
209 .tbs_certificate()
210 .get_extension::<BasicConstraints>()
211 .map_err(|_err| X509VerificationError::ExtensionFailure)?
212 .ok_or(X509VerificationError::BasicConstraintsNotPresent)?;
214
215 if !basic_constraints.ca {
216 return Err(X509VerificationError::CaNotMarkedAsSuch);
217 }
218
219 if let Some(ca_pathlen) = basic_constraints.path_len_constraint {
220 if path_length > ca_pathlen {
223 return Err(X509VerificationError::PathLengthExceeded);
224 }
225 }
226
227 let (_critical, key_usage) = authority
228 .tbs_certificate()
229 .get_extension::<KeyUsage>()
230 .map_err(|_err| X509VerificationError::ExtensionFailure)?
231 .ok_or(X509VerificationError::KeyUsageNotPresent)?;
232
233 if !key_usage.key_cert_sign() {
234 return Err(X509VerificationError::KeyUsageNotValid);
235 }
236
237 let not_before = authority
239 .tbs_certificate()
240 .validity()
241 .not_before
242 .to_unix_duration();
243
244 if not_before > current_time {
245 return Err(X509VerificationError::NotBefore);
246 }
247
248 let not_after = authority
249 .tbs_certificate()
250 .validity()
251 .not_after
252 .to_unix_duration();
253
254 if current_time > not_after {
255 return Err(X509VerificationError::NotAfter);
256 }
257
258 if certificate_to_validate.signature_algorithm() != authority.tbs_certificate().signature()
263 {
264 warn!(validate_signature = ?certificate_to_validate.signature_algorithm(), authority_signature = ?authority.tbs_certificate().signature());
265 }
267
268 let cert_to_validate_data = certificate_to_validate
269 .tbs_certificate()
270 .to_der()
271 .map_err(|_err| X509VerificationError::CertificateSerialisation)?;
272
273 let cert_to_validate_signature = certificate_to_validate
274 .signature()
275 .as_bytes()
276 .ok_or(X509VerificationError::DerSignatureInvalid)?;
277
278 verify_der_signature(
279 &cert_to_validate_data,
280 cert_to_validate_signature,
281 certificate_to_validate.signature_algorithm(),
282 authority,
283 )?;
284
285 Ok(())
286 }
287
288 fn locate_authority_certificate(
289 &self,
290 certificate_to_validate: &Certificate,
291 ) -> Result<&Certificate, X509VerificationError> {
292 self.store
293 .iter()
294 .find(|ca_cert| {
295 ca_cert.tbs_certificate().subject()
296 == certificate_to_validate.tbs_certificate().issuer()
297 })
298 .ok_or(X509VerificationError::NoMatchingIssuer)
299 }
300}
301
302fn verify_der_signature(
306 data: &[u8],
307 signature: &[u8],
308 signature_algorithm: &AlgorithmIdentifier<der::Any>,
309 certificate: &Certificate,
310) -> Result<(), X509VerificationError> {
311 let subject_public_key_info = certificate
312 .tbs_certificate()
313 .subject_public_key_info()
314 .owned_to_ref();
315
316 let (spki_alg_oid, spki_alg_params) = subject_public_key_info
317 .algorithm
318 .oids()
319 .map_err(|_| X509VerificationError::SubjectPublicKeyInformationInvalid)?;
320
321 trace!(?signature_algorithm.oid, ?spki_alg_oid, ?spki_alg_params);
322
323 match (signature_algorithm.oid, spki_alg_oid, spki_alg_params) {
324 (rfc5912::ECDSA_WITH_SHA_256, rfc5912::ID_EC_PUBLIC_KEY, Some(rfc5912::SECP_256_R_1)) => {
325 let signature = EcdsaP256DerSignature::try_from(signature).map_err(|err| {
326 error!(?err);
327 X509VerificationError::DerSignatureInvalid
328 })?;
329
330 let verifier = EcdsaP256PublicKey::try_from(subject_public_key_info)
331 .map(EcdsaP256VerifyingKey::from)
332 .map_err(|_err| X509VerificationError::VerifyingKeyFromSpki)?;
333
334 verifier
335 .verify(data, &signature)
336 .map_err(|_err| X509VerificationError::SignatureVerificationFailed)?;
337 }
338 (rfc5912::ECDSA_WITH_SHA_256, rfc5912::ID_EC_PUBLIC_KEY, Some(rfc5912::SECP_384_R_1)) => {
339 let signature = EcdsaP384DerSignature::try_from(signature)
340 .map_err(|_err| X509VerificationError::DerSignatureInvalid)?;
341
342 let verifier = EcdsaP384PublicKey::try_from(subject_public_key_info)
343 .map(EcdsaP384VerifyingKey::from)
344 .map_err(|_err| X509VerificationError::VerifyingKeyFromSpki)?;
345
346 let mut hasher = Sha256::new();
348 hasher.update(data);
349 let out: Sha256Output = hasher.finalize();
350
351 verifier
352 .verify_prehash(out.as_slice(), &signature)
353 .map_err(|_err| X509VerificationError::SignatureVerificationFailed)?;
354 }
355 (rfc5912::ECDSA_WITH_SHA_384, rfc5912::ID_EC_PUBLIC_KEY, Some(rfc5912::SECP_384_R_1)) => {
356 let signature = EcdsaP384DerSignature::try_from(signature)
357 .map_err(|_err| X509VerificationError::DerSignatureInvalid)?;
358
359 let verifier = EcdsaP384PublicKey::try_from(subject_public_key_info)
360 .map(EcdsaP384VerifyingKey::from)
361 .map_err(|_err| X509VerificationError::VerifyingKeyFromSpki)?;
362
363 verifier
364 .verify(data, &signature)
365 .map_err(|_err| X509VerificationError::SignatureVerificationFailed)?;
366 }
367 (rfc5912::SHA_256_WITH_RSA_ENCRYPTION, rfc5912::RSA_ENCRYPTION, None) => {
368 let signature = RS256Signature::try_from(signature)
369 .map_err(|_err| X509VerificationError::DerSignatureInvalid)?;
370
371 let verifier = RS256PublicKey::try_from(subject_public_key_info)
372 .map(RS256VerifyingKey::new)
373 .map_err(|_err| X509VerificationError::VerifyingKeyFromSpki)?;
374
375 verifier
376 .verify(data, &signature)
377 .map_err(|_err| X509VerificationError::SignatureVerificationFailed)?;
378 }
379 (rfc5912::SHA_384_WITH_RSA_ENCRYPTION, rfc5912::RSA_ENCRYPTION, None) => {
380 let signature = RS256Signature::try_from(signature)
381 .map_err(|_err| X509VerificationError::DerSignatureInvalid)?;
382
383 let verifier = RS256PublicKey::try_from(subject_public_key_info)
384 .map(RS384VerifyingKey::new)
385 .map_err(|_err| X509VerificationError::VerifyingKeyFromSpki)?;
386
387 verifier
388 .verify(data, &signature)
389 .map_err(|_err| X509VerificationError::SignatureVerificationFailed)?;
390 }
391 (signature_algorithm_oid, spki_alg_oid, spki_alg_params) => {
392 error!(?signature_algorithm_oid, ?spki_alg_oid, ?spki_alg_params);
393 return Err(X509VerificationError::SignatureAlgorithmNotImplemented);
394 }
395 }
396
397 Ok(())
398}