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 
15 use crate::{der, signed_data, Error};
16 
17 pub enum EndEntityOrCA<'a> {
18     EndEntity,
19     CA(&'a Cert<'a>),
20 }
21 
22 pub struct Cert<'a> {
23     pub ee_or_ca: EndEntityOrCA<'a>,
24 
25     pub signed_data: signed_data::SignedData<'a>,
26     pub issuer: untrusted::Input<'a>,
27     pub validity: untrusted::Input<'a>,
28     pub subject: untrusted::Input<'a>,
29     pub spki: der::Value<'a>,
30 
31     pub basic_constraints: Option<untrusted::Input<'a>>,
32     pub eku: Option<untrusted::Input<'a>>,
33     pub name_constraints: Option<untrusted::Input<'a>>,
34     pub subject_alt_name: Option<untrusted::Input<'a>>,
35 }
36 
parse_cert<'a>( cert_der: untrusted::Input<'a>, ee_or_ca: EndEntityOrCA<'a>, ) -> Result<Cert<'a>, Error>37 pub fn parse_cert<'a>(
38     cert_der: untrusted::Input<'a>, ee_or_ca: EndEntityOrCA<'a>,
39 ) -> Result<Cert<'a>, Error> {
40     parse_cert_internal(cert_der, ee_or_ca, certificate_serial_number)
41 }
42 
43 /// Used by `parse_cert` for regular certificates (end-entity and intermediate)
44 /// and by `cert_der_as_trust_anchor` for trust anchors encoded as
45 /// certificates.
parse_cert_internal<'a>( cert_der: untrusted::Input<'a>, ee_or_ca: EndEntityOrCA<'a>, serial_number: fn(input: &mut untrusted::Reader<'_>) -> Result<(), Error>, ) -> Result<Cert<'a>, Error>46 pub(crate) fn parse_cert_internal<'a>(
47     cert_der: untrusted::Input<'a>, ee_or_ca: EndEntityOrCA<'a>,
48     serial_number: fn(input: &mut untrusted::Reader<'_>) -> Result<(), Error>,
49 ) -> Result<Cert<'a>, Error> {
50     let (tbs, signed_data) = cert_der.read_all(Error::BadDER, |cert_der| {
51         der::nested(
52             cert_der,
53             der::Tag::Sequence,
54             Error::BadDER,
55             signed_data::parse_signed_data,
56         )
57     })?;
58 
59     tbs.read_all(Error::BadDER, |tbs| {
60         version3(tbs)?;
61         serial_number(tbs)?;
62 
63         let signature = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
64         // TODO: In mozilla::pkix, the comparison is done based on the
65         // normalized value (ignoring whether or not there is an optional NULL
66         // parameter for RSA-based algorithms), so this may be too strict.
67         if signature != signed_data.algorithm {
68             return Err(Error::SignatureAlgorithmMismatch);
69         }
70 
71         let issuer = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
72         let validity = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
73         let subject = der::expect_tag_and_get_value(tbs, der::Tag::Sequence)?;
74         let spki = der::expect_tag(tbs, der::Tag::Sequence)?;
75 
76         // In theory there could be fields [1] issuerUniqueID and [2]
77         // subjectUniqueID, but in practice there never are, and to keep the
78         // code small and simple we don't accept any certificates that do
79         // contain them.
80 
81         let mut cert = Cert {
82             ee_or_ca,
83 
84             signed_data,
85             issuer,
86             validity,
87             subject,
88             spki,
89 
90             basic_constraints: None,
91             eku: None,
92             name_constraints: None,
93             subject_alt_name: None,
94         };
95 
96         // mozilla::pkix allows the extensions to be omitted. However, since
97         // the subjectAltName extension is mandatory, the extensions are
98         // mandatory too, and we enforce that. Also, mozilla::pkix includes
99         // special logic for handling critical Netscape Cert Type extensions.
100         // That has been intentionally omitted.
101 
102         der::nested_mut(
103             tbs,
104             der::Tag::ContextSpecificConstructed3,
105             Error::BadDER,
106             |tagged| {
107                 der::nested_of_mut(
108                     tagged,
109                     der::Tag::Sequence,
110                     der::Tag::Sequence,
111                     Error::BadDER,
112                     |extension| {
113                         let extn_id = der::expect_tag_and_get_value(extension, der::Tag::OID)?;
114                         let critical = der::optional_boolean(extension)?;
115                         let extn_value =
116                             der::expect_tag_and_get_value(extension, der::Tag::OctetString)?;
117                         match remember_extension(&mut cert, extn_id, extn_value)? {
118                             Understood::No if critical => Err(Error::UnsupportedCriticalExtension),
119                             _ => Ok(()),
120                         }
121                     },
122                 )
123             },
124         )?;
125 
126         Ok(cert)
127     })
128 }
129 
130 // mozilla::pkix supports v1, v2, v3, and v4, including both the implicit
131 // (correct) and explicit (incorrect) encoding of v1. We allow only v3.
version3(input: &mut untrusted::Reader) -> Result<(), Error>132 fn version3(input: &mut untrusted::Reader) -> Result<(), Error> {
133     der::nested(
134         input,
135         der::Tag::ContextSpecificConstructed0,
136         Error::BadDER,
137         |input| {
138             let version = der::small_nonnegative_integer(input)?;
139             if version != 2 {
140                 // v3
141                 return Err(Error::UnsupportedCertVersion);
142             }
143             Ok(())
144         },
145     )
146 }
147 
certificate_serial_number(input: &mut untrusted::Reader) -> Result<(), Error>148 pub fn certificate_serial_number(input: &mut untrusted::Reader) -> Result<(), Error> {
149     // https://tools.ietf.org/html/rfc5280#section-4.1.2.2:
150     // * Conforming CAs MUST NOT use serialNumber values longer than 20 octets."
151     // * "The serial number MUST be a positive integer [...]"
152 
153     let value = der::positive_integer(input)?;
154     if value.big_endian_without_leading_zero().len() > 20 {
155         return Err(Error::BadDER);
156     }
157     Ok(())
158 }
159 
160 enum Understood {
161     Yes,
162     No,
163 }
164 
remember_extension<'a>( cert: &mut Cert<'a>, extn_id: untrusted::Input, value: untrusted::Input<'a>, ) -> Result<Understood, Error>165 fn remember_extension<'a>(
166     cert: &mut Cert<'a>, extn_id: untrusted::Input, value: untrusted::Input<'a>,
167 ) -> Result<Understood, Error> {
168     // We don't do anything with certificate policies so we can safely ignore
169     // all policy-related stuff. We assume that the policy-related extensions
170     // are not marked critical.
171 
172     // id-ce 2.5.29
173     static ID_CE: [u8; 2] = oid![2, 5, 29];
174 
175     if extn_id.len() != ID_CE.len() + 1 || !extn_id.as_slice_less_safe().starts_with(&ID_CE) {
176         return Ok(Understood::No);
177     }
178 
179     let out = match *extn_id.as_slice_less_safe().last().unwrap() {
180         // id-ce-keyUsage 2.5.29.15. We ignore the KeyUsage extension. For CA
181         // certificates, BasicConstraints.cA makes KeyUsage redundant. Firefox
182         // and other common browsers do not check KeyUsage for end-entities,
183         // though it would be kind of nice to ensure that a KeyUsage without
184         // the keyEncipherment bit could not be used for RSA key exchange.
185         15 => {
186             return Ok(Understood::Yes);
187         },
188 
189         // id-ce-subjectAltName 2.5.29.17
190         17 => &mut cert.subject_alt_name,
191 
192         // id-ce-basicConstraints 2.5.29.19
193         19 => &mut cert.basic_constraints,
194 
195         // id-ce-nameConstraints 2.5.29.30
196         30 => &mut cert.name_constraints,
197 
198         // id-ce-extKeyUsage 2.5.29.37
199         37 => &mut cert.eku,
200 
201         _ => {
202             return Ok(Understood::No);
203         },
204     };
205 
206     match *out {
207         Some(..) => {
208             // The certificate contains more than one instance of this
209             // extension.
210             return Err(Error::ExtensionValueInvalid);
211         },
212         None => {
213             // All the extensions that we care about are wrapped in a SEQUENCE.
214             let sequence_value = value.read_all(Error::BadDER, |value| {
215                 der::expect_tag_and_get_value(value, der::Tag::Sequence)
216             })?;
217             *out = Some(sequence_value);
218         },
219     }
220 
221     Ok(Understood::Yes)
222 }
223