1 // Copyright 2015-2021 Brian Smith. 2 // 3 // Permission to use, copy, modify, and/or distribute this software for any 4 // purpose with or without fee is hereby granted, provided that the above 5 // copyright notice and this permission notice appear in all copies. 6 // 7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 10 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 15 use crate::{ 16 cert, name, signed_data, verify_cert, DnsNameRef, Error, ErrorExt, SignatureAlgorithm, Time, 17 TlsClientTrustAnchors, TlsServerTrustAnchors, 18 }; 19 20 #[cfg(feature = "alloc")] 21 use alloc::vec::Vec; 22 23 /// An end-entity certificate. 24 /// 25 /// Server certificate processing in a TLS connection consists of several 26 /// steps. All of these steps are necessary: 27 /// 28 /// * `EndEntityCert.verify_is_valid_tls_server_cert`: Verify that the server's 29 /// certificate is currently valid *for use by a TLS server*. 30 /// * `EndEntityCert.verify_is_valid_for_dns_name`: Verify that the server's 31 /// certificate is valid for the host that is being connected to. 32 /// * `EndEntityCert.verify_signature`: Verify that the signature of server's 33 /// `ServerKeyExchange` message is valid for the server's certificate. 34 /// 35 /// Client certificate processing in a TLS connection consists of analogous 36 /// steps. All of these steps are necessary: 37 /// 38 /// * `EndEntityCert.verify_is_valid_tls_client_cert`: Verify that the client's 39 /// certificate is currently valid *for use by a TLS client*. 40 /// * `EndEntityCert.verify_is_valid_for_dns_name` or 41 /// `EndEntityCert.verify_is_valid_for_at_least_one_dns_name`: Verify that the 42 /// client's certificate is valid for the identity or identities used to 43 /// identify the client. (Currently client authentication only works when the 44 /// client is identified by one or more DNS hostnames.) 45 /// * `EndEntityCert.verify_signature`: Verify that the client's signature in 46 /// its `CertificateVerify` message is valid using the public key from the 47 /// client's certificate. 48 /// 49 /// Although it would be less error-prone to combine all these steps into a 50 /// single function call, some significant optimizations are possible if the 51 /// three steps are processed separately (in parallel). It does not matter much 52 /// which order the steps are done in, but **all of these steps must completed 53 /// before application data is sent and before received application data is 54 /// processed**. `EndEntityCert::from` is an inexpensive operation and is 55 /// deterministic, so if these tasks are done in multiple threads, it is 56 /// probably best to just call `EndEntityCert::from` multiple times (before each 57 /// operation) for the same DER-encoded ASN.1 certificate bytes. 58 pub struct EndEntityCert<'a> { 59 inner: cert::Cert<'a>, 60 } 61 62 impl<'a> core::convert::TryFrom<&'a [u8]> for EndEntityCert<'a> { 63 type Error = Error; 64 65 /// Parse the ASN.1 DER-encoded X.509 encoding of the certificate 66 /// `cert_der`. try_from(cert_der: &'a [u8]) -> Result<Self, Self::Error>67 fn try_from(cert_der: &'a [u8]) -> Result<Self, Self::Error> { 68 Ok(Self { 69 inner: cert::parse_cert( 70 untrusted::Input::from(cert_der), 71 cert::EndEntityOrCa::EndEntity, 72 )?, 73 }) 74 } 75 } 76 77 impl<'a> EndEntityCert<'a> { inner(&self) -> &cert::Cert78 pub(super) fn inner(&self) -> &cert::Cert { 79 &self.inner 80 } 81 82 /// Backward-SemVer-compatible wrapper around `verify_is_valid_tls_server_cert_ext`. 83 /// 84 /// Errors that aren't representable as an `Error` are mapped to `Error::UnknownIssuer`. verify_is_valid_tls_server_cert( &self, supported_sig_algs: &[&SignatureAlgorithm], trust_anchors: &TlsServerTrustAnchors, intermediate_certs: &[&[u8]], time: Time, ) -> Result<(), Error>85 pub fn verify_is_valid_tls_server_cert( 86 &self, 87 supported_sig_algs: &[&SignatureAlgorithm], 88 trust_anchors: &TlsServerTrustAnchors, 89 intermediate_certs: &[&[u8]], 90 time: Time, 91 ) -> Result<(), Error> { 92 self.verify_is_valid_tls_server_cert_ext( 93 supported_sig_algs, 94 trust_anchors, 95 intermediate_certs, 96 time, 97 ) 98 .map_err(ErrorExt::into_error_lossy) 99 } 100 101 /// Verifies that the end-entity certificate is valid for use by a TLS 102 /// server. 103 /// 104 /// `supported_sig_algs` is the list of signature algorithms that are 105 /// trusted for use in certificate signatures; the end-entity certificate's 106 /// public key is not validated against this list. `trust_anchors` is the 107 /// list of root CAs to trust. `intermediate_certs` is the sequence of 108 /// intermediate certificates that the server sent in the TLS handshake. 109 /// `time` is the time for which the validation is effective (usually the 110 /// current time). verify_is_valid_tls_server_cert_ext( &self, supported_sig_algs: &[&SignatureAlgorithm], &TlsServerTrustAnchors(trust_anchors): &TlsServerTrustAnchors, intermediate_certs: &[&[u8]], time: Time, ) -> Result<(), ErrorExt>111 pub fn verify_is_valid_tls_server_cert_ext( 112 &self, 113 supported_sig_algs: &[&SignatureAlgorithm], 114 &TlsServerTrustAnchors(trust_anchors): &TlsServerTrustAnchors, 115 intermediate_certs: &[&[u8]], 116 time: Time, 117 ) -> Result<(), ErrorExt> { 118 verify_cert::build_chain( 119 verify_cert::EKU_SERVER_AUTH, 120 supported_sig_algs, 121 trust_anchors, 122 intermediate_certs, 123 &self.inner, 124 time, 125 ) 126 } 127 128 /// Backward-SemVer-compatible wrapper around `verify_is_valid_tls_client_cert_ext`. 129 /// 130 /// Errors that aren't representable as an `Error` are mapped to `Error::UnknownIssuer`. verify_is_valid_tls_client_cert( &self, supported_sig_algs: &[&SignatureAlgorithm], trust_anchors: &TlsClientTrustAnchors, intermediate_certs: &[&[u8]], time: Time, ) -> Result<(), Error>131 pub fn verify_is_valid_tls_client_cert( 132 &self, 133 supported_sig_algs: &[&SignatureAlgorithm], 134 trust_anchors: &TlsClientTrustAnchors, 135 intermediate_certs: &[&[u8]], 136 time: Time, 137 ) -> Result<(), Error> { 138 self.verify_is_valid_tls_client_cert_ext( 139 supported_sig_algs, 140 trust_anchors, 141 intermediate_certs, 142 time, 143 ) 144 .map_err(ErrorExt::into_error_lossy) 145 } 146 147 /// Verifies that the end-entity certificate is valid for use by a TLS 148 /// client. 149 /// 150 /// If the certificate is not valid for any of the given names then this 151 /// fails with `Error::CertNotValidForName`. 152 /// 153 /// `supported_sig_algs` is the list of signature algorithms that are 154 /// trusted for use in certificate signatures; the end-entity certificate's 155 /// public key is not validated against this list. `trust_anchors` is the 156 /// list of root CAs to trust. `intermediate_certs` is the sequence of 157 /// intermediate certificates that the client sent in the TLS handshake. 158 /// `cert` is the purported end-entity certificate of the client. `time` is 159 /// the time for which the validation is effective (usually the current 160 /// time). verify_is_valid_tls_client_cert_ext( &self, supported_sig_algs: &[&SignatureAlgorithm], &TlsClientTrustAnchors(trust_anchors): &TlsClientTrustAnchors, intermediate_certs: &[&[u8]], time: Time, ) -> Result<(), ErrorExt>161 pub fn verify_is_valid_tls_client_cert_ext( 162 &self, 163 supported_sig_algs: &[&SignatureAlgorithm], 164 &TlsClientTrustAnchors(trust_anchors): &TlsClientTrustAnchors, 165 intermediate_certs: &[&[u8]], 166 time: Time, 167 ) -> Result<(), ErrorExt> { 168 verify_cert::build_chain( 169 verify_cert::EKU_CLIENT_AUTH, 170 supported_sig_algs, 171 trust_anchors, 172 intermediate_certs, 173 &self.inner, 174 time, 175 ) 176 } 177 178 /// Verifies that the certificate is valid for the given DNS host name. verify_is_valid_for_dns_name(&self, dns_name: DnsNameRef) -> Result<(), Error>179 pub fn verify_is_valid_for_dns_name(&self, dns_name: DnsNameRef) -> Result<(), Error> { 180 name::verify_cert_dns_name(self, dns_name) 181 } 182 183 /// Verifies that the certificate is valid for at least one of the given DNS 184 /// host names. 185 /// 186 /// If the certificate is not valid for any of the given names then this 187 /// fails with `Error::CertNotValidForName`. Otherwise the DNS names for 188 /// which the certificate is valid are returned. 189 /// 190 /// Requires the `alloc` default feature; i.e. this isn't available in 191 /// `#![no_std]` configurations. 192 #[cfg(feature = "alloc")] verify_is_valid_for_at_least_one_dns_name<'names, Names>( &self, dns_names: Names, ) -> Result<Vec<DnsNameRef<'names>>, Error> where Names: Iterator<Item = DnsNameRef<'names>>,193 pub fn verify_is_valid_for_at_least_one_dns_name<'names, Names>( 194 &self, 195 dns_names: Names, 196 ) -> Result<Vec<DnsNameRef<'names>>, Error> 197 where 198 Names: Iterator<Item = DnsNameRef<'names>>, 199 { 200 let result: Vec<DnsNameRef<'names>> = dns_names 201 .filter(|n| self.verify_is_valid_for_dns_name(*n).is_ok()) 202 .collect(); 203 if result.is_empty() { 204 return Err(Error::CertNotValidForName); 205 } 206 Ok(result) 207 } 208 209 /// Verifies the signature `signature` of message `msg` using the 210 /// certificate's public key. 211 /// 212 /// `signature_alg` is the algorithm to use to 213 /// verify the signature; the certificate's public key is verified to be 214 /// compatible with this algorithm. 215 /// 216 /// For TLS 1.2, `signature` corresponds to TLS's 217 /// `DigitallySigned.signature` and `signature_alg` corresponds to TLS's 218 /// `DigitallySigned.algorithm` of TLS type `SignatureAndHashAlgorithm`. In 219 /// TLS 1.2 a single `SignatureAndHashAlgorithm` may map to multiple 220 /// `SignatureAlgorithm`s. For example, a TLS 1.2 221 /// `SignatureAndHashAlgorithm` of (ECDSA, SHA-256) may map to any or all 222 /// of {`ECDSA_P256_SHA256`, `ECDSA_P384_SHA256`}, depending on how the TLS 223 /// implementation is configured. 224 /// 225 /// For current TLS 1.3 drafts, `signature_alg` corresponds to TLS's 226 /// `algorithm` fields of type `SignatureScheme`. There is (currently) a 227 /// one-to-one correspondence between TLS 1.3's `SignatureScheme` and 228 /// `SignatureAlgorithm`. verify_signature( &self, signature_alg: &SignatureAlgorithm, msg: &[u8], signature: &[u8], ) -> Result<(), Error>229 pub fn verify_signature( 230 &self, 231 signature_alg: &SignatureAlgorithm, 232 msg: &[u8], 233 signature: &[u8], 234 ) -> Result<(), Error> { 235 signed_data::verify_signature( 236 signature_alg, 237 self.inner.spki.value(), 238 untrusted::Input::from(msg), 239 untrusted::Input::from(signature), 240 ) 241 } 242 } 243