/src/mozilla-central/security/pkix/lib/pkixcheck.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This code is made available to you under your choice of the following sets |
4 | | * of licensing terms: |
5 | | */ |
6 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
7 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
8 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
9 | | */ |
10 | | /* Copyright 2013 Mozilla Contributors |
11 | | * |
12 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
13 | | * you may not use this file except in compliance with the License. |
14 | | * You may obtain a copy of the License at |
15 | | * |
16 | | * http://www.apache.org/licenses/LICENSE-2.0 |
17 | | * |
18 | | * Unless required by applicable law or agreed to in writing, software |
19 | | * distributed under the License is distributed on an "AS IS" BASIS, |
20 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
21 | | * See the License for the specific language governing permissions and |
22 | | * limitations under the License. |
23 | | */ |
24 | | |
25 | | #include "pkixcheck.h" |
26 | | |
27 | | #include "pkixder.h" |
28 | | #include "pkixutil.h" |
29 | | |
30 | | namespace mozilla { namespace pkix { |
31 | | |
32 | | // 4.1.1.2 signatureAlgorithm |
33 | | // 4.1.2.3 signature |
34 | | |
35 | | Result |
36 | | CheckSignatureAlgorithm(TrustDomain& trustDomain, |
37 | | EndEntityOrCA endEntityOrCA, |
38 | | Time notBefore, |
39 | | const der::SignedDataWithSignature& signedData, |
40 | | Input signatureValue) |
41 | 0 | { |
42 | 0 | // 4.1.1.2. signatureAlgorithm |
43 | 0 | der::PublicKeyAlgorithm publicKeyAlg; |
44 | 0 | DigestAlgorithm digestAlg; |
45 | 0 | Reader signatureAlgorithmReader(signedData.algorithm); |
46 | 0 | Result rv = der::SignatureAlgorithmIdentifierValue(signatureAlgorithmReader, |
47 | 0 | publicKeyAlg, digestAlg); |
48 | 0 | if (rv != Success) { |
49 | 0 | return rv; |
50 | 0 | } |
51 | 0 | rv = der::End(signatureAlgorithmReader); |
52 | 0 | if (rv != Success) { |
53 | 0 | return rv; |
54 | 0 | } |
55 | 0 | |
56 | 0 | // 4.1.2.3. Signature |
57 | 0 | der::PublicKeyAlgorithm signedPublicKeyAlg; |
58 | 0 | DigestAlgorithm signedDigestAlg; |
59 | 0 | Reader signedSignatureAlgorithmReader(signatureValue); |
60 | 0 | rv = der::SignatureAlgorithmIdentifierValue(signedSignatureAlgorithmReader, |
61 | 0 | signedPublicKeyAlg, |
62 | 0 | signedDigestAlg); |
63 | 0 | if (rv != Success) { |
64 | 0 | return rv; |
65 | 0 | } |
66 | 0 | rv = der::End(signedSignatureAlgorithmReader); |
67 | 0 | if (rv != Success) { |
68 | 0 | return rv; |
69 | 0 | } |
70 | 0 | |
71 | 0 | // "This field MUST contain the same algorithm identifier as the |
72 | 0 | // signatureAlgorithm field in the sequence Certificate." However, it may |
73 | 0 | // be encoded differently. In particular, one of the fields may have a NULL |
74 | 0 | // parameter while the other one may omit the parameter field altogether, and |
75 | 0 | // these are considered equivalent. Some certificates generation software |
76 | 0 | // actually generates certificates like that, so we compare the parsed values |
77 | 0 | // instead of comparing the encoded values byte-for-byte. |
78 | 0 | // |
79 | 0 | // Along the same lines, we accept two different OIDs for RSA-with-SHA1, and |
80 | 0 | // we consider those OIDs to be equivalent here. |
81 | 0 | if (publicKeyAlg != signedPublicKeyAlg || digestAlg != signedDigestAlg) { |
82 | 0 | return Result::ERROR_SIGNATURE_ALGORITHM_MISMATCH; |
83 | 0 | } |
84 | 0 | |
85 | 0 | // During the time of the deprecation of SHA-1 and the deprecation of RSA |
86 | 0 | // keys of less than 2048 bits, we will encounter many certs signed using |
87 | 0 | // SHA-1 and/or too-small RSA keys. With this in mind, we ask the trust |
88 | 0 | // domain early on if it knows it will reject the signature purely based on |
89 | 0 | // the digest algorithm and/or the RSA key size (if an RSA signature). This |
90 | 0 | // is a good optimization because it completely avoids calling |
91 | 0 | // trustDomain.FindIssuers (which may be slow) for such rejected certs, and |
92 | 0 | // more generally it short-circuits any path building with them (which, of |
93 | 0 | // course, is even slower). |
94 | 0 | |
95 | 0 | rv = trustDomain.CheckSignatureDigestAlgorithm(digestAlg, endEntityOrCA, |
96 | 0 | notBefore); |
97 | 0 | if (rv != Success) { |
98 | 0 | return rv; |
99 | 0 | } |
100 | 0 | |
101 | 0 | switch (publicKeyAlg) { |
102 | 0 | case der::PublicKeyAlgorithm::RSA_PKCS1: |
103 | 0 | { |
104 | 0 | // The RSA computation may give a result that requires fewer bytes to |
105 | 0 | // encode than the public key (since it is modular arithmetic). However, |
106 | 0 | // the last step of generating a PKCS#1.5 signature is the I2OSP |
107 | 0 | // procedure, which pads any such shorter result with zeros so that it |
108 | 0 | // is exactly the same length as the public key. |
109 | 0 | unsigned int signatureSizeInBits = signedData.signature.GetLength() * 8u; |
110 | 0 | return trustDomain.CheckRSAPublicKeyModulusSizeInBits( |
111 | 0 | endEntityOrCA, signatureSizeInBits); |
112 | 0 | } |
113 | 0 |
|
114 | 0 | case der::PublicKeyAlgorithm::ECDSA: |
115 | 0 | // In theory, we could implement a similar early-pruning optimization for |
116 | 0 | // ECDSA curves. However, since there has been no similar deprecation for |
117 | 0 | // for any curve that we support, the chances of us encountering a curve |
118 | 0 | // during path building is too low to be worth bothering with. |
119 | 0 | break; |
120 | 0 | case der::PublicKeyAlgorithm::Uninitialized: |
121 | 0 | { |
122 | 0 | assert(false); |
123 | 0 | return Result::FATAL_ERROR_LIBRARY_FAILURE; |
124 | 0 | } |
125 | 0 | MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM |
126 | 0 | } |
127 | 0 | |
128 | 0 | return Success; |
129 | 0 | } |
130 | | |
131 | | // 4.1.2.4 Issuer |
132 | | |
133 | | Result |
134 | | CheckIssuer(Input encodedIssuer) |
135 | 0 | { |
136 | 0 | // "The issuer field MUST contain a non-empty distinguished name (DN)." |
137 | 0 | Reader issuer(encodedIssuer); |
138 | 0 | Input encodedRDNs; |
139 | 0 | ExpectTagAndGetValue(issuer, der::SEQUENCE, encodedRDNs); |
140 | 0 | Reader rdns(encodedRDNs); |
141 | 0 | // Check that the issuer name contains at least one RDN |
142 | 0 | // (Note: this does not check related grammar rules, such as there being one |
143 | 0 | // or more AVAs in each RDN, or the values in AVAs not being empty strings) |
144 | 0 | if (rdns.AtEnd()) { |
145 | 0 | return Result::ERROR_EMPTY_ISSUER_NAME; |
146 | 0 | } |
147 | 0 | return Success; |
148 | 0 | } |
149 | | |
150 | | // 4.1.2.5 Validity |
151 | | |
152 | | Result |
153 | | ParseValidity(Input encodedValidity, |
154 | | /*optional out*/ Time* notBeforeOut, |
155 | | /*optional out*/ Time* notAfterOut) |
156 | 0 | { |
157 | 0 | Reader validity(encodedValidity); |
158 | 0 | Time notBefore(Time::uninitialized); |
159 | 0 | if (der::TimeChoice(validity, notBefore) != Success) { |
160 | 0 | return Result::ERROR_INVALID_DER_TIME; |
161 | 0 | } |
162 | 0 | |
163 | 0 | Time notAfter(Time::uninitialized); |
164 | 0 | if (der::TimeChoice(validity, notAfter) != Success) { |
165 | 0 | return Result::ERROR_INVALID_DER_TIME; |
166 | 0 | } |
167 | 0 | |
168 | 0 | if (der::End(validity) != Success) { |
169 | 0 | return Result::ERROR_INVALID_DER_TIME; |
170 | 0 | } |
171 | 0 | |
172 | 0 | if (notBefore > notAfter) { |
173 | 0 | return Result::ERROR_INVALID_DER_TIME; |
174 | 0 | } |
175 | 0 | |
176 | 0 | if (notBeforeOut) { |
177 | 0 | *notBeforeOut = notBefore; |
178 | 0 | } |
179 | 0 | if (notAfterOut) { |
180 | 0 | *notAfterOut = notAfter; |
181 | 0 | } |
182 | 0 |
|
183 | 0 | return Success; |
184 | 0 | } |
185 | | |
186 | | Result |
187 | | CheckValidity(Time time, Time notBefore, Time notAfter) |
188 | 0 | { |
189 | 0 | if (time < notBefore) { |
190 | 0 | return Result::ERROR_NOT_YET_VALID_CERTIFICATE; |
191 | 0 | } |
192 | 0 | |
193 | 0 | if (time > notAfter) { |
194 | 0 | return Result::ERROR_EXPIRED_CERTIFICATE; |
195 | 0 | } |
196 | 0 | |
197 | 0 | return Success; |
198 | 0 | } |
199 | | |
200 | | // 4.1.2.7 Subject Public Key Info |
201 | | |
202 | | Result |
203 | | CheckSubjectPublicKeyInfoContents(Reader& input, TrustDomain& trustDomain, |
204 | | EndEntityOrCA endEntityOrCA) |
205 | 0 | { |
206 | 0 | // Here, we validate the syntax and do very basic semantic validation of the |
207 | 0 | // public key of the certificate. The intention here is to filter out the |
208 | 0 | // types of bad inputs that are most likely to trigger non-mathematical |
209 | 0 | // security vulnerabilities in the TrustDomain, like buffer overflows or the |
210 | 0 | // use of unsafe elliptic curves. |
211 | 0 | // |
212 | 0 | // We don't check (all of) the mathematical properties of the public key here |
213 | 0 | // because it is more efficient for the TrustDomain to do it during signature |
214 | 0 | // verification and/or other use of the public key. In particular, we |
215 | 0 | // delegate the arithmetic validation of the public key, as specified in |
216 | 0 | // NIST SP800-56A section 5.6.2, to the TrustDomain, at least for now. |
217 | 0 |
|
218 | 0 | Reader algorithm; |
219 | 0 | Input subjectPublicKey; |
220 | 0 | Result rv = der::ExpectTagAndGetValue(input, der::SEQUENCE, algorithm); |
221 | 0 | if (rv != Success) { |
222 | 0 | return rv; |
223 | 0 | } |
224 | 0 | rv = der::BitStringWithNoUnusedBits(input, subjectPublicKey); |
225 | 0 | if (rv != Success) { |
226 | 0 | return rv; |
227 | 0 | } |
228 | 0 | rv = der::End(input); |
229 | 0 | if (rv != Success) { |
230 | 0 | return rv; |
231 | 0 | } |
232 | 0 | |
233 | 0 | Reader subjectPublicKeyReader(subjectPublicKey); |
234 | 0 |
|
235 | 0 | Reader algorithmOID; |
236 | 0 | rv = der::ExpectTagAndGetValue(algorithm, der::OIDTag, algorithmOID); |
237 | 0 | if (rv != Success) { |
238 | 0 | return rv; |
239 | 0 | } |
240 | 0 | |
241 | 0 | // RFC 3279 Section 2.3.1 |
242 | 0 | // python DottedOIDToCode.py rsaEncryption 1.2.840.113549.1.1.1 |
243 | 0 | static const uint8_t rsaEncryption[] = { |
244 | 0 | 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 |
245 | 0 | }; |
246 | 0 |
|
247 | 0 | // RFC 3279 Section 2.3.5 and RFC 5480 Section 2.1.1 |
248 | 0 | // python DottedOIDToCode.py id-ecPublicKey 1.2.840.10045.2.1 |
249 | 0 | static const uint8_t id_ecPublicKey[] = { |
250 | 0 | 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 |
251 | 0 | }; |
252 | 0 |
|
253 | 0 | if (algorithmOID.MatchRest(id_ecPublicKey)) { |
254 | 0 | // An id-ecPublicKey AlgorithmIdentifier has a parameter that identifes |
255 | 0 | // the curve being used. Although RFC 5480 specifies multiple forms, we |
256 | 0 | // only supported the NamedCurve form, where the curve is identified by an |
257 | 0 | // OID. |
258 | 0 |
|
259 | 0 | Reader namedCurveOIDValue; |
260 | 0 | rv = der::ExpectTagAndGetValue(algorithm, der::OIDTag, |
261 | 0 | namedCurveOIDValue); |
262 | 0 | if (rv != Success) { |
263 | 0 | return rv; |
264 | 0 | } |
265 | 0 | |
266 | 0 | // RFC 5480 |
267 | 0 | // python DottedOIDToCode.py secp256r1 1.2.840.10045.3.1.7 |
268 | 0 | static const uint8_t secp256r1[] = { |
269 | 0 | 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 |
270 | 0 | }; |
271 | 0 |
|
272 | 0 | // RFC 5480 |
273 | 0 | // python DottedOIDToCode.py secp384r1 1.3.132.0.34 |
274 | 0 | static const uint8_t secp384r1[] = { |
275 | 0 | 0x2b, 0x81, 0x04, 0x00, 0x22 |
276 | 0 | }; |
277 | 0 |
|
278 | 0 | // RFC 5480 |
279 | 0 | // python DottedOIDToCode.py secp521r1 1.3.132.0.35 |
280 | 0 | static const uint8_t secp521r1[] = { |
281 | 0 | 0x2b, 0x81, 0x04, 0x00, 0x23 |
282 | 0 | }; |
283 | 0 |
|
284 | 0 | // Matching is attempted based on a rough estimate of the commonality of the |
285 | 0 | // elliptic curve, to minimize the number of MatchRest calls. |
286 | 0 | NamedCurve curve; |
287 | 0 | unsigned int bits; |
288 | 0 | if (namedCurveOIDValue.MatchRest(secp256r1)) { |
289 | 0 | curve = NamedCurve::secp256r1; |
290 | 0 | bits = 256; |
291 | 0 | } else if (namedCurveOIDValue.MatchRest(secp384r1)) { |
292 | 0 | curve = NamedCurve::secp384r1; |
293 | 0 | bits = 384; |
294 | 0 | } else if (namedCurveOIDValue.MatchRest(secp521r1)) { |
295 | 0 | curve = NamedCurve::secp521r1; |
296 | 0 | bits = 521; |
297 | 0 | } else { |
298 | 0 | return Result::ERROR_UNSUPPORTED_ELLIPTIC_CURVE; |
299 | 0 | } |
300 | 0 | |
301 | 0 | rv = trustDomain.CheckECDSACurveIsAcceptable(endEntityOrCA, curve); |
302 | 0 | if (rv != Success) { |
303 | 0 | return rv; |
304 | 0 | } |
305 | 0 | |
306 | 0 | // RFC 5480 Section 2.2 says that the first octet will be 0x04 to indicate |
307 | 0 | // an uncompressed point, which is the only encoding we support. |
308 | 0 | uint8_t compressedOrUncompressed; |
309 | 0 | rv = subjectPublicKeyReader.Read(compressedOrUncompressed); |
310 | 0 | if (rv != Success) { |
311 | 0 | return rv; |
312 | 0 | } |
313 | 0 | if (compressedOrUncompressed != 0x04) { |
314 | 0 | return Result::ERROR_UNSUPPORTED_EC_POINT_FORM; |
315 | 0 | } |
316 | 0 | |
317 | 0 | // The point is encoded as two raw (not DER-encoded) integers, each padded |
318 | 0 | // to the bit length (rounded up to the nearest byte). |
319 | 0 | Input point; |
320 | 0 | rv = subjectPublicKeyReader.SkipToEnd(point); |
321 | 0 | if (rv != Success) { |
322 | 0 | return rv; |
323 | 0 | } |
324 | 0 | if (point.GetLength() != ((bits + 7) / 8u) * 2u) { |
325 | 0 | return Result::ERROR_BAD_DER; |
326 | 0 | } |
327 | 0 | |
328 | 0 | // XXX: We defer the mathematical verification of the validity of the point |
329 | 0 | // until signature verification. This means that if we never verify a |
330 | 0 | // signature, we'll never fully check whether the public key is valid. |
331 | 0 | } else if (algorithmOID.MatchRest(rsaEncryption)) { |
332 | 0 | // RFC 3279 Section 2.3.1 says "The parameters field MUST have ASN.1 type |
333 | 0 | // NULL for this algorithm identifier." |
334 | 0 | rv = der::ExpectTagAndEmptyValue(algorithm, der::NULLTag); |
335 | 0 | if (rv != Success) { |
336 | 0 | return rv; |
337 | 0 | } |
338 | 0 | |
339 | 0 | // RSAPublicKey :: = SEQUENCE{ |
340 | 0 | // modulus INTEGER, --n |
341 | 0 | // publicExponent INTEGER } --e |
342 | 0 | rv = der::Nested(subjectPublicKeyReader, der::SEQUENCE, |
343 | 0 | [&trustDomain, endEntityOrCA](Reader& r) { |
344 | 0 | Input modulus; |
345 | 0 | Input::size_type modulusSignificantBytes; |
346 | 0 | Result nestedRv = |
347 | 0 | der::PositiveInteger(r, modulus, &modulusSignificantBytes); |
348 | 0 | if (nestedRv != Success) { |
349 | 0 | return nestedRv; |
350 | 0 | } |
351 | 0 | // XXX: Should we do additional checks of the modulus? |
352 | 0 | nestedRv = trustDomain.CheckRSAPublicKeyModulusSizeInBits( |
353 | 0 | endEntityOrCA, modulusSignificantBytes * 8u); |
354 | 0 | if (nestedRv != Success) { |
355 | 0 | return nestedRv; |
356 | 0 | } |
357 | 0 | |
358 | 0 | // XXX: We don't allow the TrustDomain to validate the exponent. |
359 | 0 | // XXX: We don't do our own sanity checking of the exponent. |
360 | 0 | Input exponent; |
361 | 0 | return der::PositiveInteger(r, exponent); |
362 | 0 | }); |
363 | 0 | if (rv != Success) { |
364 | 0 | return rv; |
365 | 0 | } |
366 | 0 | } else { |
367 | 0 | return Result::ERROR_UNSUPPORTED_KEYALG; |
368 | 0 | } |
369 | 0 | |
370 | 0 | rv = der::End(algorithm); |
371 | 0 | if (rv != Success) { |
372 | 0 | return rv; |
373 | 0 | } |
374 | 0 | rv = der::End(subjectPublicKeyReader); |
375 | 0 | if (rv != Success) { |
376 | 0 | return rv; |
377 | 0 | } |
378 | 0 | |
379 | 0 | return Success; |
380 | 0 | } |
381 | | |
382 | | Result |
383 | | CheckSubjectPublicKeyInfo(Input subjectPublicKeyInfo, TrustDomain& trustDomain, |
384 | | EndEntityOrCA endEntityOrCA) |
385 | 0 | { |
386 | 0 | Reader spkiReader(subjectPublicKeyInfo); |
387 | 0 | Result rv = der::Nested(spkiReader, der::SEQUENCE, [&](Reader& r) { |
388 | 0 | return CheckSubjectPublicKeyInfoContents(r, trustDomain, endEntityOrCA); |
389 | 0 | }); |
390 | 0 | if (rv != Success) { |
391 | 0 | return rv; |
392 | 0 | } |
393 | 0 | return der::End(spkiReader); |
394 | 0 | } |
395 | | |
396 | | // 4.2.1.3. Key Usage (id-ce-keyUsage) |
397 | | |
398 | | // As explained in the comment in CheckKeyUsage, bit 0 is the most significant |
399 | | // bit and bit 7 is the least significant bit. |
400 | | inline uint8_t KeyUsageToBitMask(KeyUsage keyUsage) |
401 | 0 | { |
402 | 0 | assert(keyUsage != KeyUsage::noParticularKeyUsageRequired); |
403 | 0 | return 0x80u >> static_cast<uint8_t>(keyUsage); |
404 | 0 | } |
405 | | |
406 | | Result |
407 | | CheckKeyUsage(EndEntityOrCA endEntityOrCA, const Input* encodedKeyUsage, |
408 | | KeyUsage requiredKeyUsageIfPresent) |
409 | 0 | { |
410 | 0 | if (!encodedKeyUsage) { |
411 | 0 | // TODO(bug 970196): Reject certificates that are being used to verify |
412 | 0 | // certificate signatures unless the certificate is a trust anchor, to |
413 | 0 | // reduce the chances of an end-entity certificate being abused as a CA |
414 | 0 | // certificate. |
415 | 0 | // if (endEntityOrCA == EndEntityOrCA::MustBeCA && !isTrustAnchor) { |
416 | 0 | // return Result::ERROR_INADEQUATE_KEY_USAGE; |
417 | 0 | // } |
418 | 0 | // |
419 | 0 | // TODO: Users may configure arbitrary certificates as trust anchors, not |
420 | 0 | // just roots. We should only allow a certificate without a key usage to be |
421 | 0 | // used as a CA when it is self-issued and self-signed. |
422 | 0 | return Success; |
423 | 0 | } |
424 | 0 | |
425 | 0 | Reader input(*encodedKeyUsage); |
426 | 0 | Reader value; |
427 | 0 | if (der::ExpectTagAndGetValue(input, der::BIT_STRING, value) != Success) { |
428 | 0 | return Result::ERROR_INADEQUATE_KEY_USAGE; |
429 | 0 | } |
430 | 0 | |
431 | 0 | uint8_t numberOfPaddingBits; |
432 | 0 | if (value.Read(numberOfPaddingBits) != Success) { |
433 | 0 | return Result::ERROR_INADEQUATE_KEY_USAGE; |
434 | 0 | } |
435 | 0 | if (numberOfPaddingBits > 7) { |
436 | 0 | return Result::ERROR_INADEQUATE_KEY_USAGE; |
437 | 0 | } |
438 | 0 | |
439 | 0 | uint8_t bits; |
440 | 0 | if (value.Read(bits) != Success) { |
441 | 0 | // Reject empty bit masks. |
442 | 0 | return Result::ERROR_INADEQUATE_KEY_USAGE; |
443 | 0 | } |
444 | 0 | |
445 | 0 | // The most significant bit is numbered 0 (digitalSignature) and the least |
446 | 0 | // significant bit is numbered 7 (encipherOnly), and the padding is in the |
447 | 0 | // least significant bits of the last byte. The numbering of bits in a byte |
448 | 0 | // is backwards from how we usually interpret them. |
449 | 0 | // |
450 | 0 | // For example, let's say bits is encoded in one byte with of value 0xB0 and |
451 | 0 | // numberOfPaddingBits == 4. Then, bits is 10110000 in binary: |
452 | 0 | // |
453 | 0 | // bit 0 bit 3 |
454 | 0 | // | | |
455 | 0 | // v v |
456 | 0 | // 10110000 |
457 | 0 | // ^^^^ |
458 | 0 | // | |
459 | 0 | // 4 padding bits |
460 | 0 | // |
461 | 0 | // Since bits is the last byte, we have to consider the padding by ensuring |
462 | 0 | // that the least significant 4 bits are all zero, since DER rules require |
463 | 0 | // all padding bits to be zero. Then we have to look at the bit N bits to the |
464 | 0 | // right of the most significant bit, where N is a value from the KeyUsage |
465 | 0 | // enumeration. |
466 | 0 | // |
467 | 0 | // Let's say we're interested in the keyCertSign (5) bit. We'd need to look |
468 | 0 | // at bit 5, which is zero, so keyCertSign is not asserted. (Since we check |
469 | 0 | // that the padding is all zeros, it is OK to read from the padding bits.) |
470 | 0 | // |
471 | 0 | // Let's say we're interested in the digitalSignature (0) bit. We'd need to |
472 | 0 | // look at the bit 0 (the most significant bit), which is set, so that means |
473 | 0 | // digitalSignature is asserted. Similarly, keyEncipherment (2) and |
474 | 0 | // dataEncipherment (3) are asserted. |
475 | 0 | // |
476 | 0 | // Note that since the KeyUsage enumeration is limited to values 0-7, we |
477 | 0 | // only ever need to examine the first byte test for |
478 | 0 | // requiredKeyUsageIfPresent. |
479 | 0 | |
480 | 0 | if (requiredKeyUsageIfPresent != KeyUsage::noParticularKeyUsageRequired) { |
481 | 0 | // Check that the required key usage bit is set. |
482 | 0 | if ((bits & KeyUsageToBitMask(requiredKeyUsageIfPresent)) == 0) { |
483 | 0 | return Result::ERROR_INADEQUATE_KEY_USAGE; |
484 | 0 | } |
485 | 0 | } |
486 | 0 | |
487 | 0 | // RFC 5280 says "The keyCertSign bit is asserted when the subject public |
488 | 0 | // key is used for verifying signatures on public key certificates. If the |
489 | 0 | // keyCertSign bit is asserted, then the cA bit in the basic constraints |
490 | 0 | // extension (Section 4.2.1.9) MUST also be asserted." |
491 | 0 | // However, we allow end-entity certificates (i.e. certificates without |
492 | 0 | // basicConstraints.cA set to TRUE) to claim keyCertSign for compatibility |
493 | 0 | // reasons. This does not compromise security because we only allow |
494 | 0 | // certificates with basicConstraints.cA set to TRUE to act as CAs. |
495 | 0 | if (requiredKeyUsageIfPresent == KeyUsage::keyCertSign && |
496 | 0 | endEntityOrCA != EndEntityOrCA::MustBeCA) { |
497 | 0 | return Result::ERROR_INADEQUATE_KEY_USAGE; |
498 | 0 | } |
499 | 0 | |
500 | 0 | // The padding applies to the last byte, so skip to the last byte. |
501 | 0 | while (!value.AtEnd()) { |
502 | 0 | if (value.Read(bits) != Success) { |
503 | 0 | return Result::ERROR_INADEQUATE_KEY_USAGE; |
504 | 0 | } |
505 | 0 | } |
506 | 0 |
|
507 | 0 | // All of the padding bits must be zero, according to DER rules. |
508 | 0 | uint8_t paddingMask = static_cast<uint8_t>((1 << numberOfPaddingBits) - 1); |
509 | 0 | if ((bits & paddingMask) != 0) { |
510 | 0 | return Result::ERROR_INADEQUATE_KEY_USAGE; |
511 | 0 | } |
512 | 0 | |
513 | 0 | return Success; |
514 | 0 | } |
515 | | |
516 | | // RFC5820 4.2.1.4. Certificate Policies |
517 | | |
518 | | // "The user-initial-policy-set contains the special value any-policy if the |
519 | | // user is not concerned about certificate policy." |
520 | | // |
521 | | // python DottedOIDToCode.py anyPolicy 2.5.29.32.0 |
522 | | |
523 | | static const uint8_t anyPolicy[] = { |
524 | | 0x55, 0x1d, 0x20, 0x00 |
525 | | }; |
526 | | |
527 | | /*static*/ const CertPolicyId CertPolicyId::anyPolicy = { |
528 | | 4, { 0x55, 0x1d, 0x20, 0x00 } |
529 | | }; |
530 | | |
531 | | bool |
532 | 0 | CertPolicyId::IsAnyPolicy() const { |
533 | 0 | if (this == &CertPolicyId::anyPolicy) { |
534 | 0 | return true; |
535 | 0 | } |
536 | 0 | return numBytes == sizeof(::mozilla::pkix::anyPolicy) && |
537 | 0 | std::equal(bytes, bytes + numBytes, ::mozilla::pkix::anyPolicy); |
538 | 0 | } |
539 | | |
540 | | bool |
541 | | CertPolicyId::operator==(const CertPolicyId& other) const |
542 | 0 | { |
543 | 0 | return numBytes == other.numBytes && |
544 | 0 | std::equal(bytes, bytes + numBytes, other.bytes); |
545 | 0 | } |
546 | | |
547 | | // certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation |
548 | | Result |
549 | | CheckCertificatePolicies(EndEntityOrCA endEntityOrCA, |
550 | | const Input* encodedCertificatePolicies, |
551 | | const Input* encodedInhibitAnyPolicy, |
552 | | TrustLevel trustLevel, |
553 | | const CertPolicyId& requiredPolicy) |
554 | 0 | { |
555 | 0 | if (requiredPolicy.numBytes == 0 || |
556 | 0 | requiredPolicy.numBytes > sizeof requiredPolicy.bytes) { |
557 | 0 | return Result::FATAL_ERROR_INVALID_ARGS; |
558 | 0 | } |
559 | 0 | |
560 | 0 | bool requiredPolicyFound = requiredPolicy.IsAnyPolicy(); |
561 | 0 | if (requiredPolicyFound) { |
562 | 0 | return Success; |
563 | 0 | } |
564 | 0 | |
565 | 0 | // Bug 989051. Until we handle inhibitAnyPolicy we will fail close when |
566 | 0 | // inhibitAnyPolicy extension is present and we are validating for a policy. |
567 | 0 | if (!requiredPolicyFound && encodedInhibitAnyPolicy) { |
568 | 0 | return Result::ERROR_POLICY_VALIDATION_FAILED; |
569 | 0 | } |
570 | 0 | |
571 | 0 | // The root CA certificate may omit the policies that it has been |
572 | 0 | // trusted for, so we cannot require the policies to be present in those |
573 | 0 | // certificates. Instead, the determination of which roots are trusted for |
574 | 0 | // which policies is made by the TrustDomain's GetCertTrust method. |
575 | 0 | if (trustLevel == TrustLevel::TrustAnchor && |
576 | 0 | endEntityOrCA == EndEntityOrCA::MustBeCA) { |
577 | 0 | requiredPolicyFound = true; |
578 | 0 | } |
579 | 0 |
|
580 | 0 | Input requiredPolicyDER; |
581 | 0 | if (requiredPolicyDER.Init(requiredPolicy.bytes, requiredPolicy.numBytes) |
582 | 0 | != Success) { |
583 | 0 | return Result::FATAL_ERROR_INVALID_ARGS; |
584 | 0 | } |
585 | 0 | |
586 | 0 | if (encodedCertificatePolicies) { |
587 | 0 | Reader extension(*encodedCertificatePolicies); |
588 | 0 | Reader certificatePolicies; |
589 | 0 | Result rv = der::ExpectTagAndGetValue(extension, der::SEQUENCE, |
590 | 0 | certificatePolicies); |
591 | 0 | if (rv != Success) { |
592 | 0 | return Result::ERROR_POLICY_VALIDATION_FAILED; |
593 | 0 | } |
594 | 0 | if (!extension.AtEnd()) { |
595 | 0 | return Result::ERROR_POLICY_VALIDATION_FAILED; |
596 | 0 | } |
597 | 0 | |
598 | 0 | do { |
599 | 0 | // PolicyInformation ::= SEQUENCE { |
600 | 0 | // policyIdentifier CertPolicyId, |
601 | 0 | // policyQualifiers SEQUENCE SIZE (1..MAX) OF |
602 | 0 | // PolicyQualifierInfo OPTIONAL } |
603 | 0 | Reader policyInformation; |
604 | 0 | rv = der::ExpectTagAndGetValue(certificatePolicies, der::SEQUENCE, |
605 | 0 | policyInformation); |
606 | 0 | if (rv != Success) { |
607 | 0 | return Result::ERROR_POLICY_VALIDATION_FAILED; |
608 | 0 | } |
609 | 0 | |
610 | 0 | Reader policyIdentifier; |
611 | 0 | rv = der::ExpectTagAndGetValue(policyInformation, der::OIDTag, |
612 | 0 | policyIdentifier); |
613 | 0 | if (rv != Success) { |
614 | 0 | return rv; |
615 | 0 | } |
616 | 0 | |
617 | 0 | if (policyIdentifier.MatchRest(requiredPolicyDER)) { |
618 | 0 | requiredPolicyFound = true; |
619 | 0 | } else if (endEntityOrCA == EndEntityOrCA::MustBeCA && |
620 | 0 | policyIdentifier.MatchRest(anyPolicy)) { |
621 | 0 | requiredPolicyFound = true; |
622 | 0 | } |
623 | 0 |
|
624 | 0 | // RFC 5280 Section 4.2.1.4 says "Optional qualifiers, which MAY be |
625 | 0 | // present, are not expected to change the definition of the policy." Also, |
626 | 0 | // it seems that Section 6, which defines validation, does not require any |
627 | 0 | // matching of qualifiers. Thus, doing anything with the policy qualifiers |
628 | 0 | // would be a waste of time and a source of potential incompatibilities, so |
629 | 0 | // we just ignore them. |
630 | 0 | } while (!requiredPolicyFound && !certificatePolicies.AtEnd()); |
631 | 0 | } |
632 | 0 |
|
633 | 0 | if (!requiredPolicyFound) { |
634 | 0 | return Result::ERROR_POLICY_VALIDATION_FAILED; |
635 | 0 | } |
636 | 0 | |
637 | 0 | return Success; |
638 | 0 | } |
639 | | |
640 | | static const long UNLIMITED_PATH_LEN = -1; // must be less than zero |
641 | | |
642 | | // BasicConstraints ::= SEQUENCE { |
643 | | // cA BOOLEAN DEFAULT FALSE, |
644 | | // pathLenConstraint INTEGER (0..MAX) OPTIONAL } |
645 | | |
646 | | // RFC5280 4.2.1.9. Basic Constraints (id-ce-basicConstraints) |
647 | | Result |
648 | | CheckBasicConstraints(EndEntityOrCA endEntityOrCA, |
649 | | const Input* encodedBasicConstraints, |
650 | | const der::Version version, TrustLevel trustLevel, |
651 | | unsigned int subCACount) |
652 | 0 | { |
653 | 0 | bool isCA = false; |
654 | 0 | long pathLenConstraint = UNLIMITED_PATH_LEN; |
655 | 0 |
|
656 | 0 | if (encodedBasicConstraints) { |
657 | 0 | Reader input(*encodedBasicConstraints); |
658 | 0 | Result rv = der::Nested(input, der::SEQUENCE, |
659 | 0 | [&isCA, &pathLenConstraint](Reader& r) { |
660 | 0 | Result nestedRv = der::OptionalBoolean(r, isCA); |
661 | 0 | if (nestedRv != Success) { |
662 | 0 | return nestedRv; |
663 | 0 | } |
664 | 0 | // TODO(bug 985025): If isCA is false, pathLenConstraint |
665 | 0 | // MUST NOT be included (as per RFC 5280 section |
666 | 0 | // 4.2.1.9), but for compatibility reasons, we don't |
667 | 0 | // check this. |
668 | 0 | return der::OptionalInteger(r, UNLIMITED_PATH_LEN, pathLenConstraint); |
669 | 0 | }); |
670 | 0 | if (rv != Success) { |
671 | 0 | return Result::ERROR_EXTENSION_VALUE_INVALID; |
672 | 0 | } |
673 | 0 | if (der::End(input) != Success) { |
674 | 0 | return Result::ERROR_EXTENSION_VALUE_INVALID; |
675 | 0 | } |
676 | 0 | } else { |
677 | 0 | // "If the basic constraints extension is not present in a version 3 |
678 | 0 | // certificate, or the extension is present but the cA boolean is not |
679 | 0 | // asserted, then the certified public key MUST NOT be used to verify |
680 | 0 | // certificate signatures." |
681 | 0 | // |
682 | 0 | // For compatibility, we must accept v1 trust anchors without basic |
683 | 0 | // constraints as CAs. |
684 | 0 | // |
685 | 0 | // There are devices with v1 certificates that are unlikely to be trust |
686 | 0 | // anchors. In order to allow applications to treat this case differently |
687 | 0 | // from other basic constraints violations (e.g. allowing certificate error |
688 | 0 | // overrides for only this case), we return a different error code. |
689 | 0 | // |
690 | 0 | // TODO: add check for self-signedness? |
691 | 0 | if (endEntityOrCA == EndEntityOrCA::MustBeCA && version == der::Version::v1) { |
692 | 0 | if (trustLevel == TrustLevel::TrustAnchor) { |
693 | 0 | isCA = true; |
694 | 0 | } else { |
695 | 0 | return Result::ERROR_V1_CERT_USED_AS_CA; |
696 | 0 | } |
697 | 0 | } |
698 | 0 | } |
699 | 0 | |
700 | 0 | if (endEntityOrCA == EndEntityOrCA::MustBeEndEntity) { |
701 | 0 | // CA certificates are not trusted as EE certs. |
702 | 0 |
|
703 | 0 | if (isCA) { |
704 | 0 | // Note that this check prevents a delegated OCSP response signing |
705 | 0 | // certificate with the CA bit from successfully validating when we check |
706 | 0 | // it from pkixocsp.cpp, which is a good thing. |
707 | 0 | return Result::ERROR_CA_CERT_USED_AS_END_ENTITY; |
708 | 0 | } |
709 | 0 | |
710 | 0 | return Success; |
711 | 0 | } |
712 | 0 | |
713 | 0 | assert(endEntityOrCA == EndEntityOrCA::MustBeCA); |
714 | 0 |
|
715 | 0 | // End-entity certificates are not allowed to act as CA certs. |
716 | 0 | if (!isCA) { |
717 | 0 | return Result::ERROR_CA_CERT_INVALID; |
718 | 0 | } |
719 | 0 | |
720 | 0 | if (pathLenConstraint >= 0 && |
721 | 0 | static_cast<long>(subCACount) > pathLenConstraint) { |
722 | 0 | return Result::ERROR_PATH_LEN_CONSTRAINT_INVALID; |
723 | 0 | } |
724 | 0 | |
725 | 0 | return Success; |
726 | 0 | } |
727 | | |
728 | | // 4.2.1.12. Extended Key Usage (id-ce-extKeyUsage) |
729 | | |
730 | | static Result |
731 | | MatchEKU(Reader& value, KeyPurposeId requiredEKU, |
732 | | EndEntityOrCA endEntityOrCA, TrustDomain& trustDomain, |
733 | | Time notBefore, /*in/out*/ bool& found, |
734 | | /*in/out*/ bool& foundOCSPSigning) |
735 | 0 | { |
736 | 0 | // See Section 5.9 of "A Layman's Guide to a Subset of ASN.1, BER, and DER" |
737 | 0 | // for a description of ASN.1 DER encoding of OIDs. |
738 | 0 |
|
739 | 0 | // id-pkix OBJECT IDENTIFIER ::= |
740 | 0 | // { iso(1) identified-organization(3) dod(6) internet(1) |
741 | 0 | // security(5) mechanisms(5) pkix(7) } |
742 | 0 | // id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } |
743 | 0 | // id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } |
744 | 0 | // id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } |
745 | 0 | // id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } |
746 | 0 | // id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } |
747 | 0 | // id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } |
748 | 0 | static const uint8_t server[] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 1 }; |
749 | 0 | static const uint8_t client[] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 2 }; |
750 | 0 | static const uint8_t code [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 3 }; |
751 | 0 | static const uint8_t email [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 4 }; |
752 | 0 | static const uint8_t ocsp [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 9 }; |
753 | 0 |
|
754 | 0 | // id-Netscape OBJECT IDENTIFIER ::= { 2 16 840 1 113730 } |
755 | 0 | // id-Netscape-policy OBJECT IDENTIFIER ::= { id-Netscape 4 } |
756 | 0 | // id-Netscape-stepUp OBJECT IDENTIFIER ::= { id-Netscape-policy 1 } |
757 | 0 | static const uint8_t serverStepUp[] = |
758 | 0 | { (40*2)+16, 128+6,72, 1, 128+6,128+120,66, 4, 1 }; |
759 | 0 |
|
760 | 0 | bool match = false; |
761 | 0 |
|
762 | 0 | if (!found) { |
763 | 0 | switch (requiredEKU) { |
764 | 0 | case KeyPurposeId::id_kp_serverAuth: { |
765 | 0 | if (value.MatchRest(server)) { |
766 | 0 | match = true; |
767 | 0 | break; |
768 | 0 | } |
769 | 0 | // Potentially treat CA certs with step-up OID as also having SSL server |
770 | 0 | // type. Comodo has issued certificates that require this behavior that |
771 | 0 | // don't expire until June 2020! |
772 | 0 | if (endEntityOrCA == EndEntityOrCA::MustBeCA && |
773 | 0 | value.MatchRest(serverStepUp)) { |
774 | 0 | Result rv = trustDomain.NetscapeStepUpMatchesServerAuth(notBefore, |
775 | 0 | match); |
776 | 0 | if (rv != Success) { |
777 | 0 | return rv; |
778 | 0 | } |
779 | 0 | } |
780 | 0 | break; |
781 | 0 | } |
782 | 0 |
|
783 | 0 | case KeyPurposeId::id_kp_clientAuth: |
784 | 0 | match = value.MatchRest(client); |
785 | 0 | break; |
786 | 0 |
|
787 | 0 | case KeyPurposeId::id_kp_codeSigning: |
788 | 0 | match = value.MatchRest(code); |
789 | 0 | break; |
790 | 0 |
|
791 | 0 | case KeyPurposeId::id_kp_emailProtection: |
792 | 0 | match = value.MatchRest(email); |
793 | 0 | break; |
794 | 0 |
|
795 | 0 | case KeyPurposeId::id_kp_OCSPSigning: |
796 | 0 | match = value.MatchRest(ocsp); |
797 | 0 | break; |
798 | 0 |
|
799 | 0 | case KeyPurposeId::anyExtendedKeyUsage: |
800 | 0 | return NotReached("anyExtendedKeyUsage should start with found==true", |
801 | 0 | Result::FATAL_ERROR_LIBRARY_FAILURE); |
802 | 0 | } |
803 | 0 | } |
804 | 0 | |
805 | 0 | if (match) { |
806 | 0 | found = true; |
807 | 0 | if (requiredEKU == KeyPurposeId::id_kp_OCSPSigning) { |
808 | 0 | foundOCSPSigning = true; |
809 | 0 | } |
810 | 0 | } else if (value.MatchRest(ocsp)) { |
811 | 0 | foundOCSPSigning = true; |
812 | 0 | } |
813 | 0 |
|
814 | 0 | value.SkipToEnd(); // ignore unmatched OIDs. |
815 | 0 |
|
816 | 0 | return Success; |
817 | 0 | } |
818 | | |
819 | | Result |
820 | | CheckExtendedKeyUsage(EndEntityOrCA endEntityOrCA, |
821 | | const Input* encodedExtendedKeyUsage, |
822 | | KeyPurposeId requiredEKU, TrustDomain& trustDomain, |
823 | | Time notBefore) |
824 | 0 | { |
825 | 0 | // XXX: We're using Result::ERROR_INADEQUATE_CERT_TYPE here so that callers |
826 | 0 | // can distinguish EKU mismatch from KU mismatch from basic constraints |
827 | 0 | // mismatch. We should probably add a new error code that is more clear for |
828 | 0 | // this type of problem. |
829 | 0 |
|
830 | 0 | bool foundOCSPSigning = false; |
831 | 0 |
|
832 | 0 | if (encodedExtendedKeyUsage) { |
833 | 0 | bool found = requiredEKU == KeyPurposeId::anyExtendedKeyUsage; |
834 | 0 |
|
835 | 0 | Reader input(*encodedExtendedKeyUsage); |
836 | 0 | Result rv = der::NestedOf(input, der::SEQUENCE, der::OIDTag, |
837 | 0 | der::EmptyAllowed::No, [&](Reader& r) { |
838 | 0 | return MatchEKU(r, requiredEKU, endEntityOrCA, trustDomain, notBefore, |
839 | 0 | found, foundOCSPSigning); |
840 | 0 | }); |
841 | 0 | if (rv != Success) { |
842 | 0 | return Result::ERROR_INADEQUATE_CERT_TYPE; |
843 | 0 | } |
844 | 0 | if (der::End(input) != Success) { |
845 | 0 | return Result::ERROR_INADEQUATE_CERT_TYPE; |
846 | 0 | } |
847 | 0 | |
848 | 0 | // If the EKU extension was included, then the required EKU must be in the |
849 | 0 | // list. |
850 | 0 | if (!found) { |
851 | 0 | return Result::ERROR_INADEQUATE_CERT_TYPE; |
852 | 0 | } |
853 | 0 | } |
854 | 0 | |
855 | 0 | // pkixocsp.cpp depends on the following additional checks. |
856 | 0 | |
857 | 0 | if (endEntityOrCA == EndEntityOrCA::MustBeEndEntity) { |
858 | 0 | // When validating anything other than an delegated OCSP signing cert, |
859 | 0 | // reject any cert that also claims to be an OCSP responder, because such |
860 | 0 | // a cert does not make sense. For example, if an SSL certificate were to |
861 | 0 | // assert id-kp-OCSPSigning then it could sign OCSP responses for itself, |
862 | 0 | // if not for this check. |
863 | 0 | // That said, we accept CA certificates with id-kp-OCSPSigning because |
864 | 0 | // some CAs in Mozilla's CA program have issued such intermediate |
865 | 0 | // certificates, and because some CAs have reported some Microsoft server |
866 | 0 | // software wrongly requires CA certificates to have id-kp-OCSPSigning. |
867 | 0 | // Allowing this exception does not cause any security issues because we |
868 | 0 | // require delegated OCSP response signing certificates to be end-entity |
869 | 0 | // certificates. |
870 | 0 | if (foundOCSPSigning && requiredEKU != KeyPurposeId::id_kp_OCSPSigning) { |
871 | 0 | return Result::ERROR_INADEQUATE_CERT_TYPE; |
872 | 0 | } |
873 | 0 | // http://tools.ietf.org/html/rfc6960#section-4.2.2.2: |
874 | 0 | // "OCSP signing delegation SHALL be designated by the inclusion of |
875 | 0 | // id-kp-OCSPSigning in an extended key usage certificate extension |
876 | 0 | // included in the OCSP response signer's certificate." |
877 | 0 | // |
878 | 0 | // id-kp-OCSPSigning is the only EKU that isn't implicitly assumed when the |
879 | 0 | // EKU extension is missing from an end-entity certificate. However, any CA |
880 | 0 | // certificate can issue a delegated OCSP response signing certificate, so |
881 | 0 | // we can't require the EKU be explicitly included for CA certificates. |
882 | 0 | if (!foundOCSPSigning && requiredEKU == KeyPurposeId::id_kp_OCSPSigning) { |
883 | 0 | return Result::ERROR_INADEQUATE_CERT_TYPE; |
884 | 0 | } |
885 | 0 | } |
886 | 0 | |
887 | 0 | return Success; |
888 | 0 | } |
889 | | |
890 | | Result |
891 | | CheckTLSFeatures(const BackCert& subject, BackCert& potentialIssuer) |
892 | 0 | { |
893 | 0 | const Input* issuerTLSFeatures = potentialIssuer.GetRequiredTLSFeatures(); |
894 | 0 | if (!issuerTLSFeatures) { |
895 | 0 | return Success; |
896 | 0 | } |
897 | 0 | |
898 | 0 | const Input* subjectTLSFeatures = subject.GetRequiredTLSFeatures(); |
899 | 0 | if (issuerTLSFeatures->GetLength() == 0 || |
900 | 0 | !subjectTLSFeatures || |
901 | 0 | !InputsAreEqual(*issuerTLSFeatures, *subjectTLSFeatures)) { |
902 | 0 | return Result::ERROR_REQUIRED_TLS_FEATURE_MISSING; |
903 | 0 | } |
904 | 0 | |
905 | 0 | return Success; |
906 | 0 | } |
907 | | |
908 | | Result |
909 | | TLSFeaturesSatisfiedInternal(const Input* requiredTLSFeatures, |
910 | | const Input* stapledOCSPResponse) |
911 | 0 | { |
912 | 0 | if (!requiredTLSFeatures) { |
913 | 0 | return Success; |
914 | 0 | } |
915 | 0 | |
916 | 0 | // RFC 6066 10.2: ExtensionType status_request |
917 | 0 | const static uint8_t status_request = 5; |
918 | 0 | const static uint8_t status_request_bytes[] = { status_request }; |
919 | 0 |
|
920 | 0 | Reader input(*requiredTLSFeatures); |
921 | 0 | return der::NestedOf(input, der::SEQUENCE, der::INTEGER, |
922 | 0 | der::EmptyAllowed::No, [&](Reader& r) { |
923 | 0 | if (!r.MatchRest(status_request_bytes)) { |
924 | 0 | return Result::ERROR_REQUIRED_TLS_FEATURE_MISSING; |
925 | 0 | } |
926 | 0 | |
927 | 0 | if (!stapledOCSPResponse) { |
928 | 0 | return Result::ERROR_REQUIRED_TLS_FEATURE_MISSING; |
929 | 0 | } |
930 | 0 | |
931 | 0 | return Result::Success; |
932 | 0 | }); |
933 | 0 | } |
934 | | |
935 | | Result |
936 | | CheckTLSFeaturesAreSatisfied(Input& cert, |
937 | | const Input* stapledOCSPResponse) |
938 | 0 | { |
939 | 0 | BackCert backCert(cert, EndEntityOrCA::MustBeEndEntity, nullptr); |
940 | 0 | Result rv = backCert.Init(); |
941 | 0 | if (rv != Success) { |
942 | 0 | return rv; |
943 | 0 | } |
944 | 0 | |
945 | 0 | return TLSFeaturesSatisfiedInternal(backCert.GetRequiredTLSFeatures(), |
946 | 0 | stapledOCSPResponse); |
947 | 0 | } |
948 | | |
949 | | Result |
950 | | CheckIssuerIndependentProperties(TrustDomain& trustDomain, |
951 | | const BackCert& cert, |
952 | | Time time, |
953 | | KeyUsage requiredKeyUsageIfPresent, |
954 | | KeyPurposeId requiredEKUIfPresent, |
955 | | const CertPolicyId& requiredPolicy, |
956 | | unsigned int subCACount, |
957 | | /*out*/ TrustLevel& trustLevel) |
958 | 0 | { |
959 | 0 | Result rv; |
960 | 0 |
|
961 | 0 | const EndEntityOrCA endEntityOrCA = cert.endEntityOrCA; |
962 | 0 |
|
963 | 0 | // Check the cert's trust first, because we want to minimize the amount of |
964 | 0 | // processing we do on a distrusted cert, in case it is trying to exploit |
965 | 0 | // some bug in our processing. |
966 | 0 | rv = trustDomain.GetCertTrust(endEntityOrCA, requiredPolicy, cert.GetDER(), |
967 | 0 | trustLevel); |
968 | 0 | if (rv != Success) { |
969 | 0 | return rv; |
970 | 0 | } |
971 | 0 | |
972 | 0 | // IMPORTANT: We parse the validity interval here, so that we can use the |
973 | 0 | // notBefore and notAfter values in checks for things that might be deprecated |
974 | 0 | // over time. However, we must not fail for semantic errors until the end of |
975 | 0 | // this method, in order to preserve error ranking. |
976 | 0 | Time notBefore(Time::uninitialized); |
977 | 0 | Time notAfter(Time::uninitialized); |
978 | 0 | rv = ParseValidity(cert.GetValidity(), ¬Before, ¬After); |
979 | 0 | if (rv != Success) { |
980 | 0 | return rv; |
981 | 0 | } |
982 | 0 | |
983 | 0 | if (trustLevel == TrustLevel::TrustAnchor && |
984 | 0 | endEntityOrCA == EndEntityOrCA::MustBeEndEntity && |
985 | 0 | requiredEKUIfPresent == KeyPurposeId::id_kp_OCSPSigning) { |
986 | 0 | // OCSP signer certificates can never be trust anchors, especially |
987 | 0 | // since we don't support designated OCSP responders. All of the checks |
988 | 0 | // below that are dependent on trustLevel rely on this overriding of the |
989 | 0 | // trust level for OCSP signers. |
990 | 0 | trustLevel = TrustLevel::InheritsTrust; |
991 | 0 | } |
992 | 0 |
|
993 | 0 | switch (trustLevel) { |
994 | 0 | case TrustLevel::InheritsTrust: |
995 | 0 | rv = CheckSignatureAlgorithm(trustDomain, endEntityOrCA, notBefore, |
996 | 0 | cert.GetSignedData(), cert.GetSignature()); |
997 | 0 | if (rv != Success) { |
998 | 0 | return rv; |
999 | 0 | } |
1000 | 0 | break; |
1001 | 0 |
|
1002 | 0 | case TrustLevel::TrustAnchor: |
1003 | 0 | // We don't even bother checking signatureAlgorithm or signature for |
1004 | 0 | // syntactic validity for trust anchors, because we don't use those |
1005 | 0 | // fields for anything, and because the trust anchor might be signed |
1006 | 0 | // with a signature algorithm we don't actually support. |
1007 | 0 | break; |
1008 | 0 |
|
1009 | 0 | case TrustLevel::ActivelyDistrusted: |
1010 | 0 | return Result::ERROR_UNTRUSTED_CERT; |
1011 | 0 | } |
1012 | 0 | |
1013 | 0 | // Check the SPKI early, because it is one of the most selective properties |
1014 | 0 | // of the certificate due to SHA-1 deprecation and the deprecation of |
1015 | 0 | // certificates with keys weaker than RSA 2048. |
1016 | 0 | rv = CheckSubjectPublicKeyInfo(cert.GetSubjectPublicKeyInfo(), trustDomain, |
1017 | 0 | endEntityOrCA); |
1018 | 0 | if (rv != Success) { |
1019 | 0 | return rv; |
1020 | 0 | } |
1021 | 0 | |
1022 | 0 | // 4.1.2.4. Issuer |
1023 | 0 | rv = CheckIssuer(cert.GetIssuer()); |
1024 | 0 | if (rv != Success) { |
1025 | 0 | return rv; |
1026 | 0 | } |
1027 | 0 | |
1028 | 0 | // 4.2.1.1. Authority Key Identifier is ignored (see bug 965136). |
1029 | 0 | |
1030 | 0 | // 4.2.1.2. Subject Key Identifier is ignored (see bug 965136). |
1031 | 0 | |
1032 | 0 | // 4.2.1.3. Key Usage |
1033 | 0 | rv = CheckKeyUsage(endEntityOrCA, cert.GetKeyUsage(), |
1034 | 0 | requiredKeyUsageIfPresent); |
1035 | 0 | if (rv != Success) { |
1036 | 0 | return rv; |
1037 | 0 | } |
1038 | 0 | |
1039 | 0 | // 4.2.1.4. Certificate Policies |
1040 | 0 | rv = CheckCertificatePolicies(endEntityOrCA, cert.GetCertificatePolicies(), |
1041 | 0 | cert.GetInhibitAnyPolicy(), trustLevel, |
1042 | 0 | requiredPolicy); |
1043 | 0 | if (rv != Success) { |
1044 | 0 | return rv; |
1045 | 0 | } |
1046 | 0 | |
1047 | 0 | // 4.2.1.5. Policy Mappings are not supported; see the documentation about |
1048 | 0 | // policy enforcement in pkix.h. |
1049 | 0 | |
1050 | 0 | // 4.2.1.6. Subject Alternative Name dealt with during name constraint |
1051 | 0 | // checking and during name verification (CERT_VerifyCertName). |
1052 | 0 | |
1053 | 0 | // 4.2.1.7. Issuer Alternative Name is not something that needs checking. |
1054 | 0 | |
1055 | 0 | // 4.2.1.8. Subject Directory Attributes is not something that needs |
1056 | 0 | // checking. |
1057 | 0 | |
1058 | 0 | // 4.2.1.9. Basic Constraints. |
1059 | 0 | rv = CheckBasicConstraints(endEntityOrCA, cert.GetBasicConstraints(), |
1060 | 0 | cert.GetVersion(), trustLevel, subCACount); |
1061 | 0 | if (rv != Success) { |
1062 | 0 | return rv; |
1063 | 0 | } |
1064 | 0 | |
1065 | 0 | // 4.2.1.10. Name Constraints is dealt with in during path building. |
1066 | 0 | |
1067 | 0 | // 4.2.1.11. Policy Constraints are implicitly supported; see the |
1068 | 0 | // documentation about policy enforcement in pkix.h. |
1069 | 0 | |
1070 | 0 | // 4.2.1.12. Extended Key Usage |
1071 | 0 | rv = CheckExtendedKeyUsage(endEntityOrCA, cert.GetExtKeyUsage(), |
1072 | 0 | requiredEKUIfPresent, trustDomain, notBefore); |
1073 | 0 | if (rv != Success) { |
1074 | 0 | return rv; |
1075 | 0 | } |
1076 | 0 | |
1077 | 0 | // 4.2.1.13. CRL Distribution Points is not supported, though the |
1078 | 0 | // TrustDomain's CheckRevocation method may parse it and process it |
1079 | 0 | // on its own. |
1080 | 0 | |
1081 | 0 | // 4.2.1.14. Inhibit anyPolicy is implicitly supported; see the documentation |
1082 | 0 | // about policy enforcement in pkix.h. |
1083 | 0 | |
1084 | 0 | // IMPORTANT: Even though we parse validity above, we wait until this point to |
1085 | 0 | // check it, so that error ranking works correctly. |
1086 | 0 | rv = CheckValidity(time, notBefore, notAfter); |
1087 | 0 | if (rv != Success) { |
1088 | 0 | return rv; |
1089 | 0 | } |
1090 | 0 | |
1091 | 0 | rv = trustDomain.CheckValidityIsAcceptable(notBefore, notAfter, endEntityOrCA, |
1092 | 0 | requiredEKUIfPresent); |
1093 | 0 | if (rv != Success) { |
1094 | 0 | return rv; |
1095 | 0 | } |
1096 | 0 | |
1097 | 0 | return Success; |
1098 | 0 | } |
1099 | | |
1100 | | } } // namespace mozilla::pkix |