security/pkix/lib/pkixcheck.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:ae849b51e9ac
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 /* Copyright 2013 Mozilla Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <limits>
19
20 #include "pkix/pkix.h"
21 #include "pkixcheck.h"
22 #include "pkixder.h"
23 #include "pkixutil.h"
24 #include "secder.h"
25
26 namespace mozilla { namespace pkix {
27
28 Result
29 CheckTimes(const CERTCertificate* cert, PRTime time)
30 {
31 PR_ASSERT(cert);
32
33 SECCertTimeValidity validity = CERT_CheckCertValidTimes(cert, time, false);
34 if (validity != secCertTimeValid) {
35 return Fail(RecoverableError, SEC_ERROR_EXPIRED_CERTIFICATE);
36 }
37
38 return Success;
39 }
40
41 // 4.2.1.3. Key Usage (id-ce-keyUsage)
42
43 // As explained in the comment in CheckKeyUsage, bit 0 is the most significant
44 // bit and bit 7 is the least significant bit.
45 inline uint8_t KeyUsageToBitMask(KeyUsage keyUsage)
46 {
47 PR_ASSERT(keyUsage != KeyUsage::noParticularKeyUsageRequired);
48 return 0x80u >> static_cast<uint8_t>(keyUsage);
49 }
50
51 Result
52 CheckKeyUsage(EndEntityOrCA endEntityOrCA, const SECItem* encodedKeyUsage,
53 KeyUsage requiredKeyUsageIfPresent)
54 {
55 if (!encodedKeyUsage) {
56 // TODO(bug 970196): Reject certificates that are being used to verify
57 // certificate signatures unless the certificate is a trust anchor, to
58 // reduce the chances of an end-entity certificate being abused as a CA
59 // certificate.
60 // if (endEntityOrCA == EndEntityOrCA::MustBeCA && !isTrustAnchor) {
61 // return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
62 // }
63 //
64 // TODO: Users may configure arbitrary certificates as trust anchors, not
65 // just roots. We should only allow a certificate without a key usage to be
66 // used as a CA when it is self-issued and self-signed.
67 return Success;
68 }
69
70 der::Input input;
71 if (input.Init(encodedKeyUsage->data, encodedKeyUsage->len) != der::Success) {
72 return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
73 }
74 der::Input value;
75 if (der::ExpectTagAndGetValue(input, der::BIT_STRING, value) != der::Success) {
76 return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
77 }
78
79 uint8_t numberOfPaddingBits;
80 if (value.Read(numberOfPaddingBits) != der::Success) {
81 return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
82 }
83 if (numberOfPaddingBits > 7) {
84 return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
85 }
86
87 uint8_t bits;
88 if (value.Read(bits) != der::Success) {
89 // Reject empty bit masks.
90 return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
91 }
92
93 // The most significant bit is numbered 0 (digitalSignature) and the least
94 // significant bit is numbered 7 (encipherOnly), and the padding is in the
95 // least significant bits of the last byte. The numbering of bits in a byte
96 // is backwards from how we usually interpret them.
97 //
98 // For example, let's say bits is encoded in one byte with of value 0xB0 and
99 // numberOfPaddingBits == 4. Then, bits is 10110000 in binary:
100 //
101 // bit 0 bit 3
102 // | |
103 // v v
104 // 10110000
105 // ^^^^
106 // |
107 // 4 padding bits
108 //
109 // Since bits is the last byte, we have to consider the padding by ensuring
110 // that the least significant 4 bits are all zero, since DER rules require
111 // all padding bits to be zero. Then we have to look at the bit N bits to the
112 // right of the most significant bit, where N is a value from the KeyUsage
113 // enumeration.
114 //
115 // Let's say we're interested in the keyCertSign (5) bit. We'd need to look
116 // at bit 5, which is zero, so keyCertSign is not asserted. (Since we check
117 // that the padding is all zeros, it is OK to read from the padding bits.)
118 //
119 // Let's say we're interested in the digitalSignature (0) bit. We'd need to
120 // look at the bit 0 (the most significant bit), which is set, so that means
121 // digitalSignature is asserted. Similarly, keyEncipherment (2) and
122 // dataEncipherment (3) are asserted.
123 //
124 // Note that since the KeyUsage enumeration is limited to values 0-7, we
125 // only ever need to examine the first byte test for
126 // requiredKeyUsageIfPresent.
127
128 if (requiredKeyUsageIfPresent != KeyUsage::noParticularKeyUsageRequired) {
129 // Check that the required key usage bit is set.
130 if ((bits & KeyUsageToBitMask(requiredKeyUsageIfPresent)) == 0) {
131 return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
132 }
133 }
134
135 if (endEntityOrCA != EndEntityOrCA::MustBeCA) {
136 // RFC 5280 says "The keyCertSign bit is asserted when the subject public
137 // key is used for verifying signatures on public key certificates. If the
138 // keyCertSign bit is asserted, then the cA bit in the basic constraints
139 // extension (Section 4.2.1.9) MUST also be asserted."
140 if ((bits & KeyUsageToBitMask(KeyUsage::keyCertSign)) != 0) {
141 return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
142 }
143 }
144
145 // The padding applies to the last byte, so skip to the last byte.
146 while (!value.AtEnd()) {
147 if (value.Read(bits) != der::Success) {
148 return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
149 }
150 }
151
152 // All of the padding bits must be zero, according to DER rules.
153 uint8_t paddingMask = static_cast<uint8_t>((1 << numberOfPaddingBits) - 1);
154 if ((bits & paddingMask) != 0) {
155 return Fail(RecoverableError, SEC_ERROR_INADEQUATE_KEY_USAGE);
156 }
157
158 return Success;
159 }
160
161 // RFC5820 4.2.1.4. Certificate Policies
162 //
163 // "The user-initial-policy-set contains the special value any-policy if the
164 // user is not concerned about certificate policy."
165 Result
166 CheckCertificatePolicies(BackCert& cert, EndEntityOrCA endEntityOrCA,
167 bool isTrustAnchor, SECOidTag requiredPolicy)
168 {
169 if (requiredPolicy == SEC_OID_X509_ANY_POLICY) {
170 return Success;
171 }
172
173 // It is likely some callers will pass SEC_OID_UNKNOWN when they don't care,
174 // instead of passing SEC_OID_X509_ANY_POLICY. Help them out by failing hard.
175 if (requiredPolicy == SEC_OID_UNKNOWN) {
176 PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
177 return FatalError;
178 }
179
180 // Bug 989051. Until we handle inhibitAnyPolicy we will fail close when
181 // inhibitAnyPolicy extension is present and we need to evaluate certificate
182 // policies.
183 if (cert.encodedInhibitAnyPolicy) {
184 PR_SetError(SEC_ERROR_POLICY_VALIDATION_FAILED, 0);
185 return RecoverableError;
186 }
187
188 // The root CA certificate may omit the policies that it has been
189 // trusted for, so we cannot require the policies to be present in those
190 // certificates. Instead, the determination of which roots are trusted for
191 // which policies is made by the TrustDomain's GetCertTrust method.
192 if (isTrustAnchor && endEntityOrCA == MustBeCA) {
193 return Success;
194 }
195
196 if (!cert.encodedCertificatePolicies) {
197 PR_SetError(SEC_ERROR_POLICY_VALIDATION_FAILED, 0);
198 return RecoverableError;
199 }
200
201 ScopedPtr<CERTCertificatePolicies, CERT_DestroyCertificatePoliciesExtension>
202 policies(CERT_DecodeCertificatePoliciesExtension(
203 cert.encodedCertificatePolicies));
204 if (!policies) {
205 return MapSECStatus(SECFailure);
206 }
207
208 for (const CERTPolicyInfo* const* policyInfos = policies->policyInfos;
209 *policyInfos; ++policyInfos) {
210 if ((*policyInfos)->oid == requiredPolicy) {
211 return Success;
212 }
213 // Intermediate certs are allowed to have the anyPolicy OID
214 if (endEntityOrCA == MustBeCA &&
215 (*policyInfos)->oid == SEC_OID_X509_ANY_POLICY) {
216 return Success;
217 }
218 }
219
220 PR_SetError(SEC_ERROR_POLICY_VALIDATION_FAILED, 0);
221 return RecoverableError;
222 }
223
224 // BasicConstraints ::= SEQUENCE {
225 // cA BOOLEAN DEFAULT FALSE,
226 // pathLenConstraint INTEGER (0..MAX) OPTIONAL }
227 der::Result
228 DecodeBasicConstraints(const SECItem* encodedBasicConstraints,
229 CERTBasicConstraints& basicConstraints)
230 {
231 PR_ASSERT(encodedBasicConstraints);
232 if (!encodedBasicConstraints) {
233 return der::Fail(SEC_ERROR_INVALID_ARGS);
234 }
235
236 basicConstraints.isCA = false;
237 basicConstraints.pathLenConstraint = 0;
238
239 der::Input input;
240 if (input.Init(encodedBasicConstraints->data, encodedBasicConstraints->len)
241 != der::Success) {
242 return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
243 }
244
245 if (der::ExpectTagAndIgnoreLength(input, der::SEQUENCE) != der::Success) {
246 return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
247 }
248
249 bool isCA = false;
250 // TODO(bug 989518): cA is by default false. According to DER, default
251 // values must not be explicitly encoded in a SEQUENCE. So, if this
252 // value is present and false, it is an encoding error. However, Go Daddy
253 // has issued many certificates with this improper encoding, so we can't
254 // enforce this yet (hence passing true for allowInvalidExplicitEncoding
255 // to der::OptionalBoolean).
256 if (der::OptionalBoolean(input, true, isCA) != der::Success) {
257 return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
258 }
259 basicConstraints.isCA = isCA;
260
261 if (input.Peek(der::INTEGER)) {
262 SECItem pathLenConstraintEncoded;
263 if (der::Integer(input, pathLenConstraintEncoded) != der::Success) {
264 return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
265 }
266 long pathLenConstraint = DER_GetInteger(&pathLenConstraintEncoded);
267 if (pathLenConstraint >= std::numeric_limits<int>::max() ||
268 pathLenConstraint < 0) {
269 return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
270 }
271 basicConstraints.pathLenConstraint = static_cast<int>(pathLenConstraint);
272 // TODO(bug 985025): If isCA is false, pathLenConstraint MUST NOT
273 // be included (as per RFC 5280 section 4.2.1.9), but for compatibility
274 // reasons, we don't check this for now.
275 } else if (basicConstraints.isCA) {
276 // If this is a CA but the path length is omitted, it is unlimited.
277 basicConstraints.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
278 }
279
280 if (der::End(input) != der::Success) {
281 return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
282 }
283 return der::Success;
284 }
285
286 // RFC5280 4.2.1.9. Basic Constraints (id-ce-basicConstraints)
287 Result
288 CheckBasicConstraints(const BackCert& cert,
289 EndEntityOrCA endEntityOrCA,
290 bool isTrustAnchor,
291 unsigned int subCACount)
292 {
293 CERTBasicConstraints basicConstraints;
294 if (cert.encodedBasicConstraints) {
295 if (DecodeBasicConstraints(cert.encodedBasicConstraints,
296 basicConstraints) != der::Success) {
297 return RecoverableError;
298 }
299 } else {
300 // Synthesize a non-CA basic constraints by default
301 basicConstraints.isCA = false;
302 basicConstraints.pathLenConstraint = 0;
303
304 // "If the basic constraints extension is not present in a version 3
305 // certificate, or the extension is present but the cA boolean is not
306 // asserted, then the certified public key MUST NOT be used to verify
307 // certificate signatures."
308 //
309 // For compatibility, we must accept v1 trust anchors without basic
310 // constraints as CAs.
311 //
312 // TODO: add check for self-signedness?
313 if (endEntityOrCA == MustBeCA && isTrustAnchor) {
314 const CERTCertificate* nssCert = cert.GetNSSCert();
315 // We only allow trust anchor CA certs to omit the
316 // basicConstraints extension if they are v1. v1 is encoded
317 // implicitly.
318 if (!nssCert->version.data && !nssCert->version.len) {
319 basicConstraints.isCA = true;
320 basicConstraints.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
321 }
322 }
323 }
324
325 if (endEntityOrCA == MustBeEndEntity) {
326 // CA certificates are not trusted as EE certs.
327
328 if (basicConstraints.isCA) {
329 // XXX: We use SEC_ERROR_CA_CERT_INVALID here so we can distinguish
330 // this error from other errors, given that NSS does not have a "CA cert
331 // used as end-entity" error code since it doesn't have such a
332 // prohibition. We should add such an error code and stop abusing
333 // SEC_ERROR_CA_CERT_INVALID this way.
334 //
335 // Note, in particular, that this check prevents a delegated OCSP
336 // response signing certificate with the CA bit from successfully
337 // validating when we check it from pkixocsp.cpp, which is a good thing.
338 //
339 return Fail(RecoverableError, SEC_ERROR_CA_CERT_INVALID);
340 }
341
342 return Success;
343 }
344
345 PORT_Assert(endEntityOrCA == MustBeCA);
346
347 // End-entity certificates are not allowed to act as CA certs.
348 if (!basicConstraints.isCA) {
349 return Fail(RecoverableError, SEC_ERROR_CA_CERT_INVALID);
350 }
351
352 if (basicConstraints.pathLenConstraint >= 0) {
353 if (subCACount >
354 static_cast<unsigned int>(basicConstraints.pathLenConstraint)) {
355 return Fail(RecoverableError, SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID);
356 }
357 }
358
359 return Success;
360 }
361
362 Result
363 BackCert::GetConstrainedNames(/*out*/ const CERTGeneralName** result)
364 {
365 if (!constrainedNames) {
366 if (!GetArena()) {
367 return FatalError;
368 }
369
370 constrainedNames =
371 CERT_GetConstrainedCertificateNames(nssCert, arena.get(),
372 cnOptions == IncludeCN);
373 if (!constrainedNames) {
374 return MapSECStatus(SECFailure);
375 }
376 }
377
378 *result = constrainedNames;
379 return Success;
380 }
381
382 // 4.2.1.10. Name Constraints
383 Result
384 CheckNameConstraints(BackCert& cert)
385 {
386 static const char constraintFranceGov[] =
387 "\x30\x5D" /* sequence len 93*/
388 "\xA0\x5B" /* element len 91 */
389 "\x30\x05" /* sequence len 5 */
390 "\x82\x03" /* entry len 3 */
391 ".fr"
392 "\x30\x05\x82\x03" /* sequence len 5, entry len 3 */
393 ".gp"
394 "\x30\x05\x82\x03"
395 ".gf"
396 "\x30\x05\x82\x03"
397 ".mq"
398 "\x30\x05\x82\x03"
399 ".re"
400 "\x30\x05\x82\x03"
401 ".yt"
402 "\x30\x05\x82\x03"
403 ".pm"
404 "\x30\x05\x82\x03"
405 ".bl"
406 "\x30\x05\x82\x03"
407 ".mf"
408 "\x30\x05\x82\x03"
409 ".wf"
410 "\x30\x05\x82\x03"
411 ".pf"
412 "\x30\x05\x82\x03"
413 ".nc"
414 "\x30\x05\x82\x03"
415 ".tf";
416
417 /* The stringified value for the subject is:
418 E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
419 */
420 static const char rawANSSISubject[] =
421 "\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04"
422 "\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03"
423 "\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65"
424 "\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05"
425 "\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03"
426 "\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44"
427 "\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13"
428 "\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06"
429 "\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41"
430 "\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7"
431 "\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40"
432 "\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75"
433 "\x76\x2E\x66\x72";
434
435 const SECItem ANSSI_SUBJECT = {
436 siBuffer,
437 reinterpret_cast<uint8_t *>(const_cast<char *>(rawANSSISubject)),
438 sizeof(rawANSSISubject) - 1
439 };
440
441 const SECItem PERMIT_FRANCE_GOV_NC = {
442 siBuffer,
443 reinterpret_cast<uint8_t *>(const_cast<char *>(constraintFranceGov)),
444 sizeof(constraintFranceGov) - 1
445 };
446
447 const SECItem* nameConstraintsToUse = cert.encodedNameConstraints;
448
449 if (!nameConstraintsToUse) {
450 if (SECITEM_ItemsAreEqual(&cert.GetNSSCert()->derSubject, &ANSSI_SUBJECT)) {
451 nameConstraintsToUse = &PERMIT_FRANCE_GOV_NC;
452 } else {
453 return Success;
454 }
455 }
456
457 PLArenaPool* arena = cert.GetArena();
458 if (!arena) {
459 return FatalError;
460 }
461
462 // Owned by arena
463 const CERTNameConstraints* constraints =
464 CERT_DecodeNameConstraintsExtension(arena, nameConstraintsToUse);
465 if (!constraints) {
466 return MapSECStatus(SECFailure);
467 }
468
469 for (BackCert* prev = cert.childCert; prev; prev = prev->childCert) {
470 const CERTGeneralName* names = nullptr;
471 Result rv = prev->GetConstrainedNames(&names);
472 if (rv != Success) {
473 return rv;
474 }
475 PORT_Assert(names);
476 CERTGeneralName* currentName = const_cast<CERTGeneralName*>(names);
477 do {
478 if (CERT_CheckNameSpace(arena, constraints, currentName) != SECSuccess) {
479 // XXX: It seems like CERT_CheckNameSpace doesn't always call
480 // PR_SetError when it fails. We set the error code here, though this
481 // may be papering over some fatal errors. NSS's
482 // cert_VerifyCertChainOld does something similar.
483 PR_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE, 0);
484 return RecoverableError;
485 }
486 currentName = CERT_GetNextGeneralName(currentName);
487 } while (currentName != names);
488 }
489
490 return Success;
491 }
492
493 // 4.2.1.12. Extended Key Usage (id-ce-extKeyUsage)
494 // 4.2.1.12. Extended Key Usage (id-ce-extKeyUsage)
495 Result
496 CheckExtendedKeyUsage(EndEntityOrCA endEntityOrCA, const SECItem* encodedEKUs,
497 SECOidTag requiredEKU)
498 {
499 // TODO: Either do not allow anyExtendedKeyUsage to be passed as requiredEKU,
500 // or require that callers pass anyExtendedKeyUsage instead of
501 // SEC_OID_UNKNWON and disallow SEC_OID_UNKNWON.
502
503 // XXX: We're using SEC_ERROR_INADEQUATE_CERT_TYPE here so that callers can
504 // distinguish EKU mismatch from KU mismatch from basic constraints mismatch.
505 // We should probably add a new error code that is more clear for this type
506 // of problem.
507
508 bool foundOCSPSigning = false;
509
510 if (encodedEKUs) {
511 ScopedPtr<CERTOidSequence, CERT_DestroyOidSequence>
512 seq(CERT_DecodeOidSequence(encodedEKUs));
513 if (!seq) {
514 PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0);
515 return RecoverableError;
516 }
517
518 bool found = false;
519
520 // XXX: We allow duplicate entries.
521 for (const SECItem* const* oids = seq->oids; oids && *oids; ++oids) {
522 SECOidTag oidTag = SECOID_FindOIDTag(*oids);
523 if (requiredEKU != SEC_OID_UNKNOWN && oidTag == requiredEKU) {
524 found = true;
525 } else {
526 // Treat CA certs with step-up OID as also having SSL server type.
527 // COMODO has issued certificates that require this behavior
528 // that don't expire until June 2020!
529 // TODO 982932: Limit this expection to old certificates
530 if (endEntityOrCA == MustBeCA &&
531 requiredEKU == SEC_OID_EXT_KEY_USAGE_SERVER_AUTH &&
532 oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) {
533 found = true;
534 }
535 }
536 if (oidTag == SEC_OID_OCSP_RESPONDER) {
537 foundOCSPSigning = true;
538 }
539 }
540
541 // If the EKU extension was included, then the required EKU must be in the
542 // list.
543 if (!found) {
544 PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0);
545 return RecoverableError;
546 }
547 }
548
549 // pkixocsp.cpp depends on the following additional checks.
550
551 if (endEntityOrCA == MustBeEndEntity) {
552 // When validating anything other than an delegated OCSP signing cert,
553 // reject any cert that also claims to be an OCSP responder, because such
554 // a cert does not make sense. For example, if an SSL certificate were to
555 // assert id-kp-OCSPSigning then it could sign OCSP responses for itself,
556 // if not for this check.
557 // That said, we accept CA certificates with id-kp-OCSPSigning because
558 // some CAs in Mozilla's CA program have issued such intermediate
559 // certificates, and because some CAs have reported some Microsoft server
560 // software wrongly requires CA certificates to have id-kp-OCSPSigning.
561 // Allowing this exception does not cause any security issues because we
562 // require delegated OCSP response signing certificates to be end-entity
563 // certificates.
564 if (foundOCSPSigning && requiredEKU != SEC_OID_OCSP_RESPONDER) {
565 PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0);
566 return RecoverableError;
567 }
568 // http://tools.ietf.org/html/rfc6960#section-4.2.2.2:
569 // "OCSP signing delegation SHALL be designated by the inclusion of
570 // id-kp-OCSPSigning in an extended key usage certificate extension
571 // included in the OCSP response signer's certificate."
572 //
573 // id-kp-OCSPSigning is the only EKU that isn't implicitly assumed when the
574 // EKU extension is missing from an end-entity certificate. However, any CA
575 // certificate can issue a delegated OCSP response signing certificate, so
576 // we can't require the EKU be explicitly included for CA certificates.
577 if (!foundOCSPSigning && requiredEKU == SEC_OID_OCSP_RESPONDER) {
578 PR_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE, 0);
579 return RecoverableError;
580 }
581 }
582
583 return Success;
584 }
585
586 Result
587 CheckIssuerIndependentProperties(TrustDomain& trustDomain,
588 BackCert& cert,
589 PRTime time,
590 EndEntityOrCA endEntityOrCA,
591 KeyUsage requiredKeyUsageIfPresent,
592 SECOidTag requiredEKUIfPresent,
593 SECOidTag requiredPolicy,
594 unsigned int subCACount,
595 /*optional out*/ TrustDomain::TrustLevel* trustLevelOut)
596 {
597 Result rv;
598
599 TrustDomain::TrustLevel trustLevel;
600 rv = MapSECStatus(trustDomain.GetCertTrust(endEntityOrCA,
601 requiredPolicy,
602 cert.GetNSSCert(),
603 &trustLevel));
604 if (rv != Success) {
605 return rv;
606 }
607 if (trustLevel == TrustDomain::ActivelyDistrusted) {
608 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
609 return RecoverableError;
610 }
611 if (trustLevel != TrustDomain::TrustAnchor &&
612 trustLevel != TrustDomain::InheritsTrust) {
613 // The TrustDomain returned a trust level that we weren't expecting.
614 PORT_SetError(PR_INVALID_STATE_ERROR);
615 return FatalError;
616 }
617 if (trustLevelOut) {
618 *trustLevelOut = trustLevel;
619 }
620
621 bool isTrustAnchor = endEntityOrCA == MustBeCA &&
622 trustLevel == TrustDomain::TrustAnchor;
623
624 PLArenaPool* arena = cert.GetArena();
625 if (!arena) {
626 return FatalError;
627 }
628
629 // 4.2.1.1. Authority Key Identifier is ignored (see bug 965136).
630
631 // 4.2.1.2. Subject Key Identifier is ignored (see bug 965136).
632
633 // 4.2.1.3. Key Usage
634 rv = CheckKeyUsage(endEntityOrCA, cert.encodedKeyUsage,
635 requiredKeyUsageIfPresent);
636 if (rv != Success) {
637 return rv;
638 }
639
640 // 4.2.1.4. Certificate Policies
641 rv = CheckCertificatePolicies(cert, endEntityOrCA, isTrustAnchor,
642 requiredPolicy);
643 if (rv != Success) {
644 return rv;
645 }
646
647 // 4.2.1.5. Policy Mappings are not supported; see the documentation about
648 // policy enforcement in pkix.h.
649
650 // 4.2.1.6. Subject Alternative Name dealt with during name constraint
651 // checking and during name verification (CERT_VerifyCertName).
652
653 // 4.2.1.7. Issuer Alternative Name is not something that needs checking.
654
655 // 4.2.1.8. Subject Directory Attributes is not something that needs
656 // checking.
657
658 // 4.2.1.9. Basic Constraints.
659 rv = CheckBasicConstraints(cert, endEntityOrCA, isTrustAnchor, subCACount);
660 if (rv != Success) {
661 return rv;
662 }
663
664 // 4.2.1.10. Name Constraints is dealt with in during path building.
665
666 // 4.2.1.11. Policy Constraints are implicitly supported; see the
667 // documentation about policy enforcement in pkix.h.
668
669 // 4.2.1.12. Extended Key Usage
670 rv = CheckExtendedKeyUsage(endEntityOrCA, cert.encodedExtendedKeyUsage,
671 requiredEKUIfPresent);
672 if (rv != Success) {
673 return rv;
674 }
675
676 // 4.2.1.13. CRL Distribution Points is not supported, though the
677 // TrustDomain's CheckRevocation method may parse it and process it
678 // on its own.
679
680 // 4.2.1.14. Inhibit anyPolicy is implicitly supported; see the documentation
681 // about policy enforcement in pkix.h.
682
683 // IMPORTANT: This check must come after the other checks in order for error
684 // ranking to work correctly.
685 rv = CheckTimes(cert.GetNSSCert(), time);
686 if (rv != Success) {
687 return rv;
688 }
689
690 return Success;
691 }
692
693 } } // namespace mozilla::pkix

mercurial