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
15use core::ops::Deref;
16
17use pki_types::{
18 CertificateDer, ServerName, SignatureVerificationAlgorithm, TrustAnchor, UnixTime,
19};
20
21use crate::crl::RevocationOptions;
22use crate::error::Error;
23use crate::subject_name::{verify_dns_names, verify_ip_address_names, NameIterator};
24use crate::verify_cert::{self, KeyUsage, VerifiedPath};
25use crate::{cert, signed_data};
26
27/// An end-entity certificate.
28///
29/// Server certificate processing in a TLS connection consists of several
30/// steps. All of these steps are necessary:
31///
32/// * `EndEntityCert.verify_is_valid_tls_server_cert`: Verify that the server's
33/// certificate is currently valid *for use by a TLS server*.
34/// * `EndEntityCert.verify_is_valid_for_subject_name`: Verify that the server's
35/// certificate is valid for the host or IP address that is being connected to.
36///
37/// * `EndEntityCert.verify_signature`: Verify that the signature of server's
38/// `ServerKeyExchange` message is valid for the server's certificate.
39///
40/// Client certificate processing in a TLS connection consists of analogous
41/// steps. All of these steps are necessary:
42///
43/// * `EndEntityCert.verify_is_valid_tls_client_cert`: Verify that the client's
44/// certificate is currently valid *for use by a TLS client*.
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.
58pub struct EndEntityCert<'a> {
59 inner: cert::Cert<'a>,
60}
61
62impl<'a> TryFrom<&'a CertificateDer<'a>> for EndEntityCert<'a> {
63 type Error = Error;
64
65 /// Parse the ASN.1 DER-encoded X.509 encoding of the certificate
66 /// `cert_der`.
67 fn try_from(cert: &'a CertificateDer<'a>) -> Result<Self, Self::Error> {
68 Ok(Self {
69 inner: cert::Cert::from_der(cert_der:untrusted::Input::from(bytes:cert.as_ref()))?,
70 })
71 }
72}
73
74impl<'a> EndEntityCert<'a> {
75 /// Verifies that the end-entity certificate is valid for use against the
76 /// specified Extended Key Usage (EKU).
77 ///
78 /// * `supported_sig_algs` is the list of signature algorithms that are
79 /// trusted for use in certificate signatures; the end-entity certificate's
80 /// public key is not validated against this list.
81 /// * `trust_anchors` is the list of root CAs to trust in the built path.
82 /// * `intermediate_certs` is the sequence of intermediate certificates that
83 /// a peer sent for the purpose of path building.
84 /// * `time` is the time for which the validation is effective (usually the
85 /// current time).
86 /// * `usage` is the intended usage of the certificate, indicating what kind
87 /// of usage we're verifying the certificate for.
88 /// * `crls` is the list of certificate revocation lists to check
89 /// the certificate against.
90 /// * `verify_path` is an optional verification function for path candidates.
91 ///
92 /// If successful, yields a `VerifiedPath` type that can be used to inspect a verified chain
93 /// of certificates that leads from the `end_entity` to one of the `self.trust_anchors`.
94 ///
95 /// `verify_path` will only be called for potentially verified paths, that is, paths that
96 /// have been verified up to the trust anchor. As such, `verify_path()` cannot be used to
97 /// verify a path that doesn't satisfy the constraints listed above; it can only be used to
98 /// reject a path that does satisfy the aforementioned constraints. If `verify_path` returns
99 /// an error, path building will continue in order to try other options.
100 #[allow(clippy::too_many_arguments)]
101 pub fn verify_for_usage<'p>(
102 &'p self,
103 supported_sig_algs: &[&dyn SignatureVerificationAlgorithm],
104 trust_anchors: &'p [TrustAnchor],
105 intermediate_certs: &'p [CertificateDer<'p>],
106 time: UnixTime,
107 usage: KeyUsage,
108 revocation: Option<RevocationOptions<'_>>,
109 verify_path: Option<&dyn Fn(&VerifiedPath<'_>) -> Result<(), Error>>,
110 ) -> Result<VerifiedPath<'p>, Error> {
111 verify_cert::ChainOptions {
112 eku: usage,
113 supported_sig_algs,
114 trust_anchors,
115 intermediate_certs,
116 revocation,
117 }
118 .build_chain(self, time, verify_path)
119 }
120
121 /// Verifies that the certificate is valid for the given Subject Name.
122 pub fn verify_is_valid_for_subject_name(
123 &self,
124 server_name: &ServerName<'_>,
125 ) -> Result<(), Error> {
126 match server_name {
127 ServerName::DnsName(dns_name) => verify_dns_names(
128 dns_name,
129 NameIterator::new(Some(self.inner.subject), self.inner.subject_alt_name),
130 ),
131 // IP addresses are not compared against the subject field;
132 // only against Subject Alternative Names.
133 ServerName::IpAddress(ip_address) => verify_ip_address_names(
134 ip_address,
135 NameIterator::new(None, self.inner.subject_alt_name),
136 ),
137 _ => Err(Error::UnsupportedNameType),
138 }
139 }
140
141 /// Verifies the signature `signature` of message `msg` using the
142 /// certificate's public key.
143 ///
144 /// `signature_alg` is the algorithm to use to
145 /// verify the signature; the certificate's public key is verified to be
146 /// compatible with this algorithm.
147 ///
148 /// For TLS 1.2, `signature` corresponds to TLS's
149 /// `DigitallySigned.signature` and `signature_alg` corresponds to TLS's
150 /// `DigitallySigned.algorithm` of TLS type `SignatureAndHashAlgorithm`. In
151 /// TLS 1.2 a single `SignatureAndHashAlgorithm` may map to multiple
152 /// `SignatureVerificationAlgorithm`s. For example, a TLS 1.2
153 /// `SignatureAndHashAlgorithm` of (ECDSA, SHA-256) may map to any or all
154 /// of {`ECDSA_P256_SHA256`, `ECDSA_P384_SHA256`}, depending on how the TLS
155 /// implementation is configured.
156 ///
157 /// For current TLS 1.3 drafts, `signature_alg` corresponds to TLS's
158 /// `algorithm` fields of type `SignatureScheme`. There is (currently) a
159 /// one-to-one correspondence between TLS 1.3's `SignatureScheme` and
160 /// `SignatureVerificationAlgorithm`.
161 pub fn verify_signature(
162 &self,
163 signature_alg: &dyn SignatureVerificationAlgorithm,
164 msg: &[u8],
165 signature: &[u8],
166 ) -> Result<(), Error> {
167 signed_data::verify_signature(
168 signature_alg,
169 self.inner.spki,
170 untrusted::Input::from(msg),
171 untrusted::Input::from(signature),
172 )
173 }
174}
175
176impl<'a> Deref for EndEntityCert<'a> {
177 type Target = cert::Cert<'a>;
178
179 fn deref(&self) -> &Self::Target {
180 &self.inner
181 }
182}
183
184#[cfg(feature = "alloc")]
185#[cfg(test)]
186mod tests {
187 use super::*;
188 use crate::test_utils;
189
190 // This test reproduces https://github.com/rustls/webpki/issues/167 --- an
191 // end-entity cert where the common name is a `PrintableString` rather than
192 // a `UTF8String` cannot iterate over its subject alternative names.
193 #[test]
194 fn printable_string_common_name() {
195 const DNS_NAME: &str = "test.example.com";
196
197 let issuer = test_utils::make_issuer("Test");
198
199 let ee_cert_der = {
200 let mut params = test_utils::end_entity_params(vec![DNS_NAME.to_string()]);
201 // construct a certificate that uses `PrintableString` as the
202 // common name value, rather than `UTF8String`.
203 params.distinguished_name.push(
204 rcgen::DnType::CommonName,
205 rcgen::DnValue::PrintableString("example.com".to_string()),
206 );
207 let cert = rcgen::Certificate::from_params(params)
208 .expect("failed to make ee cert (this is a test bug)");
209 let bytes = cert
210 .serialize_der_with_signer(&issuer)
211 .expect("failed to serialize signed ee cert (this is a test bug)");
212 CertificateDer::from(bytes)
213 };
214
215 expect_dns_name(&ee_cert_der, DNS_NAME);
216 }
217
218 // This test reproduces https://github.com/rustls/webpki/issues/167 --- an
219 // end-entity cert where the common name is an empty SEQUENCE.
220 #[test]
221 fn empty_sequence_common_name() {
222 let ee_cert_der = {
223 // handcrafted cert DER produced using `ascii2der`, since `rcgen` is
224 // unwilling to generate this particular weird cert.
225 let bytes = include_bytes!("../tests/misc/empty_sequence_common_name.der");
226 CertificateDer::from(&bytes[..])
227 };
228 expect_dns_name(&ee_cert_der, "example.com");
229 }
230
231 fn expect_dns_name(der: &CertificateDer<'_>, name: &str) {
232 let cert =
233 EndEntityCert::try_from(der).expect("should parse end entity certificate correctly");
234
235 let mut names = cert.valid_dns_names();
236 assert_eq!(names.next(), Some(name));
237 assert_eq!(names.next(), None);
238 }
239}
240