webpki/
cert.rs

1// Copyright 2015 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 crate::der::Tag;
16use crate::signed_data::SignedData;
17use crate::x509::{remember_extension, set_extension_once, Extension};
18use crate::{der, public_values_eq, Error};
19
20/// An enumeration indicating whether a [`Cert`] is a leaf end-entity cert, or a linked
21/// list node from the CA `Cert` to a child `Cert` it issued.
22pub enum EndEntityOrCa<'a> {
23    /// The [`Cert`] is a leaf end-entity certificate.
24    EndEntity,
25
26    /// The [`Cert`] is an issuer certificate, and issued the referenced child `Cert`.
27    Ca(&'a Cert<'a>),
28}
29
30/// A parsed X509 certificate.
31pub struct Cert<'a> {
32    pub(crate) ee_or_ca: EndEntityOrCa<'a>,
33
34    pub(crate) serial: untrusted::Input<'a>,
35    pub(crate) signed_data: SignedData<'a>,
36    pub(crate) issuer: untrusted::Input<'a>,
37    pub(crate) validity: untrusted::Input<'a>,
38    pub(crate) subject: untrusted::Input<'a>,
39    pub(crate) spki: der::Value<'a>,
40
41    pub(crate) basic_constraints: Option<untrusted::Input<'a>>,
42    // key usage (KU) extension (if any). When validating certificate revocation lists (CRLs) this
43    // field will be consulted to determine if the cert is allowed to sign CRLs. For cert validation
44    // this field is ignored (for more detail see in `verify_cert.rs` and
45    // `check_issuer_independent_properties`).
46    pub(crate) key_usage: Option<untrusted::Input<'a>>,
47    pub(crate) eku: Option<untrusted::Input<'a>>,
48    pub(crate) name_constraints: Option<untrusted::Input<'a>>,
49    pub(crate) subject_alt_name: Option<untrusted::Input<'a>>,
50}
51
52impl<'a> Cert<'a> {
53    pub(crate) fn from_der(
54        cert_der: untrusted::Input<'a>,
55        ee_or_ca: EndEntityOrCa<'a>,
56    ) -> Result<Self, Error> {
57        let (tbs, signed_data) = cert_der.read_all(Error::BadDer, |cert_der| {
58            der::nested(cert_der, der::Tag::Sequence, Error::BadDer, |der| {
59                // limited to SEQUENCEs of size 2^16 or less.
60                SignedData::from_der(der, der::TWO_BYTE_DER_SIZE)
61            })
62        })?;
63
64        tbs.read_all(Error::BadDer, |tbs| {
65            version3(tbs)?;
66
67            let serial = lenient_certificate_serial_number(tbs)?;
68
69            let signature = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
70            // TODO: In mozilla::pkix, the comparison is done based on the
71            // normalized value (ignoring whether or not there is an optional NULL
72            // parameter for RSA-based algorithms), so this may be too strict.
73            if !public_values_eq(signature, signed_data.algorithm) {
74                return Err(Error::SignatureAlgorithmMismatch);
75            }
76
77            let issuer = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
78            let validity = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
79            let subject = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
80            let spki = der::expect_tag(tbs, der::Tag::Sequence)?;
81
82            // In theory there could be fields [1] issuerUniqueID and [2]
83            // subjectUniqueID, but in practice there never are, and to keep the
84            // code small and simple we don't accept any certificates that do
85            // contain them.
86
87            let mut cert = Cert {
88                ee_or_ca,
89
90                signed_data,
91                serial,
92                issuer,
93                validity,
94                subject,
95                spki,
96
97                basic_constraints: None,
98                key_usage: None,
99                eku: None,
100                name_constraints: None,
101                subject_alt_name: None,
102            };
103
104            if !tbs.at_end() {
105                der::nested(
106                    tbs,
107                    der::Tag::ContextSpecificConstructed3,
108                    Error::MalformedExtensions,
109                    |tagged| {
110                        der::nested_of_mut(
111                            tagged,
112                            der::Tag::Sequence,
113                            der::Tag::Sequence,
114                            Error::BadDer,
115                            |extension| {
116                                remember_cert_extension(&mut cert, &Extension::parse(extension)?)
117                            },
118                        )
119                    },
120                )?;
121            }
122
123            Ok(cert)
124        })
125    }
126
127    /// Raw DER encoded certificate serial number.
128    pub fn serial(&self) -> &[u8] {
129        self.serial.as_slice_less_safe()
130    }
131
132    /// Raw DER encoded certificate issuer.
133    pub fn issuer(&self) -> &[u8] {
134        self.issuer.as_slice_less_safe()
135    }
136
137    /// Raw DER encoded certificate subject.
138    pub fn subject(&self) -> &[u8] {
139        self.subject.as_slice_less_safe()
140    }
141
142    /// Returns an indication of whether the certificate is an end-entity (leaf) certificate,
143    /// or a certificate authority.
144    pub fn end_entity_or_ca(&self) -> &EndEntityOrCa {
145        &self.ee_or_ca
146    }
147}
148
149// mozilla::pkix supports v1, v2, v3, and v4, including both the implicit
150// (correct) and explicit (incorrect) encoding of v1. We allow only v3.
151fn version3(input: &mut untrusted::Reader) -> Result<(), Error> {
152    der::nested(
153        input,
154        der::Tag::ContextSpecificConstructed0,
155        Error::UnsupportedCertVersion,
156        |input| {
157            let version = der::small_nonnegative_integer(input)?;
158            if version != 2 {
159                // v3
160                return Err(Error::UnsupportedCertVersion);
161            }
162            Ok(())
163        },
164    )
165}
166
167pub(crate) fn lenient_certificate_serial_number<'a>(
168    input: &mut untrusted::Reader<'a>,
169) -> Result<untrusted::Input<'a>, Error> {
170    // https://tools.ietf.org/html/rfc5280#section-4.1.2.2:
171    // * Conforming CAs MUST NOT use serialNumber values longer than 20 octets."
172    // * "The serial number MUST be a positive integer [...]"
173    //
174    // However, we don't enforce these constraints, as there are widely-deployed trust anchors
175    // and many X.509 implementations in common use that violate these constraints. This is called
176    // out by the same section of RFC 5280 as cited above:
177    //   Note: Non-conforming CAs may issue certificates with serial numbers
178    //   that are negative or zero.  Certificate users SHOULD be prepared to
179    //   gracefully handle such certificates.
180    der::expect_tag_and_get_value(input, Tag::Integer)
181}
182
183fn remember_cert_extension<'a>(
184    cert: &mut Cert<'a>,
185    extension: &Extension<'a>,
186) -> Result<(), Error> {
187    // We don't do anything with certificate policies so we can safely ignore
188    // all policy-related stuff. We assume that the policy-related extensions
189    // are not marked critical.
190
191    remember_extension(extension, |id| {
192        let out = match id {
193            // id-ce-keyUsage 2.5.29.15.
194            15 => &mut cert.key_usage,
195
196            // id-ce-subjectAltName 2.5.29.17
197            17 => &mut cert.subject_alt_name,
198
199            // id-ce-basicConstraints 2.5.29.19
200            19 => &mut cert.basic_constraints,
201
202            // id-ce-nameConstraints 2.5.29.30
203            30 => &mut cert.name_constraints,
204
205            // id-ce-extKeyUsage 2.5.29.37
206            37 => &mut cert.eku,
207
208            // Unsupported extension
209            _ => return extension.unsupported(),
210        };
211
212        set_extension_once(out, || {
213            extension.value.read_all(Error::BadDer, |value| match id {
214                // Unlike the other extensions we remember KU is a BitString and not a Sequence. We
215                // read the raw bytes here and parse at the time of use.
216                15 => Ok(value.read_bytes_to_end()),
217                // All other remembered certificate extensions are wrapped in a Sequence.
218                _ => der::expect_tag_and_get_value(value, Tag::Sequence),
219            })
220        })
221    })
222}
223
224#[cfg(test)]
225mod tests {
226    use crate::cert::{Cert, EndEntityOrCa};
227
228    #[test]
229    // Note: cert::parse_cert is crate-local visibility, and EndEntityCert doesn't expose the
230    //       inner Cert, or the serial number. As a result we test that the raw serial value
231    //       is read correctly here instead of in tests/integration.rs.
232    fn test_serial_read() {
233        let ee = include_bytes!("../tests/misc/serial_neg_ee.der");
234        let cert = Cert::from_der(untrusted::Input::from(ee), EndEntityOrCa::EndEntity)
235            .expect("failed to parse certificate");
236        assert_eq!(cert.serial.as_slice_less_safe(), &[255, 33, 82, 65, 17]);
237
238        let ee = include_bytes!("../tests/misc/serial_large_positive.der");
239        let cert = Cert::from_der(untrusted::Input::from(ee), EndEntityOrCa::EndEntity)
240            .expect("failed to parse certificate");
241        assert_eq!(
242            cert.serial.as_slice_less_safe(),
243            &[
244                0, 230, 9, 254, 122, 234, 0, 104, 140, 224, 36, 180, 237, 32, 27, 31, 239, 82, 180,
245                68, 209
246            ]
247        )
248    }
249}