1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This code is made available to you under your choice of the following sets
4  * of licensing terms:
5  */
6 /* This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9  */
10 /* Copyright 2013 Mozilla Contributors
11  *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  *     http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  */
24 
25 #include <limits>
26 
27 #include "mozpkix/pkix.h"
28 #include "mozpkix/pkixcheck.h"
29 #include "mozpkix/pkixutil.h"
30 
31 namespace mozilla { namespace pkix {
32 
33 // These values correspond to the tag values in the ASN.1 CertStatus
34 enum class CertStatus : uint8_t {
35   Good = der::CONTEXT_SPECIFIC | 0,
36   Revoked = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
37   Unknown = der::CONTEXT_SPECIFIC | 2
38 };
39 
40 class Context final
41 {
42 public:
Context(TrustDomain & aTrustDomain,const CertID & aCertID,Time aTime,uint16_t aMaxLifetimeInDays,Time * aThisUpdate,Time * aValidThrough)43   Context(TrustDomain& aTrustDomain, const CertID& aCertID, Time aTime,
44           uint16_t aMaxLifetimeInDays, /*optional out*/ Time* aThisUpdate,
45           /*optional out*/ Time* aValidThrough)
46     : trustDomain(aTrustDomain)
47     , certID(aCertID)
48     , time(aTime)
49     , maxLifetimeInDays(aMaxLifetimeInDays)
50     , certStatus(CertStatus::Unknown)
51     , thisUpdate(aThisUpdate)
52     , validThrough(aValidThrough)
53     , expired(false)
54     , matchFound(false)
55   {
56     if (thisUpdate) {
57       *thisUpdate = TimeFromElapsedSecondsAD(0);
58     }
59     if (validThrough) {
60       *validThrough = TimeFromElapsedSecondsAD(0);
61     }
62   }
63 
64   TrustDomain& trustDomain;
65   const CertID& certID;
66   const Time time;
67   const uint16_t maxLifetimeInDays;
68   CertStatus certStatus;
69   Time* thisUpdate;
70   Time* validThrough;
71   bool expired;
72 
73   Input signedCertificateTimestamps;
74 
75   // Keep track of whether the OCSP response contains the status of the
76   // certificate we're interested in. Responders might reply without
77   // including the status of any of the requested certs, we should
78   // indicate a server failure in those cases.
79   bool matchFound;
80 
81   Context(const Context&) = delete;
82   void operator=(const Context&) = delete;
83 };
84 
85 // Verify that potentialSigner is a valid delegated OCSP response signing cert
86 // according to RFC 6960 section 4.2.2.2.
87 static Result
CheckOCSPResponseSignerCert(TrustDomain & trustDomain,BackCert & potentialSigner,Input issuerSubject,Input issuerSubjectPublicKeyInfo,Time time)88 CheckOCSPResponseSignerCert(TrustDomain& trustDomain,
89                             BackCert& potentialSigner,
90                             Input issuerSubject,
91                             Input issuerSubjectPublicKeyInfo,
92                             Time time)
93 {
94   Result rv;
95 
96   // We don't need to do a complete verification of the signer (i.e. we don't
97   // have to call BuildCertChain to verify the entire chain) because we
98   // already know that the issuer is valid, since revocation checking is done
99   // from the root to the parent after we've built a complete chain that we
100   // know is otherwise valid. Rather, we just need to do a one-step validation
101   // from potentialSigner to the issuer.
102   //
103   // It seems reasonable to require the KU_DIGITAL_SIGNATURE key usage on the
104   // OCSP responder certificate if the OCSP responder certificate has a
105   // key usage extension. However, according to bug 240456, some OCSP responder
106   // certificates may have only the nonRepudiation bit set. Also, the OCSP
107   // specification (RFC 6960) does not mandate any particular key usage to be
108   // asserted for OCSP responde signers. Oddly, the CABForum Baseline
109   // Requirements v.1.1.5 do say "If the Root CA Private Key is used for
110   // signing OCSP responses, then the digitalSignature bit MUST be set."
111   //
112   // Note that CheckIssuerIndependentProperties processes
113   // SEC_OID_OCSP_RESPONDER in the way that the OCSP specification requires us
114   // to--in particular, it doesn't allow SEC_OID_OCSP_RESPONDER to be implied
115   // by a missing EKU extension, unlike other EKUs.
116   //
117   // TODO(bug 926261): If we're validating for a policy then the policy OID we
118   // are validating for should be passed to CheckIssuerIndependentProperties.
119   TrustLevel unusedTrustLevel;
120   rv = CheckIssuerIndependentProperties(trustDomain, potentialSigner, time,
121                                         KeyUsage::noParticularKeyUsageRequired,
122                                         KeyPurposeId::id_kp_OCSPSigning,
123                                         CertPolicyId::anyPolicy, 0,
124                                         unusedTrustLevel);
125   if (rv != Success) {
126     return rv;
127   }
128 
129   // It is possible that there exists a certificate with the same key as the
130   // issuer but with a different name, so we need to compare names
131   // XXX(bug 926270) XXX(bug 1008133) XXX(bug 980163): Improve name
132   // comparison.
133   // TODO: needs test
134   if (!InputsAreEqual(potentialSigner.GetIssuer(), issuerSubject)) {
135     return Result::ERROR_OCSP_RESPONDER_CERT_INVALID;
136   }
137 
138   // TODO(bug 926260): check name constraints
139 
140   rv = VerifySignedData(trustDomain, potentialSigner.GetSignedData(),
141                         issuerSubjectPublicKeyInfo);
142 
143   // TODO: check for revocation of the OCSP responder certificate unless no-check
144   // or the caller forcing no-check. To properly support the no-check policy, we'd
145   // need to enforce policy constraints from the issuerChain.
146 
147   return rv;
148 }
149 
150 enum class ResponderIDType : uint8_t
151 {
152   byName = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
153   byKey = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 2
154 };
155 
156 static inline Result OCSPResponse(Reader&, Context&);
157 static inline Result ResponseBytes(Reader&, Context&);
158 static inline Result BasicResponse(Reader&, Context&);
159 static inline Result ResponseData(
160                        Reader& tbsResponseData,
161                        Context& context,
162                        const der::SignedDataWithSignature& signedResponseData,
163                        const DERArray& certs);
164 static inline Result SingleResponse(Reader& input, Context& context);
165 static Result ExtensionNotUnderstood(Reader& extnID, Input extnValue,
166                                      bool critical, /*out*/ bool& understood);
167 static Result RememberSingleExtension(Context& context, Reader& extnID,
168                                       Input extnValue, bool critical,
169                                       /*out*/ bool& understood);
170 // It is convention to name the function after the part of the data structure
171 // we're parsing from the RFC (e.g. OCSPResponse, ResponseBytes).
172 // But since we also have a C++ type called CertID, this function doesn't
173 // follow the convention to prevent shadowing.
174 static inline Result MatchCertID(Reader& input,
175                                  const Context& context,
176                                  /*out*/ bool& match);
177 static Result MatchKeyHash(TrustDomain& trustDomain,
178                            DigestAlgorithm hashAlgorithm,
179                            Input issuerKeyHash,
180                            Input issuerSubjectPublicKeyInfo,
181                            /*out*/ bool& match);
182 static Result KeyHash(TrustDomain& trustDomain,
183                       DigestAlgorithm hashAlgorithm,
184                       Input subjectPublicKeyInfo,
185                       /*out*/ uint8_t* hashBuf, size_t hashBufSize);
186 
187 static Result
MatchResponderID(TrustDomain & trustDomain,ResponderIDType responderIDType,Input responderID,Input potentialSignerSubject,Input potentialSignerSubjectPublicKeyInfo,bool & match)188 MatchResponderID(TrustDomain& trustDomain,
189                  ResponderIDType responderIDType,
190                  Input responderID,
191                  Input potentialSignerSubject,
192                  Input potentialSignerSubjectPublicKeyInfo,
193                  /*out*/ bool& match)
194 {
195   match = false;
196 
197   switch (responderIDType) {
198     case ResponderIDType::byName:
199       // XXX(bug 926270) XXX(bug 1008133) XXX(bug 980163): Improve name
200       // comparison.
201       match = InputsAreEqual(responderID, potentialSignerSubject);
202       return Success;
203 
204     case ResponderIDType::byKey:
205     {
206       Reader input(responderID);
207       Input keyHash;
208       Result rv = der::ExpectTagAndGetValue(input, der::OCTET_STRING, keyHash);
209       if (rv != Success) {
210         return rv;
211       }
212       return MatchKeyHash(trustDomain, DigestAlgorithm::sha1, keyHash,
213                           potentialSignerSubjectPublicKeyInfo, match);
214     }
215 
216     MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
217   }
218 }
219 
220 static Result
VerifyOCSPSignedData(TrustDomain & trustDomain,const der::SignedDataWithSignature & signedResponseData,Input spki)221 VerifyOCSPSignedData(TrustDomain& trustDomain,
222                      const der::SignedDataWithSignature& signedResponseData,
223                      Input spki)
224 {
225   Result rv = VerifySignedData(trustDomain, signedResponseData, spki);
226   if (rv == Result::ERROR_BAD_SIGNATURE) {
227     rv = Result::ERROR_OCSP_BAD_SIGNATURE;
228   }
229   return rv;
230 }
231 
232 // RFC 6960 section 4.2.2.2: The OCSP responder must either be the issuer of
233 // the cert or it must be a delegated OCSP response signing cert directly
234 // issued by the issuer. If the OCSP responder is a delegated OCSP response
235 // signer, then its certificate is (probably) embedded within the OCSP
236 // response and we'll need to verify that it is a valid certificate that chains
237 // *directly* to issuerCert.
238 static Result
VerifySignature(Context & context,ResponderIDType responderIDType,Input responderID,const DERArray & certs,const der::SignedDataWithSignature & signedResponseData)239 VerifySignature(Context& context, ResponderIDType responderIDType,
240                 Input responderID, const DERArray& certs,
241                 const der::SignedDataWithSignature& signedResponseData)
242 {
243   bool match;
244   Result rv = MatchResponderID(context.trustDomain, responderIDType,
245                                responderID, context.certID.issuer,
246                                context.certID.issuerSubjectPublicKeyInfo,
247                                match);
248   if (rv != Success) {
249     return rv;
250   }
251   if (match) {
252     return VerifyOCSPSignedData(context.trustDomain, signedResponseData,
253                                 context.certID.issuerSubjectPublicKeyInfo);
254   }
255 
256   size_t numCerts = certs.GetLength();
257   for (size_t i = 0; i < numCerts; ++i) {
258     BackCert cert(*certs.GetDER(i), EndEntityOrCA::MustBeEndEntity, nullptr);
259     rv = cert.Init();
260     if (rv != Success) {
261       return rv;
262     }
263     rv = MatchResponderID(context.trustDomain, responderIDType, responderID,
264                           cert.GetSubject(), cert.GetSubjectPublicKeyInfo(),
265                           match);
266     if (rv != Success) {
267       if (IsFatalError(rv)) {
268         return rv;
269       }
270       continue;
271     }
272 
273     if (match) {
274       rv = CheckOCSPResponseSignerCert(context.trustDomain, cert,
275                                        context.certID.issuer,
276                                        context.certID.issuerSubjectPublicKeyInfo,
277                                        context.time);
278       if (rv != Success) {
279         if (IsFatalError(rv)) {
280           return rv;
281         }
282         continue;
283       }
284 
285       return VerifyOCSPSignedData(context.trustDomain, signedResponseData,
286                                   cert.GetSubjectPublicKeyInfo());
287     }
288   }
289 
290   return Result::ERROR_OCSP_INVALID_SIGNING_CERT;
291 }
292 
293 static inline Result
MapBadDERToMalformedOCSPResponse(Result rv)294 MapBadDERToMalformedOCSPResponse(Result rv)
295 {
296   if (rv == Result::ERROR_BAD_DER) {
297     return Result::ERROR_OCSP_MALFORMED_RESPONSE;
298   }
299   return rv;
300 }
301 
302 Result
VerifyEncodedOCSPResponse(TrustDomain & trustDomain,const struct CertID & certID,Time time,uint16_t maxOCSPLifetimeInDays,Input encodedResponse,bool & expired,Time * thisUpdate,Time * validThrough)303 VerifyEncodedOCSPResponse(TrustDomain& trustDomain, const struct CertID& certID,
304                           Time time, uint16_t maxOCSPLifetimeInDays,
305                           Input encodedResponse,
306                           /*out*/ bool& expired,
307                           /*optional out*/ Time* thisUpdate,
308                           /*optional out*/ Time* validThrough)
309 {
310   // Always initialize this to something reasonable.
311   expired = false;
312 
313   Context context(trustDomain, certID, time, maxOCSPLifetimeInDays,
314                   thisUpdate, validThrough);
315 
316   Reader input(encodedResponse);
317   Result rv = der::Nested(input, der::SEQUENCE, [&context](Reader& r) {
318     return OCSPResponse(r, context);
319   });
320   if (rv != Success) {
321     return MapBadDERToMalformedOCSPResponse(rv);
322   }
323   rv = der::End(input);
324   if (rv != Success) {
325     return MapBadDERToMalformedOCSPResponse(rv);
326   }
327   if (!context.matchFound) {
328     return Result::ERROR_OCSP_RESPONSE_FOR_CERT_MISSING;
329   }
330 
331   expired = context.expired;
332 
333   switch (context.certStatus) {
334     case CertStatus::Good:
335       if (expired) {
336         return Result::ERROR_OCSP_OLD_RESPONSE;
337       }
338       if (context.signedCertificateTimestamps.GetLength()) {
339         Input sctList;
340         rv = ExtractSignedCertificateTimestampListFromExtension(
341           context.signedCertificateTimestamps, sctList);
342         if (rv != Success) {
343           return MapBadDERToMalformedOCSPResponse(rv);
344         }
345         context.trustDomain.NoteAuxiliaryExtension(
346           AuxiliaryExtension::SCTListFromOCSPResponse, sctList);
347       }
348       return Success;
349     case CertStatus::Revoked:
350       return Result::ERROR_REVOKED_CERTIFICATE;
351     case CertStatus::Unknown:
352       return Result::ERROR_OCSP_UNKNOWN_CERT;
353      MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
354   }
355 }
356 
357 // OCSPResponse ::= SEQUENCE {
358 //       responseStatus         OCSPResponseStatus,
359 //       responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
360 //
361 static inline Result
OCSPResponse(Reader & input,Context & context)362 OCSPResponse(Reader& input, Context& context)
363 {
364   // OCSPResponseStatus ::= ENUMERATED {
365   //     successful            (0),  -- Response has valid confirmations
366   //     malformedRequest      (1),  -- Illegal confirmation request
367   //     internalError         (2),  -- Internal error in issuer
368   //     tryLater              (3),  -- Try again later
369   //                                 -- (4) is not used
370   //     sigRequired           (5),  -- Must sign the request
371   //     unauthorized          (6)   -- Request unauthorized
372   // }
373   uint8_t responseStatus;
374 
375   Result rv = der::Enumerated(input, responseStatus);
376   if (rv != Success) {
377     return rv;
378   }
379   switch (responseStatus) {
380     case 0: break; // successful
381     case 1: return Result::ERROR_OCSP_MALFORMED_REQUEST;
382     case 2: return Result::ERROR_OCSP_SERVER_ERROR;
383     case 3: return Result::ERROR_OCSP_TRY_SERVER_LATER;
384     case 5: return Result::ERROR_OCSP_REQUEST_NEEDS_SIG;
385     case 6: return Result::ERROR_OCSP_UNAUTHORIZED_REQUEST;
386     default: return Result::ERROR_OCSP_UNKNOWN_RESPONSE_STATUS;
387   }
388 
389   return der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0,
390                      der::SEQUENCE, [&context](Reader& r) {
391     return ResponseBytes(r, context);
392   });
393 }
394 
395 // ResponseBytes ::=       SEQUENCE {
396 //     responseType   OBJECT IDENTIFIER,
397 //     response       OCTET STRING }
398 static inline Result
ResponseBytes(Reader & input,Context & context)399 ResponseBytes(Reader& input, Context& context)
400 {
401   static const uint8_t id_pkix_ocsp_basic[] = {
402     0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
403   };
404 
405   Result rv = der::OID(input, id_pkix_ocsp_basic);
406   if (rv != Success) {
407     return rv;
408   }
409 
410   return der::Nested(input, der::OCTET_STRING, der::SEQUENCE,
411                      [&context](Reader& r) {
412     return BasicResponse(r, context);
413   });
414 }
415 
416 // BasicOCSPResponse       ::= SEQUENCE {
417 //    tbsResponseData      ResponseData,
418 //    signatureAlgorithm   AlgorithmIdentifier,
419 //    signature            BIT STRING,
420 //    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
421 Result
BasicResponse(Reader & input,Context & context)422 BasicResponse(Reader& input, Context& context)
423 {
424   Reader tbsResponseData;
425   der::SignedDataWithSignature signedData;
426   Result rv = der::SignedData(input, tbsResponseData, signedData);
427   if (rv != Success) {
428     if (rv == Result::ERROR_BAD_SIGNATURE) {
429       return Result::ERROR_OCSP_BAD_SIGNATURE;
430     }
431     return rv;
432   }
433 
434   // Parse certificates, if any
435   NonOwningDERArray certs;
436   if (!input.AtEnd()) {
437     rv = der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0,
438                      der::SEQUENCE, [&certs](Reader& certsDER) -> Result {
439       while (!certsDER.AtEnd()) {
440         Input cert;
441         Result nestedRv =
442           der::ExpectTagAndGetTLV(certsDER, der::SEQUENCE, cert);
443         if (nestedRv != Success) {
444           return nestedRv;
445         }
446         nestedRv = certs.Append(cert);
447         if (nestedRv != Success) {
448           return Result::ERROR_BAD_DER; // Too many certs
449         }
450       }
451       return Success;
452     });
453     if (rv != Success) {
454       return rv;
455     }
456   }
457 
458   return ResponseData(tbsResponseData, context, signedData, certs);
459 }
460 
461 // ResponseData ::= SEQUENCE {
462 //    version             [0] EXPLICIT Version DEFAULT v1,
463 //    responderID             ResponderID,
464 //    producedAt              GeneralizedTime,
465 //    responses               SEQUENCE OF SingleResponse,
466 //    responseExtensions  [1] EXPLICIT Extensions OPTIONAL }
467 static inline Result
ResponseData(Reader & input,Context & context,const der::SignedDataWithSignature & signedResponseData,const DERArray & certs)468 ResponseData(Reader& input, Context& context,
469              const der::SignedDataWithSignature& signedResponseData,
470              const DERArray& certs)
471 {
472   der::Version version;
473   Result rv = der::OptionalVersion(input, version);
474   if (rv != Success) {
475     return rv;
476   }
477   if (version != der::Version::v1) {
478     // TODO: more specific error code for bad version?
479     return Result::ERROR_BAD_DER;
480   }
481 
482   // ResponderID ::= CHOICE {
483   //    byName              [1] Name,
484   //    byKey               [2] KeyHash }
485   Input responderID;
486   ResponderIDType responderIDType
487     = input.Peek(static_cast<uint8_t>(ResponderIDType::byName))
488     ? ResponderIDType::byName
489     : ResponderIDType::byKey;
490   rv = der::ExpectTagAndGetValue(input, static_cast<uint8_t>(responderIDType),
491                                  responderID);
492   if (rv != Success) {
493     return rv;
494   }
495 
496   // This is the soonest we can verify the signature. We verify the signature
497   // right away to follow the principal of minimizing the processing of data
498   // before verifying its signature.
499   rv = VerifySignature(context, responderIDType, responderID, certs,
500                        signedResponseData);
501   if (rv != Success) {
502     return rv;
503   }
504 
505   // TODO: Do we even need to parse this? Should we just skip it?
506   Time producedAt(Time::uninitialized);
507   rv = der::GeneralizedTime(input, producedAt);
508   if (rv != Success) {
509     return rv;
510   }
511 
512   // We don't accept an empty sequence of responses. In practice, a legit OCSP
513   // responder will never return an empty response, and handling the case of an
514   // empty response makes things unnecessarily complicated.
515   rv = der::NestedOf(input, der::SEQUENCE, der::SEQUENCE,
516                      der::EmptyAllowed::No, [&context](Reader& r) {
517     return SingleResponse(r, context);
518   });
519   if (rv != Success) {
520     return rv;
521   }
522 
523   return der::OptionalExtensions(input,
524                                  der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
525                                  ExtensionNotUnderstood);
526 }
527 
528 // SingleResponse ::= SEQUENCE {
529 //    certID                       CertID,
530 //    certStatus                   CertStatus,
531 //    thisUpdate                   GeneralizedTime,
532 //    nextUpdate           [0]     EXPLICIT GeneralizedTime OPTIONAL,
533 //    singleExtensions     [1]     EXPLICIT Extensions{{re-ocsp-crl |
534 //                                              re-ocsp-archive-cutoff |
535 //                                              CrlEntryExtensions, ...}
536 //                                              } OPTIONAL }
537 static inline Result
SingleResponse(Reader & input,Context & context)538 SingleResponse(Reader& input, Context& context)
539 {
540   bool match = false;
541   Result rv = der::Nested(input, der::SEQUENCE, [&context, &match](Reader& r) {
542     return MatchCertID(r, context, match);
543   });
544   if (rv != Success) {
545     return rv;
546   }
547 
548   if (!match) {
549     // This response does not reference the certificate we're interested in.
550     // By consuming the rest of our input and returning successfully, we can
551     // continue processing and examine another response that might have what
552     // we want.
553     input.SkipToEnd();
554     return Success;
555   }
556 
557   // We found a response for the cert we're interested in.
558   context.matchFound = true;
559 
560   // CertStatus ::= CHOICE {
561   //     good        [0]     IMPLICIT NULL,
562   //     revoked     [1]     IMPLICIT RevokedInfo,
563   //     unknown     [2]     IMPLICIT UnknownInfo }
564   //
565   // In the event of multiple SingleResponses for a cert that have conflicting
566   // statuses, we use the following precedence rules:
567   //
568   // * revoked overrides good and unknown
569   // * good overrides unknown
570   if (input.Peek(static_cast<uint8_t>(CertStatus::Good))) {
571     rv = der::ExpectTagAndEmptyValue(input,
572                                      static_cast<uint8_t>(CertStatus::Good));
573     if (rv != Success) {
574       return rv;
575     }
576     if (context.certStatus != CertStatus::Revoked) {
577       context.certStatus = CertStatus::Good;
578     }
579   } else if (input.Peek(static_cast<uint8_t>(CertStatus::Revoked))) {
580     // We don't need any info from the RevokedInfo structure, so we don't even
581     // parse it. TODO: We should mention issues like this in the explanation of
582     // why we treat invalid OCSP responses equivalently to revoked for OCSP
583     // stapling.
584     rv = der::ExpectTagAndSkipValue(input,
585                                     static_cast<uint8_t>(CertStatus::Revoked));
586     if (rv != Success) {
587       return rv;
588     }
589     context.certStatus = CertStatus::Revoked;
590   } else {
591     rv = der::ExpectTagAndEmptyValue(input,
592                                      static_cast<uint8_t>(CertStatus::Unknown));
593     if (rv != Success) {
594       return rv;
595     }
596   }
597 
598   // http://tools.ietf.org/html/rfc6960#section-3.2
599   // 5. The time at which the status being indicated is known to be
600   //    correct (thisUpdate) is sufficiently recent;
601   // 6. When available, the time at or before which newer information will
602   //    be available about the status of the certificate (nextUpdate) is
603   //    greater than the current time.
604 
605   Time thisUpdate(Time::uninitialized);
606   rv = der::GeneralizedTime(input, thisUpdate);
607   if (rv != Success) {
608     return rv;
609   }
610 
611   static const uint64_t SLOP_SECONDS = Time::ONE_DAY_IN_SECONDS;
612 
613   Time timePlusSlop(context.time);
614   rv = timePlusSlop.AddSeconds(SLOP_SECONDS);
615   if (rv != Success) {
616     return rv;
617   }
618   if (thisUpdate > timePlusSlop) {
619     return Result::ERROR_OCSP_FUTURE_RESPONSE;
620   }
621 
622   Time notAfter(Time::uninitialized);
623   static const uint8_t NEXT_UPDATE_TAG =
624     der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0;
625   if (input.Peek(NEXT_UPDATE_TAG)) {
626     Time nextUpdate(Time::uninitialized);
627     rv = der::Nested(input, NEXT_UPDATE_TAG, [&nextUpdate](Reader& r) {
628       return der::GeneralizedTime(r, nextUpdate);
629     });
630     if (rv != Success) {
631       return rv;
632     }
633 
634     if (nextUpdate < thisUpdate) {
635       return Result::ERROR_OCSP_MALFORMED_RESPONSE;
636     }
637     notAfter = thisUpdate;
638     if (notAfter.AddSeconds(context.maxLifetimeInDays *
639                             Time::ONE_DAY_IN_SECONDS) != Success) {
640       // This could only happen if we're dealing with times beyond the year
641       // 10,000AD.
642       return Result::ERROR_OCSP_FUTURE_RESPONSE;
643     }
644     if (nextUpdate <= notAfter) {
645       notAfter = nextUpdate;
646     }
647   } else {
648     // NSS requires all OCSP responses without a nextUpdate to be recent.
649     // Match that stricter behavior.
650     notAfter = thisUpdate;
651     if (notAfter.AddSeconds(Time::ONE_DAY_IN_SECONDS) != Success) {
652       // This could only happen if we're dealing with times beyond the year
653       // 10,000AD.
654       return Result::ERROR_OCSP_FUTURE_RESPONSE;
655     }
656   }
657 
658   // Add some slop to hopefully handle clock-skew.
659   Time notAfterPlusSlop(notAfter);
660   rv = notAfterPlusSlop.AddSeconds(SLOP_SECONDS);
661   if (rv != Success) {
662     // This could only happen if we're dealing with times beyond the year
663     // 10,000AD.
664     return Result::ERROR_OCSP_FUTURE_RESPONSE;
665   }
666   if (context.time > notAfterPlusSlop) {
667     context.expired = true;
668   }
669 
670   rv = der::OptionalExtensions(
671     input,
672     der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
673     [&context](Reader& extnID, const Input& extnValue, bool critical,
674                /*out*/ bool& understood) {
675       return RememberSingleExtension(context, extnID, extnValue, critical,
676                                      understood);
677     });
678 
679   if (rv != Success) {
680     return rv;
681   }
682 
683   if (context.thisUpdate) {
684     *context.thisUpdate = thisUpdate;
685   }
686   if (context.validThrough) {
687     *context.validThrough = notAfterPlusSlop;
688   }
689 
690   return Success;
691 }
692 
693 // CertID          ::=     SEQUENCE {
694 //        hashAlgorithm       AlgorithmIdentifier,
695 //        issuerNameHash      OCTET STRING, -- Hash of issuer's DN
696 //        issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
697 //        serialNumber        CertificateSerialNumber }
698 static inline Result
MatchCertID(Reader & input,const Context & context,bool & match)699 MatchCertID(Reader& input, const Context& context, /*out*/ bool& match)
700 {
701   match = false;
702 
703   DigestAlgorithm hashAlgorithm;
704   Result rv = der::DigestAlgorithmIdentifier(input, hashAlgorithm);
705   if (rv != Success) {
706     if (rv == Result::ERROR_INVALID_ALGORITHM) {
707       // Skip entries that are hashed with algorithms we don't support.
708       input.SkipToEnd();
709       return Success;
710     }
711     return rv;
712   }
713 
714   Input issuerNameHash;
715   rv = der::ExpectTagAndGetValue(input, der::OCTET_STRING, issuerNameHash);
716   if (rv != Success) {
717     return rv;
718   }
719 
720   Input issuerKeyHash;
721   rv = der::ExpectTagAndGetValue(input, der::OCTET_STRING, issuerKeyHash);
722   if (rv != Success) {
723     return rv;
724   }
725 
726   Input serialNumber;
727   rv = der::CertificateSerialNumber(input, serialNumber);
728   if (rv != Success) {
729     return rv;
730   }
731 
732   if (!InputsAreEqual(serialNumber, context.certID.serialNumber)) {
733     // This does not reference the certificate we're interested in.
734     // Consume the rest of the input and return successfully to
735     // potentially continue processing other responses.
736     input.SkipToEnd();
737     return Success;
738   }
739 
740   size_t hashAlgorithmLength = DigestAlgorithmToSizeInBytes(hashAlgorithm);
741   if (issuerNameHash.GetLength() != hashAlgorithmLength) {
742     return Result::ERROR_OCSP_MALFORMED_RESPONSE;
743   }
744 
745   // From http://tools.ietf.org/html/rfc6960#section-4.1.1:
746   // "The hash shall be calculated over the DER encoding of the
747   // issuer's name field in the certificate being checked."
748   uint8_t hashBuf[MAX_DIGEST_SIZE_IN_BYTES];
749   if (hashAlgorithmLength > sizeof(hashBuf)) {
750     return Result::FATAL_ERROR_LIBRARY_FAILURE;
751   }
752   rv = context.trustDomain.DigestBuf(context.certID.issuer,
753                                      hashAlgorithm, hashBuf,
754                                      hashAlgorithmLength);
755   if (rv != Success) {
756     return rv;
757   }
758   Input computed;
759   rv = computed.Init(hashBuf, hashAlgorithmLength);
760   if (rv != Success) {
761     return rv;
762   }
763   if (!InputsAreEqual(computed, issuerNameHash)) {
764     // Again, not interested in this response. Consume input, return success.
765     input.SkipToEnd();
766     return Success;
767   }
768 
769   return MatchKeyHash(context.trustDomain, hashAlgorithm, issuerKeyHash,
770                       context.certID.issuerSubjectPublicKeyInfo, match);
771 }
772 
773 // From http://tools.ietf.org/html/rfc6960#section-4.1.1:
774 // "The hash shall be calculated over the value (excluding tag and length) of
775 // the subject public key field in the issuer's certificate."
776 //
777 // From http://tools.ietf.org/html/rfc6960#appendix-B.1:
778 // KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
779 //                          -- (i.e., the SHA-1 hash of the value of the
780 //                          -- BIT STRING subjectPublicKey [excluding
781 //                          -- the tag, length, and number of unused
782 //                          -- bits] in the responder's certificate)
783 //
784 // From https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1:
785 //    CertID          ::=     SEQUENCE {
786 //        hashAlgorithm       AlgorithmIdentifier,
787 //        issuerNameHash      OCTET STRING, -- Hash of issuer's DN
788 //        issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
789 //        serialNumber        CertificateSerialNumber }
790 // ...
791 //    o  hashAlgorithm is the hash algorithm used to generate the
792 //       issuerNameHash and issuerKeyHash values.
793 // ...
794 //    o  issuerKeyHash is the hash of the issuer's public key.  The hash
795 //       shall be calculated over the value (excluding tag and length) of
796 //       the subject public key field in the issuer's certificate.
797 static Result
MatchKeyHash(TrustDomain & trustDomain,DigestAlgorithm hashAlgorithm,Input keyHash,const Input subjectPublicKeyInfo,bool & match)798 MatchKeyHash(TrustDomain& trustDomain, DigestAlgorithm hashAlgorithm,
799              Input keyHash, const Input subjectPublicKeyInfo,
800              /*out*/ bool& match)
801 {
802   size_t hashLength = DigestAlgorithmToSizeInBytes(hashAlgorithm);
803   if (keyHash.GetLength() != hashLength)  {
804     return Result::ERROR_OCSP_MALFORMED_RESPONSE;
805   }
806   uint8_t hashBuf[MAX_DIGEST_SIZE_IN_BYTES];
807   if (hashLength > MAX_DIGEST_SIZE_IN_BYTES) {
808     return Result::FATAL_ERROR_LIBRARY_FAILURE;
809   }
810   Result rv = KeyHash(trustDomain, hashAlgorithm, subjectPublicKeyInfo,
811                       hashBuf, hashLength);
812   if (rv != Success) {
813     return rv;
814   }
815   Input computed;
816   rv = computed.Init(hashBuf, hashLength);
817   if (rv != Success) {
818     return rv;
819   }
820   match = InputsAreEqual(computed, keyHash);
821   return Success;
822 }
823 
824 Result
KeyHash(TrustDomain & trustDomain,DigestAlgorithm hashAlgorithm,const Input subjectPublicKeyInfo,uint8_t * hashBuf,size_t hashBufSize)825 KeyHash(TrustDomain& trustDomain, DigestAlgorithm hashAlgorithm,
826         const Input subjectPublicKeyInfo, /*out*/ uint8_t* hashBuf,
827         size_t hashBufSize)
828 {
829   if (!hashBuf || hashBufSize != DigestAlgorithmToSizeInBytes(hashAlgorithm)) {
830     return Result::FATAL_ERROR_LIBRARY_FAILURE;
831   }
832 
833   // RFC 5280 Section 4.1
834   //
835   // SubjectPublicKeyInfo  ::=  SEQUENCE  {
836   //    algorithm            AlgorithmIdentifier,
837   //    subjectPublicKey     BIT STRING  }
838 
839   Reader spki;
840   Result rv = der::ExpectTagAndGetValueAtEnd(subjectPublicKeyInfo,
841                                              der::SEQUENCE, spki);
842   if (rv != Success) {
843     return rv;
844   }
845 
846   // Skip AlgorithmIdentifier
847   rv = der::ExpectTagAndSkipValue(spki, der::SEQUENCE);
848   if (rv != Success) {
849     return rv;
850   }
851 
852   Input subjectPublicKey;
853   rv = der::BitStringWithNoUnusedBits(spki, subjectPublicKey);
854   if (rv != Success) {
855     return rv;
856   }
857   rv = der::End(spki);
858   if (rv != Success) {
859     return rv;
860   }
861 
862   return trustDomain.DigestBuf(subjectPublicKey, hashAlgorithm, hashBuf,
863                                hashBufSize);
864 }
865 
866 Result
ExtensionNotUnderstood(Reader &,Input,bool,bool & understood)867 ExtensionNotUnderstood(Reader& /*extnID*/, Input /*extnValue*/,
868                        bool /*critical*/, /*out*/ bool& understood)
869 {
870   understood = false;
871   return Success;
872 }
873 
874 Result
RememberSingleExtension(Context & context,Reader & extnID,Input extnValue,bool,bool & understood)875 RememberSingleExtension(Context& context, Reader& extnID, Input extnValue,
876                         bool /*critical*/, /*out*/ bool& understood)
877 {
878   understood = false;
879 
880   // SingleExtension for Signed Certificate Timestamp List.
881   // See Section 3.3 of RFC 6962.
882   // python DottedOIDToCode.py
883   //   id_ocsp_singleExtensionSctList 1.3.6.1.4.1.11129.2.4.5
884   static const uint8_t id_ocsp_singleExtensionSctList[] = {
885     0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x04, 0x05
886   };
887 
888   if (extnID.MatchRest(id_ocsp_singleExtensionSctList)) {
889     // Empty values are not allowed for this extension. Note that
890     // we assume this later, when checking if the extension was present.
891     if (extnValue.GetLength() == 0) {
892       return Result::ERROR_EXTENSION_VALUE_INVALID;
893     }
894     if (context.signedCertificateTimestamps.Init(extnValue) != Success) {
895       // Duplicate extension.
896       return Result::ERROR_EXTENSION_VALUE_INVALID;
897     }
898     understood = true;
899   }
900 
901   return Success;
902 }
903 
904 //   1. The certificate identified in a received response corresponds to
905 //      the certificate that was identified in the corresponding request;
906 //   2. The signature on the response is valid;
907 //   3. The identity of the signer matches the intended recipient of the
908 //      request;
909 //   4. The signer is currently authorized to provide a response for the
910 //      certificate in question;
911 //   5. The time at which the status being indicated is known to be
912 //      correct (thisUpdate) is sufficiently recent;
913 //   6. When available, the time at or before which newer information will
914 //      be available about the status of the certificate (nextUpdate) is
915 //      greater than the current time.
916 //
917 //   Responses whose nextUpdate value is earlier than
918 //   the local system time value SHOULD be considered unreliable.
919 //   Responses whose thisUpdate time is later than the local system time
920 //   SHOULD be considered unreliable.
921 //
922 //   If nextUpdate is not set, the responder is indicating that newer
923 //   revocation information is available all the time.
924 //
925 // http://tools.ietf.org/html/rfc5019#section-4
926 
927 Result
CreateEncodedOCSPRequest(TrustDomain & trustDomain,const struct CertID & certID,uint8_t (& out)[OCSP_REQUEST_MAX_LENGTH],size_t & outLen)928 CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
929                          /*out*/ uint8_t (&out)[OCSP_REQUEST_MAX_LENGTH],
930                          /*out*/ size_t& outLen)
931 {
932   // We do not add any extensions to the request.
933 
934   // RFC 6960 says "An OCSP client MAY wish to specify the kinds of response
935   // types it understands. To do so, it SHOULD use an extension with the OID
936   // id-pkix-ocsp-response." This use of MAY and SHOULD is unclear. MSIE11
937   // on Windows 8.1 does not include any extensions, whereas NSS has always
938   // included the id-pkix-ocsp-response extension. Avoiding the sending the
939   // extension is better for OCSP GET because it makes the request smaller,
940   // and thus more likely to fit within the 255 byte limit for OCSP GET that
941   // is specified in RFC 5019 Section 5.
942 
943   // Since we don't know whether the OCSP responder supports anything other
944   // than SHA-1, we have no choice but to use SHA-1 for issuerNameHash and
945   // issuerKeyHash.
946   static const uint8_t hashAlgorithm[11] = {
947     0x30, 0x09,                               // SEQUENCE
948     0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, //   OBJECT IDENTIFIER id-sha1
949     0x05, 0x00,                               //   NULL
950   };
951   static const uint8_t hashLen = 160 / 8;
952 
953   static const unsigned int totalLenWithoutSerialNumberData
954     = 2                             // OCSPRequest
955     + 2                             //   tbsRequest
956     + 2                             //     requestList
957     + 2                             //       Request
958     + 2                             //         reqCert (CertID)
959     + sizeof(hashAlgorithm)         //           hashAlgorithm
960     + 2 + hashLen                   //           issuerNameHash
961     + 2 + hashLen                   //           issuerKeyHash
962     + 2;                            //           serialNumber (header)
963 
964   // The only way we could have a request this large is if the serialNumber was
965   // ridiculously and unreasonably large. RFC 5280 says "Conforming CAs MUST
966   // NOT use serialNumber values longer than 20 octets." With this restriction,
967   // we allow for some amount of non-conformance with that requirement while
968   // still ensuring we can encode the length values in the ASN.1 TLV structures
969   // in a single byte.
970   static_assert(totalLenWithoutSerialNumberData < OCSP_REQUEST_MAX_LENGTH,
971                 "totalLenWithoutSerialNumberData too big");
972   if (certID.serialNumber.GetLength() >
973         OCSP_REQUEST_MAX_LENGTH - totalLenWithoutSerialNumberData) {
974     return Result::ERROR_BAD_DER;
975   }
976 
977   outLen = totalLenWithoutSerialNumberData + certID.serialNumber.GetLength();
978 
979   uint8_t totalLen = static_cast<uint8_t>(outLen);
980 
981   uint8_t* d = out;
982   *d++ = 0x30; *d++ = totalLen - 2u;  // OCSPRequest (SEQUENCE)
983   *d++ = 0x30; *d++ = totalLen - 4u;  //   tbsRequest (SEQUENCE)
984   *d++ = 0x30; *d++ = totalLen - 6u;  //     requestList (SEQUENCE OF)
985   *d++ = 0x30; *d++ = totalLen - 8u;  //       Request (SEQUENCE)
986   *d++ = 0x30; *d++ = totalLen - 10u; //         reqCert (CertID SEQUENCE)
987 
988   // reqCert.hashAlgorithm
989   for (const uint8_t hashAlgorithmByte : hashAlgorithm) {
990     *d++ = hashAlgorithmByte;
991   }
992 
993   // reqCert.issuerNameHash (OCTET STRING)
994   *d++ = 0x04;
995   *d++ = hashLen;
996   Result rv = trustDomain.DigestBuf(certID.issuer, DigestAlgorithm::sha1, d,
997                                     hashLen);
998   if (rv != Success) {
999     return rv;
1000   }
1001   d += hashLen;
1002 
1003   // reqCert.issuerKeyHash (OCTET STRING)
1004   *d++ = 0x04;
1005   *d++ = hashLen;
1006   rv = KeyHash(trustDomain, DigestAlgorithm::sha1,
1007                certID.issuerSubjectPublicKeyInfo, d, hashLen);
1008   if (rv != Success) {
1009     return rv;
1010   }
1011   d += hashLen;
1012 
1013   // reqCert.serialNumber (INTEGER)
1014   *d++ = 0x02; // INTEGER
1015   *d++ = static_cast<uint8_t>(certID.serialNumber.GetLength());
1016   Reader serialNumber(certID.serialNumber);
1017   do {
1018     rv = serialNumber.Read(*d);
1019     if (rv != Success) {
1020       return rv;
1021     }
1022     ++d;
1023   } while (!serialNumber.AtEnd());
1024 
1025   assert(d == out + totalLen);
1026 
1027   return Success;
1028 }
1029 
1030 } } // namespace mozilla::pkix
1031