security/pkix/lib/pkixcheck.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     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  */
    18 #include <limits>
    20 #include "pkix/pkix.h"
    21 #include "pkixcheck.h"
    22 #include "pkixder.h"
    23 #include "pkixutil.h"
    24 #include "secder.h"
    26 namespace mozilla { namespace pkix {
    28 Result
    29 CheckTimes(const CERTCertificate* cert, PRTime time)
    30 {
    31   PR_ASSERT(cert);
    33   SECCertTimeValidity validity = CERT_CheckCertValidTimes(cert, time, false);
    34   if (validity != secCertTimeValid) {
    35     return Fail(RecoverableError, SEC_ERROR_EXPIRED_CERTIFICATE);
    36   }
    38   return Success;
    39 }
    41 // 4.2.1.3. Key Usage (id-ce-keyUsage)
    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 }
    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   }
    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   }
    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   }
    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   }
    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.
   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   }
   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   }
   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   }
   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   }
   158   return Success;
   159 }
   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   }
   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   }
   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   }
   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   }
   196   if (!cert.encodedCertificatePolicies) {
   197     PR_SetError(SEC_ERROR_POLICY_VALIDATION_FAILED, 0);
   198     return RecoverableError;
   199   }
   201   ScopedPtr<CERTCertificatePolicies, CERT_DestroyCertificatePoliciesExtension>
   202     policies(CERT_DecodeCertificatePoliciesExtension(
   203                 cert.encodedCertificatePolicies));
   204   if (!policies) {
   205     return MapSECStatus(SECFailure);
   206   }
   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   }
   220   PR_SetError(SEC_ERROR_POLICY_VALIDATION_FAILED, 0);
   221   return RecoverableError;
   222 }
   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   }
   236   basicConstraints.isCA = false;
   237   basicConstraints.pathLenConstraint = 0;
   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   }
   245   if (der::ExpectTagAndIgnoreLength(input, der::SEQUENCE) != der::Success) {
   246     return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
   247   }
   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;
   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   }
   280   if (der::End(input) != der::Success) {
   281     return der::Fail(SEC_ERROR_EXTENSION_VALUE_INVALID);
   282   }
   283   return der::Success;
   284 }
   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;
   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   }
   325   if (endEntityOrCA == MustBeEndEntity) {
   326     // CA certificates are not trusted as EE certs.
   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     }
   342     return Success;
   343   }
   345   PORT_Assert(endEntityOrCA == MustBeCA);
   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   }
   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   }
   359   return Success;
   360 }
   362 Result
   363 BackCert::GetConstrainedNames(/*out*/ const CERTGeneralName** result)
   364 {
   365   if (!constrainedNames) {
   366     if (!GetArena()) {
   367       return FatalError;
   368     }
   370     constrainedNames =
   371       CERT_GetConstrainedCertificateNames(nssCert, arena.get(),
   372                                           cnOptions == IncludeCN);
   373     if (!constrainedNames) {
   374       return MapSECStatus(SECFailure);
   375     }
   376   }
   378   *result = constrainedNames;
   379   return Success;
   380 }
   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";
   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";
   435   const SECItem ANSSI_SUBJECT = {
   436     siBuffer,
   437     reinterpret_cast<uint8_t *>(const_cast<char *>(rawANSSISubject)),
   438     sizeof(rawANSSISubject) - 1
   439   };
   441   const SECItem PERMIT_FRANCE_GOV_NC = {
   442     siBuffer,
   443     reinterpret_cast<uint8_t *>(const_cast<char *>(constraintFranceGov)),
   444     sizeof(constraintFranceGov) - 1
   445   };
   447   const SECItem* nameConstraintsToUse = cert.encodedNameConstraints;
   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   }
   457   PLArenaPool* arena = cert.GetArena();
   458   if (!arena) {
   459     return FatalError;
   460   }
   462   // Owned by arena
   463   const CERTNameConstraints* constraints =
   464     CERT_DecodeNameConstraintsExtension(arena, nameConstraintsToUse);
   465   if (!constraints) {
   466     return MapSECStatus(SECFailure);
   467   }
   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   }
   490   return Success;
   491 }
   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.
   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.
   508   bool foundOCSPSigning = false;
   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     }
   518     bool found = false;
   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     }
   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   }
   549   // pkixocsp.cpp depends on the following additional checks.
   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   }
   583   return Success;
   584 }
   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;
   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   }
   621   bool isTrustAnchor = endEntityOrCA == MustBeCA &&
   622                        trustLevel == TrustDomain::TrustAnchor;
   624   PLArenaPool* arena = cert.GetArena();
   625   if (!arena) {
   626     return FatalError;
   627   }
   629   // 4.2.1.1. Authority Key Identifier is ignored (see bug 965136).
   631   // 4.2.1.2. Subject Key Identifier is ignored (see bug 965136).
   633   // 4.2.1.3. Key Usage
   634   rv = CheckKeyUsage(endEntityOrCA, cert.encodedKeyUsage,
   635                      requiredKeyUsageIfPresent);
   636   if (rv != Success) {
   637     return rv;
   638   }
   640   // 4.2.1.4. Certificate Policies
   641   rv = CheckCertificatePolicies(cert, endEntityOrCA, isTrustAnchor,
   642                                 requiredPolicy);
   643   if (rv != Success) {
   644     return rv;
   645   }
   647   // 4.2.1.5. Policy Mappings are not supported; see the documentation about
   648   //          policy enforcement in pkix.h.
   650   // 4.2.1.6. Subject Alternative Name dealt with during name constraint
   651   //          checking and during name verification (CERT_VerifyCertName).
   653   // 4.2.1.7. Issuer Alternative Name is not something that needs checking.
   655   // 4.2.1.8. Subject Directory Attributes is not something that needs
   656   //          checking.
   658   // 4.2.1.9. Basic Constraints.
   659   rv = CheckBasicConstraints(cert, endEntityOrCA, isTrustAnchor, subCACount);
   660   if (rv != Success) {
   661     return rv;
   662   }
   664   // 4.2.1.10. Name Constraints is dealt with in during path building.
   666   // 4.2.1.11. Policy Constraints are implicitly supported; see the
   667   //           documentation about policy enforcement in pkix.h.
   669   // 4.2.1.12. Extended Key Usage
   670   rv = CheckExtendedKeyUsage(endEntityOrCA, cert.encodedExtendedKeyUsage,
   671                              requiredEKUIfPresent);
   672   if (rv != Success) {
   673     return rv;
   674   }
   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.
   680   // 4.2.1.14. Inhibit anyPolicy is implicitly supported; see the documentation
   681   //           about policy enforcement in pkix.h.
   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   }
   690   return Success;
   691 }
   693 } } // namespace mozilla::pkix

mercurial