From eb358ea1cf1f66ad332bb85e79e2254e367c53b3 Mon Sep 17 00:00:00 2001 From: Xiaoyu Lu Date: Fri, 24 Sep 2021 08:56:00 +0800 Subject: [PATCH] Add support for verifying certificate chain with EKU --- src/end_entity.rs | 35 +++++++++++++++++++++++++++++++++++ src/verify_cert.rs | 16 ++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/end_entity.rs b/src/end_entity.rs index bd545df5..f8d2c3cd 100644 --- a/src/end_entity.rs +++ b/src/end_entity.rs @@ -181,4 +181,39 @@ impl<'a> EndEntityCert<'a> { untrusted::Input::from(signature), ) } + + /// Verifies that the end-entity certificate is valid for use by cert chain + /// + /// `required_eku` is the Certificate Extended Key Usage Oid in bytes. + /// If the certificate is not valid for `required_eku` then this + /// fails with `Error::CertNotValidForName`. + /// `supported_sig_algs` is the list of signature algorithms that are + /// trusted for use in certificate signatures; the end-entity certificate's + /// public key is not validated against this list. `trust_anchors` is the + /// list of root CAs to trust. `intermediate_certs` is the sequence of + /// intermediate certificates that the client sent in the TLS handshake. + /// `cert` is the purported end-entity certificate of the client. `time` is + /// the time for which the validation is effective (usually the current + /// time). + /// + pub fn verify_is_valid_cert_with_eku( + &self, + required_eku: &'static [u8], + supported_sig_algs: &[&SignatureAlgorithm], + trust_anchors: &[crate::TrustAnchor], + intermediate_certs: &[&[u8]], + time: Time, + ) -> Result<(), Error> { + let eku = verify_cert::KeyPurposeId::new(required_eku); + + crate::verify_cert::build_chain( + eku, + supported_sig_algs, + trust_anchors, + intermediate_certs, + &self.inner, + time, + 0, + ) + } } diff --git a/src/verify_cert.rs b/src/verify_cert.rs index 237473c6..65616f87 100644 --- a/src/verify_cert.rs +++ b/src/verify_cert.rs @@ -257,6 +257,22 @@ pub struct KeyPurposeId { oid_value: untrusted::Input<'static>, } +impl KeyPurposeId { + /// Construct a new `KeyPurposeId` + /// + /// `oid` is the OBJECT IDENTIFIER in bytes. + /// + /// For example: + /// static EKU_SERVER_AUTH_BYTES: &'static [u8] = &[(40 * 1) + 3, 6, 1, 5, 5, 7, 3, 1]; + /// let oid = KeyPurposeId::new(EKU_SERVER_AUTH_BYTES); + /// + pub fn new(oid: &'static [u8]) -> Self { + KeyPurposeId { + oid_value: untrusted::Input::from(oid), + } + } +} + // id-pkix OBJECT IDENTIFIER ::= { 1 3 6 1 5 5 7 } // id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }