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