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}