security/pkix/lib/pkixocsp.cpp

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     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/bind.h"
    21 #include "pkix/pkix.h"
    22 #include "pkixcheck.h"
    23 #include "pkixder.h"
    25 #include "hasht.h"
    26 #include "pk11pub.h"
    27 #include "secder.h"
    29 #ifdef _MSC_VER
    30 // C4480: nonstandard extension used: specifying underlying type for enum
    31 #define ENUM_CLASS  __pragma(warning(disable: 4480)) enum
    32 #else
    33 #define ENUM_CLASS enum class
    34 #endif
    36 // TODO: use typed/qualified typedefs everywhere?
    37 // TODO: When should we return SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE?
    39 namespace mozilla { namespace pkix {
    41 static const PRTime ONE_DAY
    42   = INT64_C(24) * INT64_C(60) * INT64_C(60) * PR_USEC_PER_SEC;
    43 static const PRTime SLOP = ONE_DAY;
    45 // These values correspond to the tag values in the ASN.1 CertStatus
    46 ENUM_CLASS CertStatus : uint8_t {
    47   Good = der::CONTEXT_SPECIFIC | 0,
    48   Revoked = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
    49   Unknown = der::CONTEXT_SPECIFIC | 2
    50 };
    52 class Context
    53 {
    54 public:
    55   Context(TrustDomain& trustDomain,
    56           const CERTCertificate& cert,
    57           CERTCertificate& issuerCert,
    58           PRTime time,
    59           uint16_t maxLifetimeInDays,
    60           PRTime* thisUpdate,
    61           PRTime* validThrough)
    62     : trustDomain(trustDomain)
    63     , cert(cert)
    64     , issuerCert(issuerCert)
    65     , time(time)
    66     , maxLifetimeInDays(maxLifetimeInDays)
    67     , certStatus(CertStatus::Unknown)
    68     , thisUpdate(thisUpdate)
    69     , validThrough(validThrough)
    70     , expired(false)
    71   {
    72     if (thisUpdate) {
    73       *thisUpdate = 0;
    74     }
    75     if (validThrough) {
    76       *validThrough = 0;
    77     }
    78   }
    80   TrustDomain& trustDomain;
    81   const CERTCertificate& cert;
    82   CERTCertificate& issuerCert;
    83   const PRTime time;
    84   const uint16_t maxLifetimeInDays;
    85   CertStatus certStatus;
    86   PRTime* thisUpdate;
    87   PRTime* validThrough;
    88   bool expired;
    90 private:
    91   Context(const Context&); // delete
    92   void operator=(const Context&); // delete
    93 };
    95 // Verify that potentialSigner is a valid delegated OCSP response signing cert
    96 // according to RFC 6960 section 4.2.2.2.
    97 static Result
    98 CheckOCSPResponseSignerCert(TrustDomain& trustDomain,
    99                             CERTCertificate& potentialSigner,
   100                             const CERTCertificate& issuerCert, PRTime time)
   101 {
   102   Result rv;
   104   BackCert cert(&potentialSigner, nullptr, BackCert::ExcludeCN);
   105   rv = cert.Init();
   106   if (rv != Success) {
   107     return rv;
   108   }
   110   // We don't need to do a complete verification of the signer (i.e. we don't
   111   // have to call BuildCertChain to verify the entire chain) because we
   112   // already know that the issuerCert is valid, since revocation checking is
   113   // done from the root to the parent after we've built a complete chain that
   114   // we know is otherwise valid. Rather, we just need to do a one-step
   115   // validation from potentialSigner to issuerCert.
   116   //
   117   // It seems reasonable to require the KU_DIGITAL_SIGNATURE key usage on the
   118   // OCSP responder certificate if the OCSP responder certificate has a
   119   // key usage extension. However, according to bug 240456, some OCSP responder
   120   // certificates may have only the nonRepudiation bit set. Also, the OCSP
   121   // specification (RFC 6960) does not mandate any particular key usage to be
   122   // asserted for OCSP responde signers. Oddly, the CABForum Baseline
   123   // Requirements v.1.1.5 do say "If the Root CA Private Key is used for
   124   // signing OCSP responses, then the digitalSignature bit MUST be set."
   125   //
   126   // Note that CheckIssuerIndependentProperties processes
   127   // SEC_OID_OCSP_RESPONDER in the way that the OCSP specification requires us
   128   // to--in particular, it doesn't allow SEC_OID_OCSP_RESPONDER to be implied
   129   // by a missing EKU extension, unlike other EKUs.
   130   //
   131   // TODO(bug 926261): If we're validating for a policy then the policy OID we
   132   // are validating for should be passed to CheckIssuerIndependentProperties.
   133   rv = CheckIssuerIndependentProperties(trustDomain, cert, time,
   134                                         MustBeEndEntity,
   135                                         KeyUsage::noParticularKeyUsageRequired,
   136                                         SEC_OID_OCSP_RESPONDER,
   137                                         SEC_OID_X509_ANY_POLICY, 0);
   138   if (rv != Success) {
   139     return rv;
   140   }
   142   // It is possible that there exists a certificate with the same key as the
   143   // issuer but with a different name, so we need to compare names
   144   // TODO: needs test
   145   if (!SECITEM_ItemsAreEqual(&cert.GetNSSCert()->derIssuer,
   146                              &issuerCert.derSubject) &&
   147       CERT_CompareName(&cert.GetNSSCert()->issuer,
   148                        &issuerCert.subject) != SECEqual) {
   149     return Fail(RecoverableError, SEC_ERROR_OCSP_RESPONDER_CERT_INVALID);
   150   }
   152   // TODO(bug 926260): check name constraints
   154   if (trustDomain.VerifySignedData(&potentialSigner.signatureWrap,
   155                                    &issuerCert) != SECSuccess) {
   156     return MapSECStatus(SECFailure);
   157   }
   159   // TODO: check for revocation of the OCSP responder certificate unless no-check
   160   // or the caller forcing no-check. To properly support the no-check policy, we'd
   161   // need to enforce policy constraints from the issuerChain.
   163   return Success;
   164 }
   166 //typedef enum {
   167 //    ocspResponderID_byName = 1,
   168 //    ocspResponderID_byKey = 2
   169 //} ResponderIDType;
   171 ENUM_CLASS ResponderIDType : uint8_t
   172 {
   173   byName = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
   174   byKey = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 2
   175 };
   177 static inline der::Result OCSPResponse(der::Input&, Context&);
   178 static inline der::Result ResponseBytes(der::Input&, Context&);
   179 static inline der::Result BasicResponse(der::Input&, Context&);
   180 static inline der::Result ResponseData(
   181                               der::Input& tbsResponseData, Context& context,
   182                               const CERTSignedData& signedResponseData,
   183                               /*const*/ SECItem* certs, size_t numCerts);
   184 static inline der::Result SingleResponse(der::Input& input,
   185                                           Context& context);
   186 static inline der::Result CheckExtensionsForCriticality(der::Input&);
   187 static inline der::Result CertID(der::Input& input,
   188                                   const Context& context,
   189                                   /*out*/ bool& match);
   190 static der::Result MatchIssuerKey(const SECItem& issuerKeyHash,
   191                                    const CERTCertificate& issuer,
   192                                    /*out*/ bool& match);
   194 // RFC 6960 section 4.2.2.2: The OCSP responder must either be the issuer of
   195 // the cert or it must be a delegated OCSP response signing cert directly
   196 // issued by the issuer. If the OCSP responder is a delegated OCSP response
   197 // signer, then its certificate is (probably) embedded within the OCSP
   198 // response and we'll need to verify that it is a valid certificate that chains
   199 // *directly* to issuerCert.
   200 static CERTCertificate*
   201 GetOCSPSignerCertificate(TrustDomain& trustDomain,
   202                          ResponderIDType responderIDType,
   203                          const SECItem& responderIDItem,
   204                          const SECItem* certs, size_t numCerts,
   205                          CERTCertificate& issuerCert, PRTime time)
   206 {
   207   bool isIssuer = true;
   208   size_t i = 0;
   209   for (;;) {
   210     ScopedCERTCertificate potentialSigner;
   211     if (isIssuer) {
   212       potentialSigner = CERT_DupCertificate(&issuerCert);
   213     } else if (i < numCerts) {
   214       potentialSigner = CERT_NewTempCertificate(
   215                           CERT_GetDefaultCertDB(),
   216                           /*TODO*/const_cast<SECItem*>(&certs[i]), nullptr,
   217                           false, false);
   218       if (!potentialSigner) {
   219         return nullptr;
   220       }
   221       ++i;
   222     } else {
   223       PR_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT, 0);
   224       return nullptr;
   225     }
   227     bool match;
   228     switch (responderIDType) {
   229       case ResponderIDType::byName:
   230         // The CA is very likely to have encoded the name in the OCSP response
   231         // exactly the same as the name is encoded in the signing certificate.
   232         // Consequently, most of the time we will avoid parsing the name
   233         // completely. We're assuming here that the signer's subject name is
   234         // correctly formatted.
   235         // TODO: need test for exact name
   236         // TODO: need test for non-exact name match
   237         match = SECITEM_ItemsAreEqual(&responderIDItem,
   238                                       &potentialSigner->derSubject);
   239         if (!match) {
   240           ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
   241           if (!arena) {
   242             return nullptr;
   243           }
   244           CERTName name;
   245           if (SEC_QuickDERDecodeItem(arena.get(), &name,
   246                                      SEC_ASN1_GET(CERT_NameTemplate),
   247                                      &responderIDItem) != SECSuccess) {
   248             return nullptr;
   249           }
   250           match = CERT_CompareName(&name, &potentialSigner->subject) == SECEqual;
   251         }
   252         break;
   254       case ResponderIDType::byKey:
   255       {
   256         der::Input responderID;
   257         if (responderID.Init(responderIDItem.data, responderIDItem.len)
   258               != der::Success) {
   259           return nullptr;
   260         }
   261         SECItem issuerKeyHash;
   262         if (der::Skip(responderID, der::OCTET_STRING, issuerKeyHash) != der::Success) {
   263           return nullptr;
   264         }
   265         if (MatchIssuerKey(issuerKeyHash, *potentialSigner.get(), match)
   266               != der::Success) {
   267           return nullptr;
   268         }
   269         break;
   270       }
   272       default:
   273         PR_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE, 0);
   274         return nullptr;
   275     }
   277     if (match && !isIssuer) {
   278       Result rv = CheckOCSPResponseSignerCert(trustDomain,
   279                                               *potentialSigner.get(),
   280                                               issuerCert, time);
   281       if (rv == RecoverableError) {
   282         match = false;
   283       } else if (rv != Success) {
   284         return nullptr;
   285       }
   286     }
   288     if (match) {
   289       return potentialSigner.release();
   290     }
   292     isIssuer = false;
   293   }
   294 }
   296 static SECStatus
   297 VerifySignature(Context& context, ResponderIDType responderIDType,
   298                 const SECItem& responderID, const SECItem* certs,
   299                 size_t numCerts, const CERTSignedData& signedResponseData)
   300 {
   301   ScopedCERTCertificate signer(
   302     GetOCSPSignerCertificate(context.trustDomain, responderIDType, responderID,
   303                              certs, numCerts, context.issuerCert,
   304                              context.time));
   305   if (!signer) {
   306     return SECFailure;
   307   }
   309   if (context.trustDomain.VerifySignedData(&signedResponseData, signer.get())
   310         != SECSuccess) {
   311     if (PR_GetError() == SEC_ERROR_BAD_SIGNATURE) {
   312       PR_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE, 0);
   313     }
   314     return SECFailure;
   315   }
   317   return SECSuccess;
   318 }
   320 static inline void
   321 SetErrorToMalformedResponseOnBadDERError()
   322 {
   323   if (PR_GetError() == SEC_ERROR_BAD_DER) {
   324     PR_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE, 0);
   325   }
   326 }
   328 SECStatus
   329 VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
   330                           const CERTCertificate* cert,
   331                           CERTCertificate* issuerCert, PRTime time,
   332                           uint16_t maxOCSPLifetimeInDays,
   333                           const SECItem* encodedResponse,
   334                           bool& expired,
   335                           PRTime* thisUpdate,
   336                           PRTime* validThrough)
   337 {
   338   PR_ASSERT(cert);
   339   PR_ASSERT(issuerCert);
   340   // TODO: PR_Assert(pinArg)
   341   PR_ASSERT(encodedResponse);
   342   if (!cert || !issuerCert || !encodedResponse || !encodedResponse->data) {
   343     PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
   344     return SECFailure;
   345   }
   347   // Always initialize this to something reasonable.
   348   expired = false;
   350   der::Input input;
   351   if (input.Init(encodedResponse->data, encodedResponse->len) != der::Success) {
   352     SetErrorToMalformedResponseOnBadDERError();
   353     return SECFailure;
   354   }
   355   Context context(trustDomain, *cert, *issuerCert, time, maxOCSPLifetimeInDays,
   356                   thisUpdate, validThrough);
   358   if (der::Nested(input, der::SEQUENCE,
   359                   bind(OCSPResponse, _1, ref(context))) != der::Success) {
   360     SetErrorToMalformedResponseOnBadDERError();
   361     return SECFailure;
   362   }
   364   if (der::End(input) != der::Success) {
   365     SetErrorToMalformedResponseOnBadDERError();
   366     return SECFailure;
   367   }
   369   expired = context.expired;
   371   switch (context.certStatus) {
   372     case CertStatus::Good:
   373       if (expired) {
   374         PR_SetError(SEC_ERROR_OCSP_OLD_RESPONSE, 0);
   375         return SECFailure;
   376       }
   377       return SECSuccess;
   378     case CertStatus::Revoked:
   379       PR_SetError(SEC_ERROR_REVOKED_CERTIFICATE, 0);
   380       return SECFailure;
   381     case CertStatus::Unknown:
   382       PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0);
   383       return SECFailure;
   384   }
   386   PR_NOT_REACHED("unknown CertStatus");
   387   PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0);
   388   return SECFailure;
   389 }
   391 // OCSPResponse ::= SEQUENCE {
   392 //       responseStatus         OCSPResponseStatus,
   393 //       responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
   394 //
   395 static inline der::Result
   396 OCSPResponse(der::Input& input, Context& context)
   397 {
   398   // OCSPResponseStatus ::= ENUMERATED {
   399   //     successful            (0),  -- Response has valid confirmations
   400   //     malformedRequest      (1),  -- Illegal confirmation request
   401   //     internalError         (2),  -- Internal error in issuer
   402   //     tryLater              (3),  -- Try again later
   403   //                                 -- (4) is not used
   404   //     sigRequired           (5),  -- Must sign the request
   405   //     unauthorized          (6)   -- Request unauthorized
   406   // }
   407   uint8_t responseStatus;
   409   if (der::Enumerated(input, responseStatus) != der::Success) {
   410     return der::Failure;
   411   }
   412   switch (responseStatus) {
   413     case 0: break; // successful
   414     case 1: return der::Fail(SEC_ERROR_OCSP_MALFORMED_REQUEST);
   415     case 2: return der::Fail(SEC_ERROR_OCSP_SERVER_ERROR);
   416     case 3: return der::Fail(SEC_ERROR_OCSP_TRY_SERVER_LATER);
   417     case 5: return der::Fail(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG);
   418     case 6: return der::Fail(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST);
   419     default: return der::Fail(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS);
   420   }
   422   return der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0,
   423                      der::SEQUENCE, bind(ResponseBytes, _1, ref(context)));
   424 }
   426 // ResponseBytes ::=       SEQUENCE {
   427 //     responseType   OBJECT IDENTIFIER,
   428 //     response       OCTET STRING }
   429 static inline der::Result
   430 ResponseBytes(der::Input& input, Context& context)
   431 {
   432   static const uint8_t id_pkix_ocsp_basic[] = {
   433     0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
   434   };
   436   if (der::OID(input, id_pkix_ocsp_basic) != der::Success) {
   437     return der::Failure;
   438   }
   440   return der::Nested(input, der::OCTET_STRING, der::SEQUENCE,
   441                      bind(BasicResponse, _1, ref(context)));
   442 }
   444 // BasicOCSPResponse       ::= SEQUENCE {
   445 //    tbsResponseData      ResponseData,
   446 //    signatureAlgorithm   AlgorithmIdentifier,
   447 //    signature            BIT STRING,
   448 //    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
   449 der::Result
   450 BasicResponse(der::Input& input, Context& context)
   451 {
   452   der::Input::Mark mark(input.GetMark());
   454   uint16_t length;
   455   if (der::ExpectTagAndGetLength(input, der::SEQUENCE, length)
   456         != der::Success) {
   457     return der::Failure;
   458   }
   460   // The signature covers the entire DER encoding of tbsResponseData, including
   461   // the beginning tag and length. However, when we're parsing tbsResponseData,
   462   // we want to strip off the tag and length because we don't need it after
   463   // we've confirmed it's there and figured out what length it is.
   465   der::Input tbsResponseData;
   467   if (input.Skip(length, tbsResponseData) != der::Success) {
   468     return der::Failure;
   469   }
   471   CERTSignedData signedData;
   473   input.GetSECItem(siBuffer, mark, signedData.data);
   475   if (der::Nested(input, der::SEQUENCE,
   476                   bind(der::AlgorithmIdentifier, _1,
   477                        ref(signedData.signatureAlgorithm))) != der::Success) {
   478     return der::Failure;
   479   }
   481   if (der::Skip(input, der::BIT_STRING, signedData.signature) != der::Success) {
   482     return der::Failure;
   483   }
   484   if (signedData.signature.len == 0) {
   485     return der::Fail(SEC_ERROR_OCSP_BAD_SIGNATURE);
   486   }
   487   unsigned int unusedBitsAtEnd = signedData.signature.data[0];
   488   // XXX: Really the constraint should be that unusedBitsAtEnd must be less
   489   // than 7. But, we suspect there are no valid OCSP response signatures with
   490   // non-zero unused bits. It seems like NSS assumes this in various places, so
   491   // we enforce it. If we find compatibility issues, we'll know we're wrong.
   492   if (unusedBitsAtEnd != 0) {
   493     return der::Fail(SEC_ERROR_OCSP_BAD_SIGNATURE);
   494   }
   495   ++signedData.signature.data;
   496   --signedData.signature.len;
   497   signedData.signature.len = (signedData.signature.len << 3); // Bytes to bits
   499   // Parse certificates, if any
   501   SECItem certs[8];
   502   size_t numCerts = 0;
   504   if (!input.AtEnd()) {
   505     // We ignore the lengths of the wrappers because we'll detect bad lengths
   506     // during parsing--too short and we'll run out of input for parsing a cert,
   507     // and too long and we'll have leftover data that won't parse as a cert.
   509     // [0] wrapper
   510     if (der::ExpectTagAndIgnoreLength(
   511           input, der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 0)
   512         != der::Success) {
   513       return der::Failure;
   514     }
   516     // SEQUENCE wrapper
   517     if (der::ExpectTagAndIgnoreLength(input, der::SEQUENCE) != der::Success) {
   518       return der::Failure;
   519     }
   521     // sequence of certificates
   522     while (!input.AtEnd()) {
   523       if (numCerts == PR_ARRAY_SIZE(certs)) {
   524         return der::Fail(SEC_ERROR_BAD_DER);
   525       }
   527       // Unwrap the SEQUENCE that contains the certificate, which is itself a
   528       // SEQUENCE.
   529       der::Input::Mark mark(input.GetMark());
   530       if (der::Skip(input, der::SEQUENCE) != der::Success) {
   531         return der::Failure;
   532       }
   534       input.GetSECItem(siBuffer, mark, certs[numCerts]);
   535       ++numCerts;
   536     }
   537   }
   539   return ResponseData(tbsResponseData, context, signedData, certs, numCerts);
   540 }
   542 // ResponseData ::= SEQUENCE {
   543 //    version             [0] EXPLICIT Version DEFAULT v1,
   544 //    responderID             ResponderID,
   545 //    producedAt              GeneralizedTime,
   546 //    responses               SEQUENCE OF SingleResponse,
   547 //    responseExtensions  [1] EXPLICIT Extensions OPTIONAL }
   548 static inline der::Result
   549 ResponseData(der::Input& input, Context& context,
   550              const CERTSignedData& signedResponseData,
   551              /*const*/ SECItem* certs, size_t numCerts)
   552 {
   553   uint8_t version;
   554   if (der::OptionalVersion(input, version) != der::Success) {
   555     return der::Failure;
   556   }
   557   if (version != der::v1) {
   558     // TODO: more specific error code for bad version?
   559     return der::Fail(SEC_ERROR_BAD_DER);
   560   }
   562   // ResponderID ::= CHOICE {
   563   //    byName              [1] Name,
   564   //    byKey               [2] KeyHash }
   565   SECItem responderID;
   566   uint16_t responderIDLength;
   567   ResponderIDType responderIDType
   568     = input.Peek(static_cast<uint8_t>(ResponderIDType::byName))
   569     ? ResponderIDType::byName
   570     : ResponderIDType::byKey;
   571   if (ExpectTagAndGetLength(input, static_cast<uint8_t>(responderIDType),
   572                             responderIDLength) != der::Success) {
   573     return der::Failure;
   574   }
   575   // TODO: responderID probably needs to have another level of ASN1 tag/length
   576   // checked and stripped.
   577   if (input.Skip(responderIDLength, responderID) != der::Success) {
   578     return der::Failure;
   579   }
   581   // This is the soonest we can verify the signature. We verify the signature
   582   // right away to follow the principal of minimizing the processing of data
   583   // before verifying its signature.
   584   if (VerifySignature(context, responderIDType, responderID, certs, numCerts,
   585                       signedResponseData) != SECSuccess) {
   586     return der::Failure;
   587   }
   589   // TODO: Do we even need to parse this? Should we just skip it?
   590   PRTime producedAt;
   591   if (der::GeneralizedTime(input, producedAt) != der::Success) {
   592     return der::Failure;
   593   }
   595   // We don't accept an empty sequence of responses. In practice, a legit OCSP
   596   // responder will never return an empty response, and handling the case of an
   597   // empty response makes things unnecessarily complicated.
   598   if (der::NestedOf(input, der::SEQUENCE, der::SEQUENCE,
   599                     der::MustNotBeEmpty,
   600                     bind(SingleResponse, _1, ref(context))) != der::Success) {
   601     return der::Failure;
   602   }
   604   if (!input.AtEnd()) {
   605     if (der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
   606                     CheckExtensionsForCriticality) != der::Success) {
   607       return der::Failure;
   608     }
   609   }
   611   return der::Success;
   612 }
   614 // SingleResponse ::= SEQUENCE {
   615 //    certID                       CertID,
   616 //    certStatus                   CertStatus,
   617 //    thisUpdate                   GeneralizedTime,
   618 //    nextUpdate           [0]     EXPLICIT GeneralizedTime OPTIONAL,
   619 //    singleExtensions     [1]     EXPLICIT Extensions{{re-ocsp-crl |
   620 //                                              re-ocsp-archive-cutoff |
   621 //                                              CrlEntryExtensions, ...}
   622 //                                              } OPTIONAL }
   623 static inline der::Result
   624 SingleResponse(der::Input& input, Context& context)
   625 {
   626   bool match = false;
   627   if (der::Nested(input, der::SEQUENCE,
   628                   bind(CertID, _1, cref(context), ref(match)))
   629         != der::Success) {
   630     return der::Failure;
   631   }
   633   if (!match) {
   634     // This response does not reference the certificate we're interested in.
   635     // By consuming the rest of our input and returning successfully, we can
   636     // continue processing and examine another response that might have what
   637     // we want.
   638     input.SkipToEnd();
   639     return der::Success;
   640   }
   642   // CertStatus ::= CHOICE {
   643   //     good        [0]     IMPLICIT NULL,
   644   //     revoked     [1]     IMPLICIT RevokedInfo,
   645   //     unknown     [2]     IMPLICIT UnknownInfo }
   646   //
   647   // In the event of multiple SingleResponses for a cert that have conflicting
   648   // statuses, we use the following precedence rules:
   649   //
   650   // * revoked overrides good and unknown
   651   // * good overrides unknown
   652   if (input.Peek(static_cast<uint8_t>(CertStatus::Good))) {
   653     if (ExpectTagAndLength(input, static_cast<uint8_t>(CertStatus::Good), 0)
   654           != der::Success) {
   655       return der::Failure;
   656     }
   657     if (context.certStatus != CertStatus::Revoked) {
   658       context.certStatus = CertStatus::Good;
   659     }
   660   } else if (input.Peek(static_cast<uint8_t>(CertStatus::Revoked))) {
   661     // We don't need any info from the RevokedInfo structure, so we don't even
   662     // parse it. TODO: We should mention issues like this in the explanation of
   663     // why we treat invalid OCSP responses equivalently to revoked for OCSP
   664     // stapling.
   665     if (der::Skip(input, static_cast<uint8_t>(CertStatus::Revoked))
   666           != der::Success) {
   667       return der::Failure;
   668     }
   669     context.certStatus = CertStatus::Revoked;
   670   } else if (ExpectTagAndLength(input,
   671                                 static_cast<uint8_t>(CertStatus::Unknown),
   672                                 0) != der::Success) {
   673     return der::Failure;
   674   }
   676   // http://tools.ietf.org/html/rfc6960#section-3.2
   677   // 5. The time at which the status being indicated is known to be
   678   //    correct (thisUpdate) is sufficiently recent;
   679   // 6. When available, the time at or before which newer information will
   680   //    be available about the status of the certificate (nextUpdate) is
   681   //    greater than the current time.
   683   const PRTime maxLifetime =
   684     context.maxLifetimeInDays * ONE_DAY;
   686   PRTime thisUpdate;
   687   if (der::GeneralizedTime(input, thisUpdate) != der::Success) {
   688     return der::Failure;
   689   }
   691   if (thisUpdate > context.time + SLOP) {
   692     return der::Fail(SEC_ERROR_OCSP_FUTURE_RESPONSE);
   693   }
   695   PRTime notAfter;
   696   static const uint8_t NEXT_UPDATE_TAG =
   697     der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0;
   698   if (input.Peek(NEXT_UPDATE_TAG)) {
   699     PRTime nextUpdate;
   700     if (der::Nested(input, NEXT_UPDATE_TAG,
   701                     bind(der::GeneralizedTime, _1, ref(nextUpdate)))
   702           != der::Success) {
   703       return der::Failure;
   704     }
   706     if (nextUpdate < thisUpdate) {
   707       return der::Fail(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
   708     }
   709     if (nextUpdate - thisUpdate <= maxLifetime) {
   710       notAfter = nextUpdate;
   711     } else {
   712       notAfter = thisUpdate + maxLifetime;
   713     }
   714   } else {
   715     // NSS requires all OCSP responses without a nextUpdate to be recent.
   716     // Match that stricter behavior.
   717     notAfter = thisUpdate + ONE_DAY;
   718   }
   720   if (context.time < SLOP) { // prevent underflow
   721     return der::Fail(SEC_ERROR_INVALID_ARGS);
   722   }
   724   if (context.time - SLOP > notAfter) {
   725     context.expired = true;
   726   }
   728   if (!input.AtEnd()) {
   729     if (der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
   730                     CheckExtensionsForCriticality) != der::Success) {
   731       return der::Failure;
   732     }
   733   }
   735   if (context.thisUpdate) {
   736     *context.thisUpdate = thisUpdate;
   737   }
   738   if (context.validThrough) {
   739     *context.validThrough = notAfter;
   740   }
   742   return der::Success;
   743 }
   745 // CertID          ::=     SEQUENCE {
   746 //        hashAlgorithm       AlgorithmIdentifier,
   747 //        issuerNameHash      OCTET STRING, -- Hash of issuer's DN
   748 //        issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
   749 //        serialNumber        CertificateSerialNumber }
   750 static inline der::Result
   751 CertID(der::Input& input, const Context& context, /*out*/ bool& match)
   752 {
   753   match = false;
   755   SECAlgorithmID hashAlgorithm;
   756   if (der::Nested(input, der::SEQUENCE,
   757                   bind(der::AlgorithmIdentifier, _1, ref(hashAlgorithm)))
   758          != der::Success) {
   759     return der::Failure;
   760   }
   762   SECItem issuerNameHash;
   763   if (der::Skip(input, der::OCTET_STRING, issuerNameHash) != der::Success) {
   764     return der::Failure;
   765   }
   767   SECItem issuerKeyHash;
   768   if (der::Skip(input, der::OCTET_STRING, issuerKeyHash) != der::Success) {
   769     return der::Failure;
   770   }
   772   SECItem serialNumber;
   773   if (der::CertificateSerialNumber(input, serialNumber) != der::Success) {
   774     return der::Failure;
   775   }
   777   const CERTCertificate& cert = context.cert;
   778   const CERTCertificate& issuerCert = context.issuerCert;
   780   if (!SECITEM_ItemsAreEqual(&serialNumber, &cert.serialNumber)) {
   781     // This does not reference the certificate we're interested in.
   782     // Consume the rest of the input and return successfully to
   783     // potentially continue processing other responses.
   784     input.SkipToEnd();
   785     return der::Success;
   786   }
   788   // TODO: support SHA-2 hashes.
   790   SECOidTag hashAlg = SECOID_GetAlgorithmTag(&hashAlgorithm);
   791   if (hashAlg != SEC_OID_SHA1) {
   792     // Again, not interested in this response. Consume input, return success.
   793     input.SkipToEnd();
   794     return der::Success;
   795   }
   797   if (issuerNameHash.len != SHA1_LENGTH) {
   798     return der::Fail(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
   799   }
   801   // From http://tools.ietf.org/html/rfc6960#section-4.1.1:
   802   // "The hash shall be calculated over the DER encoding of the
   803   // issuer's name field in the certificate being checked."
   804   uint8_t hashBuf[SHA1_LENGTH];
   805   if (PK11_HashBuf(SEC_OID_SHA1, hashBuf, cert.derIssuer.data,
   806                    cert.derIssuer.len) != SECSuccess) {
   807     return der::Failure;
   808   }
   809   if (memcmp(hashBuf, issuerNameHash.data, issuerNameHash.len)) {
   810     // Again, not interested in this response. Consume input, return success.
   811     input.SkipToEnd();
   812     return der::Success;
   813   }
   815   return MatchIssuerKey(issuerKeyHash, issuerCert, match);
   816 }
   818 // From http://tools.ietf.org/html/rfc6960#section-4.1.1:
   819 // "The hash shall be calculated over the value (excluding tag and length) of
   820 // the subject public key field in the issuer's certificate."
   821 static der::Result
   822 MatchIssuerKey(const SECItem& issuerKeyHash, const CERTCertificate& issuer,
   823                /*out*/ bool& match)
   824 {
   825   if (issuerKeyHash.len != SHA1_LENGTH)  {
   826     return der::Fail(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
   827   }
   829   // TODO(bug 966856): support SHA-2 hashes
   831   // Copy just the length and data pointer (nothing needs to be freed) of the
   832   // subject public key so we can convert the length from bits to bytes, which
   833   // is what the digest function expects.
   834   SECItem spk = issuer.subjectPublicKeyInfo.subjectPublicKey;
   835   DER_ConvertBitString(&spk);
   837   static uint8_t hashBuf[SHA1_LENGTH];
   838   if (PK11_HashBuf(SEC_OID_SHA1, hashBuf, spk.data, spk.len) != SECSuccess) {
   839     return der::Failure;
   840   }
   842   match = !memcmp(hashBuf, issuerKeyHash.data, issuerKeyHash.len);
   843   return der::Success;
   844 }
   846 // Extension  ::=  SEQUENCE  {
   847 //      extnID      OBJECT IDENTIFIER,
   848 //      critical    BOOLEAN DEFAULT FALSE,
   849 //      extnValue   OCTET STRING
   850 //      }
   851 static der::Result
   852 CheckExtensionForCriticality(der::Input& input)
   853 {
   854   uint16_t toSkip;
   855   if (ExpectTagAndGetLength(input, der::OIDTag, toSkip) != der::Success) {
   856     return der::Failure;
   857   }
   859   // TODO: maybe we should check the syntax of the OID value
   860   if (input.Skip(toSkip) != der::Success) {
   861     return der::Failure;
   862   }
   864   // The only valid explicit encoding of the value is TRUE, so don't even
   865   // bother parsing it, since we're going to fail either way.
   866   if (input.Peek(der::BOOLEAN)) {
   867     return der::Fail(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
   868   }
   870   if (ExpectTagAndGetLength(input, der::OCTET_STRING, toSkip)
   871         != der::Success) {
   872     return der::Failure;
   873   }
   874   return input.Skip(toSkip);
   875 }
   877 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
   878 static der::Result
   879 CheckExtensionsForCriticality(der::Input& input)
   880 {
   881   // TODO(bug 997994): some responders include an empty SEQUENCE OF
   882   // Extension, which is invalid (der::MayBeEmpty should really be
   883   // der::MustNotBeEmpty).
   884   return der::NestedOf(input, der::SEQUENCE, der::SEQUENCE,
   885                        der::MayBeEmpty, CheckExtensionForCriticality);
   886 }
   888 //   1. The certificate identified in a received response corresponds to
   889 //      the certificate that was identified in the corresponding request;
   890 //   2. The signature on the response is valid;
   891 //   3. The identity of the signer matches the intended recipient of the
   892 //      request;
   893 //   4. The signer is currently authorized to provide a response for the
   894 //      certificate in question;
   895 //   5. The time at which the status being indicated is known to be
   896 //      correct (thisUpdate) is sufficiently recent;
   897 //   6. When available, the time at or before which newer information will
   898 //      be available about the status of the certificate (nextUpdate) is
   899 //      greater than the current time.
   900 //
   901 //   Responses whose nextUpdate value is earlier than
   902 //   the local system time value SHOULD be considered unreliable.
   903 //   Responses whose thisUpdate time is later than the local system time
   904 //   SHOULD be considered unreliable.
   905 //
   906 //   If nextUpdate is not set, the responder is indicating that newer
   907 //   revocation information is available all the time.
   908 //
   909 // http://tools.ietf.org/html/rfc5019#section-4
   911 SECItem*
   912 CreateEncodedOCSPRequest(PLArenaPool* arena,
   913                          const CERTCertificate* cert,
   914                          const CERTCertificate* issuerCert)
   915 {
   916   if (!arena || !cert || !issuerCert) {
   917     PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
   918     return nullptr;
   919   }
   921   // We do not add any extensions to the request.
   923   // RFC 6960 says "An OCSP client MAY wish to specify the kinds of response
   924   // types it understands. To do so, it SHOULD use an extension with the OID
   925   // id-pkix-ocsp-response." This use of MAY and SHOULD is unclear. MSIE11
   926   // on Windows 8.1 does not include any extensions, whereas NSS has always
   927   // included the id-pkix-ocsp-response extension. Avoiding the sending the
   928   // extension is better for OCSP GET because it makes the request smaller,
   929   // and thus more likely to fit within the 255 byte limit for OCSP GET that
   930   // is specified in RFC 5019 Section 5.
   932   // Bug 966856: Add the id-pkix-ocsp-pref-sig-algs extension.
   934   // Since we don't know whether the OCSP responder supports anything other
   935   // than SHA-1, we have no choice but to use SHA-1 for issuerNameHash and
   936   // issuerKeyHash.
   937   static const uint8_t hashAlgorithm[11] = {
   938     0x30, 0x09,                               // SEQUENCE
   939     0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, //   OBJECT IDENTIFIER id-sha1
   940     0x05, 0x00,                               //   NULL
   941   };
   942   static const uint8_t hashLen = SHA1_LENGTH;
   944   static const unsigned int totalLenWithoutSerialNumberData
   945     = 2                             // OCSPRequest
   946     + 2                             //   tbsRequest
   947     + 2                             //     requestList
   948     + 2                             //       Request
   949     + 2                             //         reqCert (CertID)
   950     + PR_ARRAY_SIZE(hashAlgorithm)  //           hashAlgorithm
   951     + 2 + hashLen                   //           issuerNameHash
   952     + 2 + hashLen                   //           issuerKeyHash
   953     + 2;                            //           serialNumber (header)
   955   // The only way we could have a request this large is if the serialNumber was
   956   // ridiculously and unreasonably large. RFC 5280 says "Conforming CAs MUST
   957   // NOT use serialNumber values longer than 20 octets." With this restriction,
   958   // we allow for some amount of non-conformance with that requirement while
   959   // still ensuring we can encode the length values in the ASN.1 TLV structures
   960   // in a single byte.
   961   if (issuerCert->serialNumber.len > 127u - totalLenWithoutSerialNumberData) {
   962     PR_SetError(SEC_ERROR_BAD_DATA, 0);
   963     return nullptr;
   964   }
   966   uint8_t totalLen = static_cast<uint8_t>(totalLenWithoutSerialNumberData +
   967     cert->serialNumber.len);
   969   SECItem* encodedRequest = SECITEM_AllocItem(arena, nullptr, totalLen);
   970   if (!encodedRequest) {
   971     return nullptr;
   972   }
   974   uint8_t* d = encodedRequest->data;
   975   *d++ = 0x30; *d++ = totalLen - 2;  // OCSPRequest (SEQUENCE)
   976   *d++ = 0x30; *d++ = totalLen - 4;  //   tbsRequest (SEQUENCE)
   977   *d++ = 0x30; *d++ = totalLen - 6;  //     requestList (SEQUENCE OF)
   978   *d++ = 0x30; *d++ = totalLen - 8;  //       Request (SEQUENCE)
   979   *d++ = 0x30; *d++ = totalLen - 10; //         reqCert (CertID SEQUENCE)
   981   // reqCert.hashAlgorithm
   982   for (size_t i = 0; i < PR_ARRAY_SIZE(hashAlgorithm); ++i) {
   983     *d++ = hashAlgorithm[i];
   984   }
   986   // reqCert.issuerNameHash (OCTET STRING)
   987   *d++ = 0x04;
   988   *d++ = hashLen;
   989   if (PK11_HashBuf(SEC_OID_SHA1, d, issuerCert->derSubject.data,
   990                    issuerCert->derSubject.len) != SECSuccess) {
   991     return nullptr;
   992   }
   993   d += hashLen;
   995   // reqCert.issuerKeyHash (OCTET STRING)
   996   *d++ = 0x04;
   997   *d++ = hashLen;
   998   SECItem key = issuerCert->subjectPublicKeyInfo.subjectPublicKey;
   999   DER_ConvertBitString(&key);
  1000   if (PK11_HashBuf(SEC_OID_SHA1, d, key.data, key.len) != SECSuccess) {
  1001     return nullptr;
  1003   d += hashLen;
  1005   // reqCert.serialNumber (INTEGER)
  1006   *d++ = 0x02; // INTEGER
  1007   *d++ = static_cast<uint8_t>(cert->serialNumber.len);
  1008   for (size_t i = 0; i < cert->serialNumber.len; ++i) {
  1009     *d++ = cert->serialNumber.data[i];
  1012   PR_ASSERT(d == encodedRequest->data + totalLen);
  1014   return encodedRequest;
  1017 } } // namespace mozilla::pkix

mercurial