webpki/
end_entity.rs

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#[cfg(feature = "alloc")]
16use crate::subject_name::GeneralDnsNameRef;
17use crate::{
18    cert, signed_data, subject_name, verify_cert, CertRevocationList, Error, KeyUsage,
19    SignatureAlgorithm, SubjectNameRef, Time, TrustAnchor,
20};
21#[allow(deprecated)]
22use crate::{TlsClientTrustAnchors, TlsServerTrustAnchors};
23
24/// An end-entity certificate.
25///
26/// Server certificate processing in a TLS connection consists of several
27/// steps. All of these steps are necessary:
28///
29/// * `EndEntityCert.verify_is_valid_tls_server_cert`: Verify that the server's
30///   certificate is currently valid *for use by a TLS server*.
31/// * `EndEntityCert.verify_is_valid_for_subject_name`: Verify that the server's
32///   certificate is valid for the host or IP address that is being connected to.
33///
34/// * `EndEntityCert.verify_signature`: Verify that the signature of server's
35///   `ServerKeyExchange` message is valid for the server's certificate.
36///
37/// Client certificate processing in a TLS connection consists of analogous
38/// steps. All of these steps are necessary:
39///
40/// * `EndEntityCert.verify_is_valid_tls_client_cert`: Verify that the client's
41///   certificate is currently valid *for use by a TLS client*.
42/// * `EndEntityCert.verify_signature`: Verify that the client's signature in
43///   its `CertificateVerify` message is valid using the public key from the
44///   client's certificate.
45///
46/// Although it would be less error-prone to combine all these steps into a
47/// single function call, some significant optimizations are possible if the
48/// three steps are processed separately (in parallel). It does not matter much
49/// which order the steps are done in, but **all of these steps must completed
50/// before application data is sent and before received application data is
51/// processed**. `EndEntityCert::from` is an inexpensive operation and is
52/// deterministic, so if these tasks are done in multiple threads, it is
53/// probably best to just call `EndEntityCert::from` multiple times (before each
54/// operation) for the same DER-encoded ASN.1 certificate bytes.
55pub struct EndEntityCert<'a> {
56    inner: cert::Cert<'a>,
57}
58
59impl<'a> TryFrom<&'a [u8]> for EndEntityCert<'a> {
60    type Error = Error;
61
62    /// Parse the ASN.1 DER-encoded X.509 encoding of the certificate
63    /// `cert_der`.
64    fn try_from(cert_der: &'a [u8]) -> Result<Self, Self::Error> {
65        Ok(Self {
66            inner: cert::Cert::from_der(
67                untrusted::Input::from(cert_der),
68                cert::EndEntityOrCa::EndEntity,
69            )?,
70        })
71    }
72}
73
74impl<'a> EndEntityCert<'a> {
75    pub(super) fn inner(&self) -> &cert::Cert {
76        &self.inner
77    }
78
79    fn verify_is_valid_cert(
80        &self,
81        supported_sig_algs: &[&SignatureAlgorithm],
82        trust_anchors: &[TrustAnchor],
83        intermediate_certs: &[&[u8]],
84        time: Time,
85        eku: KeyUsage,
86        crls: &[&dyn CertRevocationList],
87    ) -> Result<(), Error> {
88        verify_cert::build_chain(
89            &verify_cert::ChainOptions {
90                eku,
91                supported_sig_algs,
92                trust_anchors,
93                intermediate_certs,
94                crls,
95            },
96            &self.inner,
97            time,
98        )
99    }
100
101    /// Verifies that the end-entity certificate is valid for use against the
102    /// specified Extended Key Usage (EKU).
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.
107    /// * `trust_anchors` is the list of root CAs to trust
108    /// * `intermediate_certs` is the sequence of intermediate certificates that
109    ///   the server sent in the TLS handshake.
110    /// * `time` is the time for which the validation is effective (usually the
111    ///   current time).
112    /// * `usage` is the intended usage of the certificate, indicating what kind
113    ///   of usage we're verifying the certificate for.
114    /// * `crls` is the list of certificate revocation lists to check
115    ///   the certificate against.
116    pub fn verify_for_usage(
117        &self,
118        supported_sig_algs: &[&SignatureAlgorithm],
119        trust_anchors: &[TrustAnchor],
120        intermediate_certs: &[&[u8]],
121        time: Time,
122        usage: KeyUsage,
123        crls: &[&dyn CertRevocationList],
124    ) -> Result<(), Error> {
125        self.verify_is_valid_cert(
126            supported_sig_algs,
127            trust_anchors,
128            intermediate_certs,
129            time,
130            usage,
131            crls,
132        )
133    }
134
135    /// Verifies that the end-entity certificate is valid for use by a TLS
136    /// server.
137    ///
138    /// `supported_sig_algs` is the list of signature algorithms that are
139    /// trusted for use in certificate signatures; the end-entity certificate's
140    /// public key is not validated against this list. `trust_anchors` is the
141    /// list of root CAs to trust. `intermediate_certs` is the sequence of
142    /// intermediate certificates that the server sent in the TLS handshake.
143    /// `time` is the time for which the validation is effective (usually the
144    /// current time).
145    #[allow(deprecated)]
146    #[deprecated(
147        since = "0.101.2",
148        note = "The per-usage trust anchor representations and verification functions are deprecated in \
149        favor of the general-purpose `TrustAnchor` type and `EndEntity::verify_for_usage` function. \
150        The new `verify_for_usage` function expresses trust anchor and end entity purpose with the \
151        key usage argument."
152    )]
153    pub fn verify_is_valid_tls_server_cert(
154        &self,
155        supported_sig_algs: &[&SignatureAlgorithm],
156        &TlsServerTrustAnchors(trust_anchors): &TlsServerTrustAnchors,
157        intermediate_certs: &[&[u8]],
158        time: Time,
159    ) -> Result<(), Error> {
160        self.verify_is_valid_cert(
161            supported_sig_algs,
162            trust_anchors,
163            intermediate_certs,
164            time,
165            KeyUsage::server_auth(),
166            &[],
167        )
168    }
169
170    /// Verifies that the end-entity certificate is valid for use by a TLS
171    /// client.
172    ///
173    /// `supported_sig_algs` is the list of signature algorithms that are
174    /// trusted for use in certificate signatures; the end-entity certificate's
175    /// public key is not validated against this list. `trust_anchors` is the
176    /// list of root CAs to trust. `intermediate_certs` is the sequence of
177    /// intermediate certificates that the client sent in the TLS handshake.
178    /// `cert` is the purported end-entity certificate of the client. `time` is
179    /// the time for which the validation is effective (usually the current
180    /// time).
181    #[allow(deprecated)]
182    #[deprecated(
183        since = "0.101.2",
184        note = "The per-usage trust anchor representations and verification functions are deprecated in \
185        favor of the general-purpose `TrustAnchor` type and `EndEntity::verify_for_usage` function. \
186        The new `verify_for_usage` function expresses trust anchor and end entity purpose with the \
187        key usage argument."
188    )]
189    pub fn verify_is_valid_tls_client_cert(
190        &self,
191        supported_sig_algs: &[&SignatureAlgorithm],
192        &TlsClientTrustAnchors(trust_anchors): &TlsClientTrustAnchors,
193        intermediate_certs: &[&[u8]],
194        time: Time,
195        crls: &[&dyn CertRevocationList],
196    ) -> Result<(), Error> {
197        self.verify_is_valid_cert(
198            supported_sig_algs,
199            trust_anchors,
200            intermediate_certs,
201            time,
202            KeyUsage::client_auth(),
203            crls,
204        )
205    }
206
207    /// Verifies that the certificate is valid for the given Subject Name.
208    pub fn verify_is_valid_for_subject_name(
209        &self,
210        subject_name: SubjectNameRef,
211    ) -> Result<(), Error> {
212        subject_name::verify_cert_subject_name(self, subject_name)
213    }
214
215    /// Verifies the signature `signature` of message `msg` using the
216    /// certificate's public key.
217    ///
218    /// `signature_alg` is the algorithm to use to
219    /// verify the signature; the certificate's public key is verified to be
220    /// compatible with this algorithm.
221    ///
222    /// For TLS 1.2, `signature` corresponds to TLS's
223    /// `DigitallySigned.signature` and `signature_alg` corresponds to TLS's
224    /// `DigitallySigned.algorithm` of TLS type `SignatureAndHashAlgorithm`. In
225    /// TLS 1.2 a single `SignatureAndHashAlgorithm` may map to multiple
226    /// `SignatureAlgorithm`s. For example, a TLS 1.2
227    /// `SignatureAndHashAlgorithm` of (ECDSA, SHA-256) may map to any or all
228    /// of {`ECDSA_P256_SHA256`, `ECDSA_P384_SHA256`}, depending on how the TLS
229    /// implementation is configured.
230    ///
231    /// For current TLS 1.3 drafts, `signature_alg` corresponds to TLS's
232    /// `algorithm` fields of type `SignatureScheme`. There is (currently) a
233    /// one-to-one correspondence between TLS 1.3's `SignatureScheme` and
234    /// `SignatureAlgorithm`.
235    pub fn verify_signature(
236        &self,
237        signature_alg: &SignatureAlgorithm,
238        msg: &[u8],
239        signature: &[u8],
240    ) -> Result<(), Error> {
241        signed_data::verify_signature(
242            signature_alg,
243            self.inner.spki.value(),
244            untrusted::Input::from(msg),
245            untrusted::Input::from(signature),
246        )
247    }
248
249    /// Returns a list of the DNS names provided in the subject alternative names extension
250    ///
251    /// This function must not be used to implement custom DNS name verification.
252    /// Verification functions are already provided as `verify_is_valid_for_dns_name`
253    /// and `verify_is_valid_for_at_least_one_dns_name`.
254    #[cfg(feature = "alloc")]
255    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
256    pub fn dns_names(&'a self) -> Result<impl Iterator<Item = GeneralDnsNameRef<'a>>, Error> {
257        subject_name::list_cert_dns_names(self)
258    }
259}
260
261#[cfg(feature = "alloc")]
262#[cfg(test)]
263mod tests {
264    use super::*;
265    use crate::test_utils;
266
267    // This test reproduces https://github.com/rustls/webpki/issues/167 --- an
268    // end-entity cert where the common name is a `PrintableString` rather than
269    // a `UTF8String` cannot iterate over its subject alternative names.
270    #[test]
271    fn printable_string_common_name() {
272        const DNS_NAME: &str = "test.example.com";
273
274        let issuer = test_utils::make_issuer("Test", None);
275
276        let ee_cert_der = {
277            let mut params = rcgen::CertificateParams::new(vec![DNS_NAME.to_string()]);
278            // construct a certificate that uses `PrintableString` as the
279            // common name value, rather than `UTF8String`.
280            params.distinguished_name.push(
281                rcgen::DnType::CommonName,
282                rcgen::DnValue::PrintableString("example.com".to_string()),
283            );
284            params.is_ca = rcgen::IsCa::ExplicitNoCa;
285            params.alg = test_utils::RCGEN_SIGNATURE_ALG;
286            let cert = rcgen::Certificate::from_params(params)
287                .expect("failed to make ee cert (this is a test bug)");
288            cert.serialize_der_with_signer(&issuer)
289                .expect("failed to serialize signed ee cert (this is a test bug)")
290        };
291
292        expect_dns_name(&ee_cert_der, DNS_NAME);
293    }
294
295    // This test reproduces https://github.com/rustls/webpki/issues/167 --- an
296    // end-entity cert where the common name is an empty SEQUENCE.
297    #[test]
298    fn empty_sequence_common_name() {
299        // handcrafted cert DER produced using `ascii2der`, since `rcgen` is
300        // unwilling to generate this particular weird cert.
301        let ee_cert_der = include_bytes!("../tests/misc/empty_sequence_common_name.der").as_slice();
302        expect_dns_name(ee_cert_der, "example.com");
303    }
304
305    fn expect_dns_name(der: &[u8], name: &str) {
306        let cert =
307            EndEntityCert::try_from(der).expect("should parse end entity certificate correctly");
308
309        let mut names = cert
310            .dns_names()
311            .expect("should get all DNS names correctly for end entity cert");
312        assert_eq!(names.next().map(<&str>::from), Some(name));
313        assert_eq!(names.next().map(<&str>::from), None);
314    }
315}