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