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 2014 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 "pkixgtest.h"
26 
27 #include "mozpkix/pkixder.h"
28 
29 #include "secoid.h"
30 
31 using namespace mozilla::pkix;
32 using namespace mozilla::pkix::test;
33 
34 const uint16_t END_ENTITY_MAX_LIFETIME_IN_DAYS = 10;
35 
36 // Note that CheckRevocation is never called for OCSP signing certificates.
37 class OCSPTestTrustDomain : public DefaultCryptoTrustDomain
38 {
39 public:
OCSPTestTrustDomain()40   OCSPTestTrustDomain() { }
41 
GetCertTrust(EndEntityOrCA endEntityOrCA,const CertPolicyId &,Input,TrustLevel & trustLevel)42   Result GetCertTrust(EndEntityOrCA endEntityOrCA, const CertPolicyId&,
43                       Input, /*out*/ TrustLevel& trustLevel)
44                       /*non-final*/ override
45   {
46     EXPECT_EQ(endEntityOrCA, EndEntityOrCA::MustBeEndEntity);
47     trustLevel = TrustLevel::InheritsTrust;
48     return Success;
49   }
50 
NoteAuxiliaryExtension(AuxiliaryExtension extension,Input extensionData)51   virtual void NoteAuxiliaryExtension(AuxiliaryExtension extension,
52                                       Input extensionData) override
53   {
54     if (extension == AuxiliaryExtension::SCTListFromOCSPResponse) {
55       signedCertificateTimestamps = InputToByteString(extensionData);
56     } else {
57       // We do not currently expect to receive any other extension here.
58       ADD_FAILURE();
59     }
60   }
61 
62   ByteString signedCertificateTimestamps;
63 };
64 
65 namespace {
66 char const* const rootName = "Test CA 1";
67 } // namespace
68 
69 class pkixocsp_VerifyEncodedResponse : public ::testing::Test
70 {
71 public:
SetUpTestSuite()72   static void SetUpTestSuite()
73   {
74     rootKeyPair.reset(GenerateKeyPair());
75     if (!rootKeyPair) {
76       abort();
77     }
78   }
79 
SetUp()80   void SetUp()
81   {
82     rootNameDER = CNToDERName(rootName);
83     if (ENCODING_FAILED(rootNameDER)) {
84       abort();
85     }
86     Input rootNameDERInput;
87     if (rootNameDERInput.Init(rootNameDER.data(), rootNameDER.length())
88           != Success) {
89       abort();
90     }
91 
92     serialNumberDER =
93       CreateEncodedSerialNumber(static_cast<long>(++rootIssuedCount));
94     if (ENCODING_FAILED(serialNumberDER)) {
95       abort();
96     }
97     Input serialNumberDERInput;
98     if (serialNumberDERInput.Init(serialNumberDER.data(),
99                                   serialNumberDER.length()) != Success) {
100       abort();
101     }
102 
103     Input rootSPKIDER;
104     if (rootSPKIDER.Init(rootKeyPair->subjectPublicKeyInfo.data(),
105                          rootKeyPair->subjectPublicKeyInfo.length())
106           != Success) {
107       abort();
108     }
109     endEntityCertID.reset(new (std::nothrow) CertID(rootNameDERInput, rootSPKIDER,
110                                                     serialNumberDERInput));
111     if (!endEntityCertID) {
112       abort();
113     }
114   }
115 
116   static ScopedTestKeyPair rootKeyPair;
117   static uint32_t rootIssuedCount;
118   OCSPTestTrustDomain trustDomain;
119 
120   // endEntityCertID references rootKeyPair, rootNameDER, and serialNumberDER.
121   ByteString rootNameDER;
122   ByteString serialNumberDER;
123   // endEntityCertID references rootKeyPair, rootNameDER, and serialNumberDER.
124   ScopedCertID endEntityCertID;
125 };
126 
127 /*static*/ ScopedTestKeyPair pkixocsp_VerifyEncodedResponse::rootKeyPair;
128 /*static*/ uint32_t pkixocsp_VerifyEncodedResponse::rootIssuedCount = 0;
129 
130 ///////////////////////////////////////////////////////////////////////////////
131 // responseStatus
132 
133 struct WithoutResponseBytes
134 {
135   uint8_t responseStatus;
136   Result expectedError;
137 };
138 
139 static const WithoutResponseBytes WITHOUT_RESPONSEBYTES[] = {
140   { OCSPResponseContext::successful, Result::ERROR_OCSP_MALFORMED_RESPONSE },
141   { OCSPResponseContext::malformedRequest, Result::ERROR_OCSP_MALFORMED_REQUEST },
142   { OCSPResponseContext::internalError, Result::ERROR_OCSP_SERVER_ERROR },
143   { OCSPResponseContext::tryLater, Result::ERROR_OCSP_TRY_SERVER_LATER },
144   { 4/*unused*/, Result::ERROR_OCSP_UNKNOWN_RESPONSE_STATUS },
145   { OCSPResponseContext::sigRequired, Result::ERROR_OCSP_REQUEST_NEEDS_SIG },
146   { OCSPResponseContext::unauthorized, Result::ERROR_OCSP_UNAUTHORIZED_REQUEST },
147   { OCSPResponseContext::unauthorized + 1,
148     Result::ERROR_OCSP_UNKNOWN_RESPONSE_STATUS
149   },
150 };
151 
152 class pkixocsp_VerifyEncodedResponse_WithoutResponseBytes
153   : public pkixocsp_VerifyEncodedResponse
154   , public ::testing::WithParamInterface<WithoutResponseBytes>
155 {
156 protected:
CreateEncodedOCSPErrorResponse(uint8_t status)157   ByteString CreateEncodedOCSPErrorResponse(uint8_t status)
158   {
159     static const Input EMPTY;
160     OCSPResponseContext context(CertID(EMPTY, EMPTY, EMPTY),
161                                 oneDayBeforeNow);
162     context.responseStatus = status;
163     context.skipResponseBytes = true;
164     return CreateEncodedOCSPResponse(context);
165   }
166 };
167 
TEST_P(pkixocsp_VerifyEncodedResponse_WithoutResponseBytes,CorrectErrorCode)168 TEST_P(pkixocsp_VerifyEncodedResponse_WithoutResponseBytes, CorrectErrorCode)
169 {
170   ByteString
171     responseString(CreateEncodedOCSPErrorResponse(GetParam().responseStatus));
172   Input response;
173   ASSERT_EQ(Success,
174             response.Init(responseString.data(), responseString.length()));
175   bool expired;
176   ASSERT_EQ(GetParam().expectedError,
177             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
178                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
179                                       response, expired));
180 }
181 
182 INSTANTIATE_TEST_SUITE_P(pkixocsp_VerifyEncodedResponse_WithoutResponseBytes,
183                         pkixocsp_VerifyEncodedResponse_WithoutResponseBytes,
184                         testing::ValuesIn(WITHOUT_RESPONSEBYTES));
185 
186 ///////////////////////////////////////////////////////////////////////////////
187 // "successful" responses
188 
189 namespace {
190 
191 // Alias for nullptr to aid readability in the code below.
192 static const char* byKey = nullptr;
193 
194 } // namespace
195 
196 class pkixocsp_VerifyEncodedResponse_successful
197   : public pkixocsp_VerifyEncodedResponse
198 {
199 public:
SetUp()200   void SetUp()
201   {
202     pkixocsp_VerifyEncodedResponse::SetUp();
203   }
204 
SetUpTestSuite()205   static void SetUpTestSuite()
206   {
207     pkixocsp_VerifyEncodedResponse::SetUpTestSuite();
208   }
209 
CreateEncodedOCSPSuccessfulResponse(OCSPResponseContext::CertStatus certStatus,const CertID & certID,const char * signerName,const TestKeyPair & signerKeyPair,time_t producedAt,time_t thisUpdate,const time_t * nextUpdate,const TestSignatureAlgorithm & signatureAlgorithm,const ByteString * certs=nullptr,OCSPResponseExtension * singleExtensions=nullptr,OCSPResponseExtension * responseExtensions=nullptr,DigestAlgorithm certIDHashAlgorithm=DigestAlgorithm::sha1,ByteString certIDHashAlgorithmEncoded=ByteString ())210   ByteString CreateEncodedOCSPSuccessfulResponse(
211                     OCSPResponseContext::CertStatus certStatus,
212                     const CertID& certID,
213        /*optional*/ const char* signerName,
214                     const TestKeyPair& signerKeyPair,
215                     time_t producedAt, time_t thisUpdate,
216        /*optional*/ const time_t* nextUpdate,
217                     const TestSignatureAlgorithm& signatureAlgorithm,
218        /*optional*/ const ByteString* certs = nullptr,
219        /*optional*/ OCSPResponseExtension* singleExtensions = nullptr,
220        /*optional*/ OCSPResponseExtension* responseExtensions = nullptr,
221        /*optional*/ DigestAlgorithm certIDHashAlgorithm = DigestAlgorithm::sha1,
222        /*optional*/ ByteString certIDHashAlgorithmEncoded = ByteString())
223   {
224     OCSPResponseContext context(certID, producedAt);
225     context.certIDHashAlgorithm = certIDHashAlgorithm;
226     context.certIDHashAlgorithmEncoded = certIDHashAlgorithmEncoded;
227     if (signerName) {
228       context.signerNameDER = CNToDERName(signerName);
229       EXPECT_FALSE(ENCODING_FAILED(context.signerNameDER));
230     }
231     context.signerKeyPair.reset(signerKeyPair.Clone());
232     EXPECT_TRUE(context.signerKeyPair.get());
233     context.responseStatus = OCSPResponseContext::successful;
234     context.producedAt = producedAt;
235     context.signatureAlgorithm = signatureAlgorithm;
236     context.certs = certs;
237     context.singleExtensions = singleExtensions;
238     context.responseExtensions = responseExtensions;
239 
240     context.certStatus = static_cast<uint8_t>(certStatus);
241     context.thisUpdate = thisUpdate;
242     context.nextUpdate = nextUpdate ? *nextUpdate : 0;
243     context.includeNextUpdate = nextUpdate != nullptr;
244 
245     return CreateEncodedOCSPResponse(context);
246   }
247 };
248 
TEST_F(pkixocsp_VerifyEncodedResponse_successful,good_byKey)249 TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byKey)
250 {
251   ByteString responseString(
252                CreateEncodedOCSPSuccessfulResponse(
253                          OCSPResponseContext::good, *endEntityCertID, byKey,
254                          *rootKeyPair, oneDayBeforeNow,
255                          oneDayBeforeNow, &oneDayAfterNow,
256                          sha256WithRSAEncryption()));
257   Input response;
258   ASSERT_EQ(Success,
259             response.Init(responseString.data(), responseString.length()));
260   bool expired;
261   ASSERT_EQ(Success,
262             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
263                                       Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
264                                       response, expired));
265   ASSERT_FALSE(expired);
266 }
267 
TEST_F(pkixocsp_VerifyEncodedResponse_successful,good_byName)268 TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byName)
269 {
270   ByteString responseString(
271                CreateEncodedOCSPSuccessfulResponse(
272                          OCSPResponseContext::good, *endEntityCertID, rootName,
273                          *rootKeyPair, oneDayBeforeNow,
274                          oneDayBeforeNow, &oneDayAfterNow,
275                          sha256WithRSAEncryption()));
276   Input response;
277   ASSERT_EQ(Success,
278             response.Init(responseString.data(), responseString.length()));
279   bool expired;
280   ASSERT_EQ(Success,
281             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
282                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
283                                       response, expired));
284   ASSERT_FALSE(expired);
285 }
286 
TEST_F(pkixocsp_VerifyEncodedResponse_successful,good_byKey_without_nextUpdate)287 TEST_F(pkixocsp_VerifyEncodedResponse_successful, good_byKey_without_nextUpdate)
288 {
289   ByteString responseString(
290                CreateEncodedOCSPSuccessfulResponse(
291                          OCSPResponseContext::good, *endEntityCertID, byKey,
292                          *rootKeyPair, oneDayBeforeNow,
293                          oneDayBeforeNow, nullptr,
294                          sha256WithRSAEncryption()));
295   Input response;
296   ASSERT_EQ(Success,
297             response.Init(responseString.data(), responseString.length()));
298   bool expired;
299   ASSERT_EQ(Success,
300             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
301                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
302                                       response, expired));
303   ASSERT_FALSE(expired);
304 }
305 
TEST_F(pkixocsp_VerifyEncodedResponse_successful,revoked)306 TEST_F(pkixocsp_VerifyEncodedResponse_successful, revoked)
307 {
308   ByteString responseString(
309                CreateEncodedOCSPSuccessfulResponse(
310                          OCSPResponseContext::revoked, *endEntityCertID, byKey,
311                          *rootKeyPair, oneDayBeforeNow,
312                          oneDayBeforeNow, &oneDayAfterNow,
313                          sha256WithRSAEncryption()));
314   Input response;
315   ASSERT_EQ(Success,
316             response.Init(responseString.data(), responseString.length()));
317   bool expired;
318   ASSERT_EQ(Result::ERROR_REVOKED_CERTIFICATE,
319             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
320                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
321                                       response, expired));
322   ASSERT_FALSE(expired);
323 }
324 
TEST_F(pkixocsp_VerifyEncodedResponse_successful,unknown)325 TEST_F(pkixocsp_VerifyEncodedResponse_successful, unknown)
326 {
327   ByteString responseString(
328                CreateEncodedOCSPSuccessfulResponse(
329                          OCSPResponseContext::unknown, *endEntityCertID, byKey,
330                          *rootKeyPair, oneDayBeforeNow,
331                          oneDayBeforeNow, &oneDayAfterNow,
332                          sha256WithRSAEncryption()));
333   Input response;
334   ASSERT_EQ(Success,
335             response.Init(responseString.data(), responseString.length()));
336   bool expired;
337   ASSERT_EQ(Result::ERROR_OCSP_UNKNOWN_CERT,
338             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
339                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
340                                       response, expired));
341   ASSERT_FALSE(expired);
342 }
343 
TEST_F(pkixocsp_VerifyEncodedResponse_successful,good_unsupportedSignatureAlgorithm)344 TEST_F(pkixocsp_VerifyEncodedResponse_successful,
345        good_unsupportedSignatureAlgorithm)
346 {
347   PRUint32 policyMd5;
348   ASSERT_EQ(SECSuccess,NSS_GetAlgorithmPolicy(SEC_OID_MD5, &policyMd5));
349 
350   /* our encode won't work if MD5 isn't allowed by policy */
351   ASSERT_EQ(SECSuccess,
352             NSS_SetAlgorithmPolicy(SEC_OID_MD5, NSS_USE_ALG_IN_SIGNATURE, 0));
353   ByteString responseString(
354                CreateEncodedOCSPSuccessfulResponse(
355                          OCSPResponseContext::good, *endEntityCertID, byKey,
356                          *rootKeyPair, oneDayBeforeNow,
357                          oneDayBeforeNow, &oneDayAfterNow,
358                          md5WithRSAEncryption()));
359   Input response;
360   ASSERT_EQ(Success,
361             response.Init(responseString.data(), responseString.length()));
362   /* now restore the existing policy */
363   ASSERT_EQ(SECSuccess,
364            NSS_SetAlgorithmPolicy(SEC_OID_MD5, policyMd5, NSS_USE_ALG_IN_SIGNATURE));
365   bool expired;
366   ASSERT_EQ(Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED,
367             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
368                                       Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
369                                       response, expired));
370   ASSERT_FALSE(expired);
371 }
372 
373 // Added for bug 1079436. The output variable validThrough represents the
374 // latest time for which VerifyEncodedOCSPResponse will succeed, which is
375 // different from the nextUpdate time in the OCSP response due to the slop we
376 // add for time comparisons to deal with clock skew.
TEST_F(pkixocsp_VerifyEncodedResponse_successful,check_validThrough)377 TEST_F(pkixocsp_VerifyEncodedResponse_successful, check_validThrough)
378 {
379   ByteString responseString(
380                CreateEncodedOCSPSuccessfulResponse(
381                          OCSPResponseContext::good, *endEntityCertID, byKey,
382                          *rootKeyPair, oneDayBeforeNow,
383                          oneDayBeforeNow, &oneDayAfterNow,
384                          sha256WithRSAEncryption()));
385   Time validThrough(Time::uninitialized);
386   {
387     Input response;
388     ASSERT_EQ(Success,
389               response.Init(responseString.data(), responseString.length()));
390     bool expired;
391     ASSERT_EQ(Success,
392               VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
393                                         Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
394                                         response, expired, nullptr,
395                                         &validThrough));
396     ASSERT_FALSE(expired);
397     // The response was created to be valid until one day after now, so the
398     // value we got for validThrough should be after that.
399     Time oneDayAfterNowAsPKIXTime(
400           TimeFromEpochInSeconds(static_cast<uint64_t>(oneDayAfterNow)));
401     ASSERT_TRUE(validThrough > oneDayAfterNowAsPKIXTime);
402   }
403   {
404     Input response;
405     ASSERT_EQ(Success,
406               response.Init(responseString.data(), responseString.length()));
407     bool expired;
408     // Given validThrough from a previous verification, this response should be
409     // valid through that time.
410     ASSERT_EQ(Success,
411               VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
412                                         validThrough, END_ENTITY_MAX_LIFETIME_IN_DAYS,
413                                         response, expired));
414     ASSERT_FALSE(expired);
415   }
416   {
417     Time noLongerValid(validThrough);
418     ASSERT_EQ(Success, noLongerValid.AddSeconds(1));
419     Input response;
420     ASSERT_EQ(Success,
421               response.Init(responseString.data(), responseString.length()));
422     bool expired;
423     // The verification time is now after when the response will be considered
424     // valid.
425     ASSERT_EQ(Result::ERROR_OCSP_OLD_RESPONSE,
426               VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
427                                         noLongerValid, END_ENTITY_MAX_LIFETIME_IN_DAYS,
428                                         response, expired));
429     ASSERT_TRUE(expired);
430   }
431 }
432 
TEST_F(pkixocsp_VerifyEncodedResponse_successful,ct_extension)433 TEST_F(pkixocsp_VerifyEncodedResponse_successful, ct_extension)
434 {
435   // python DottedOIDToCode.py --tlv
436   //   id_ocsp_singleExtensionSctList 1.3.6.1.4.1.11129.2.4.5
437   static const uint8_t tlv_id_ocsp_singleExtensionSctList[] = {
438     0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x04, 0x05
439   };
440   static const uint8_t dummySctList[] = {
441     0x01, 0x02, 0x03, 0x04, 0x05
442   };
443 
444   OCSPResponseExtension ctExtension;
445   ctExtension.id = BytesToByteString(tlv_id_ocsp_singleExtensionSctList);
446   // SignedCertificateTimestampList structure is encoded as an OCTET STRING
447   // within the extension value (see RFC 6962 section 3.3).
448   // pkix decodes it internally and returns the actual structure.
449   ctExtension.value = TLV(der::OCTET_STRING, BytesToByteString(dummySctList));
450 
451   ByteString responseString(
452                CreateEncodedOCSPSuccessfulResponse(
453                          OCSPResponseContext::good, *endEntityCertID, byKey,
454                          *rootKeyPair, oneDayBeforeNow,
455                          oneDayBeforeNow, &oneDayAfterNow,
456                          sha256WithRSAEncryption(),
457                          /*certs*/ nullptr,
458                          &ctExtension));
459   Input response;
460   ASSERT_EQ(Success,
461             response.Init(responseString.data(), responseString.length()));
462 
463   bool expired;
464   ASSERT_EQ(Success,
465             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
466                                       Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
467                                       response, expired));
468   ASSERT_FALSE(expired);
469   ASSERT_EQ(BytesToByteString(dummySctList),
470             trustDomain.signedCertificateTimestamps);
471 }
472 
473 struct CertIDHashAlgorithm
474 {
475   DigestAlgorithm hashAlgorithm;
476   ByteString encodedHashAlgorithm;
477   Result expectedResult;
478 };
479 
480 // python DottedOIDToCode.py --alg id-sha1 1.3.14.3.2.26
481 static const uint8_t alg_id_sha1[] = {
482   0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a
483 };
484 // python DottedOIDToCode.py --alg id-sha256 2.16.840.1.101.3.4.2.1
485 static const uint8_t alg_id_sha256[] = {
486   0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
487 };
488 static const uint8_t not_an_encoded_hash_oid[] = {
489   0x01, 0x02, 0x03, 0x04
490 };
491 
492 static const CertIDHashAlgorithm CERTID_HASH_ALGORITHMS[] = {
493   { DigestAlgorithm::sha1, ByteString(), Success },
494   { DigestAlgorithm::sha256, ByteString(), Success },
495   { DigestAlgorithm::sha384, ByteString(), Success },
496   { DigestAlgorithm::sha512, ByteString(), Success },
497   { DigestAlgorithm::sha256, BytesToByteString(alg_id_sha1),
498     Result::ERROR_OCSP_MALFORMED_RESPONSE },
499   { DigestAlgorithm::sha1, BytesToByteString(alg_id_sha256),
500     Result::ERROR_OCSP_MALFORMED_RESPONSE },
501   { DigestAlgorithm::sha1, BytesToByteString(not_an_encoded_hash_oid),
502     Result::ERROR_OCSP_MALFORMED_RESPONSE },
503 };
504 
505 class pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm
506   : public pkixocsp_VerifyEncodedResponse_successful
507   , public ::testing::WithParamInterface<CertIDHashAlgorithm>
508 {
509 };
510 
TEST_P(pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm,CertIDHashAlgorithm)511 TEST_P(pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm, CertIDHashAlgorithm)
512 {
513   ByteString responseString(
514                CreateEncodedOCSPSuccessfulResponse(
515                          OCSPResponseContext::good, *endEntityCertID, byKey,
516                          *rootKeyPair, oneDayBeforeNow,
517                          oneDayBeforeNow, &oneDayAfterNow,
518                          sha256WithRSAEncryption(),
519                          nullptr,
520                          nullptr,
521                          nullptr,
522                          GetParam().hashAlgorithm,
523                          GetParam().encodedHashAlgorithm));
524   Input response;
525   ASSERT_EQ(Success,
526             response.Init(responseString.data(), responseString.length()));
527   bool expired;
528   ASSERT_EQ(GetParam().expectedResult,
529             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
530                                       Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
531                                       response, expired));
532   ASSERT_FALSE(expired);
533 }
534 
535 INSTANTIATE_TEST_SUITE_P(pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm,
536                         pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm,
537                         testing::ValuesIn(CERTID_HASH_ALGORITHMS));
538 
539 ///////////////////////////////////////////////////////////////////////////////
540 // indirect responses (signed by a delegated OCSP responder cert)
541 
542 class pkixocsp_VerifyEncodedResponse_DelegatedResponder
543   : public pkixocsp_VerifyEncodedResponse_successful
544 {
545 protected:
546   // certSubjectName should be unique for each call. This way, we avoid any
547   // issues with NSS caching the certificates internally. For the same reason,
548   // we generate a new keypair on each call. Either one of these should be
549   // sufficient to avoid issues with the NSS cache, but we do both to be
550   // cautious.
551   //
552   // signerName should be byKey to use the byKey ResponderID construction, or
553   // another value (usually equal to certSubjectName) to use the byName
554   // ResponderID construction.
555   //
556   // certSignatureAlgorithm specifies the signature algorithm that the
557   // certificate will be signed with, not the OCSP response.
558   //
559   // If signerEKU is omitted, then the certificate will have the
560   // id-kp-OCSPSigning EKU. If signerEKU is SEC_OID_UNKNOWN then it will not
561   // have any EKU extension. Otherwise, the certificate will have the given
562   // EKU.
CreateEncodedIndirectOCSPSuccessfulResponse(const char * certSubjectName,OCSPResponseContext::CertStatus certStatus,const char * signerName,const TestSignatureAlgorithm & certSignatureAlgorithm,const Input * signerEKUDER=& OCSPSigningEKUDER,ByteString * signerDEROut=nullptr)563   ByteString CreateEncodedIndirectOCSPSuccessfulResponse(
564                const char* certSubjectName,
565                OCSPResponseContext::CertStatus certStatus,
566                const char* signerName,
567                const TestSignatureAlgorithm& certSignatureAlgorithm,
568                /*optional*/ const Input* signerEKUDER = &OCSPSigningEKUDER,
569                /*optional, out*/ ByteString* signerDEROut = nullptr)
570   {
571     assert(certSubjectName);
572 
573     const ByteString extensions[] = {
574       signerEKUDER
575         ? CreateEncodedEKUExtension(*signerEKUDER, Critical::No)
576         : ByteString(),
577       ByteString()
578     };
579     ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
580     ByteString signerDER(CreateEncodedCertificate(
581                            ++rootIssuedCount, certSignatureAlgorithm,
582                            rootName, oneDayBeforeNow, oneDayAfterNow,
583                            certSubjectName, *signerKeyPair,
584                            signerEKUDER ? extensions : nullptr,
585                            *rootKeyPair));
586     EXPECT_FALSE(ENCODING_FAILED(signerDER));
587     if (signerDEROut) {
588       *signerDEROut = signerDER;
589     }
590 
591     ByteString signerNameDER;
592     if (signerName) {
593       signerNameDER = CNToDERName(signerName);
594       EXPECT_FALSE(ENCODING_FAILED(signerNameDER));
595     }
596     ByteString certs[] = { signerDER, ByteString() };
597     return CreateEncodedOCSPSuccessfulResponse(certStatus, *endEntityCertID,
598                                                signerName, *signerKeyPair,
599                                                oneDayBeforeNow,
600                                                oneDayBeforeNow,
601                                                &oneDayAfterNow,
602                                                sha256WithRSAEncryption(),
603                                                certs);
604   }
605 
CreateEncodedCertificate(uint32_t serialNumber,const TestSignatureAlgorithm & signatureAlg,const char * issuer,time_t notBefore,time_t notAfter,const char * subject,const TestKeyPair & subjectKeyPair,const ByteString * extensions,const TestKeyPair & signerKeyPair)606   static ByteString CreateEncodedCertificate(uint32_t serialNumber,
607                                              const TestSignatureAlgorithm& signatureAlg,
608                                              const char* issuer,
609                                              time_t notBefore,
610                                              time_t notAfter,
611                                              const char* subject,
612                                              const TestKeyPair& subjectKeyPair,
613                                 /*optional*/ const ByteString* extensions,
614                                              const TestKeyPair& signerKeyPair)
615   {
616     ByteString serialNumberDER(CreateEncodedSerialNumber(
617                                  static_cast<long>(serialNumber)));
618     if (ENCODING_FAILED(serialNumberDER)) {
619       return ByteString();
620     }
621     ByteString issuerDER(CNToDERName(issuer));
622     if (ENCODING_FAILED(issuerDER)) {
623       return ByteString();
624     }
625     ByteString subjectDER(CNToDERName(subject));
626     if (ENCODING_FAILED(subjectDER)) {
627       return ByteString();
628     }
629     return ::mozilla::pkix::test::CreateEncodedCertificate(
630                                     v3, signatureAlg, serialNumberDER,
631                                     issuerDER, notBefore, notAfter,
632                                     subjectDER, subjectKeyPair, extensions,
633                                     signerKeyPair, signatureAlg);
634   }
635 
636   static const Input OCSPSigningEKUDER;
637 };
638 
639 /*static*/ const Input pkixocsp_VerifyEncodedResponse_DelegatedResponder::
640   OCSPSigningEKUDER(tlv_id_kp_OCSPSigning);
641 
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_byKey)642 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_byKey)
643 {
644   ByteString responseString(
645                CreateEncodedIndirectOCSPSuccessfulResponse(
646                          "good_indirect_byKey", OCSPResponseContext::good,
647                          byKey, sha256WithRSAEncryption()));
648   Input response;
649   ASSERT_EQ(Success,
650             response.Init(responseString.data(), responseString.length()));
651   bool expired;
652   ASSERT_EQ(Success,
653             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
654                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
655                                       response, expired));
656   ASSERT_FALSE(expired);
657 }
658 
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_byName)659 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_byName)
660 {
661   ByteString responseString(
662                CreateEncodedIndirectOCSPSuccessfulResponse(
663                          "good_indirect_byName", OCSPResponseContext::good,
664                          "good_indirect_byName", sha256WithRSAEncryption()));
665   Input response;
666   ASSERT_EQ(Success,
667             response.Init(responseString.data(), responseString.length()));
668   bool expired;
669   ASSERT_EQ(Success,
670             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
671                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
672                                       response, expired));
673   ASSERT_FALSE(expired);
674 }
675 
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_byKey_missing_signer)676 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
677        good_byKey_missing_signer)
678 {
679   ScopedTestKeyPair missingSignerKeyPair(GenerateKeyPair());
680   ASSERT_TRUE(missingSignerKeyPair.get());
681 
682   ByteString responseString(
683                CreateEncodedOCSPSuccessfulResponse(
684                          OCSPResponseContext::good, *endEntityCertID, byKey,
685                          *missingSignerKeyPair, oneDayBeforeNow,
686                          oneDayBeforeNow, nullptr,
687                          sha256WithRSAEncryption()));
688   Input response;
689   ASSERT_EQ(Success,
690             response.Init(responseString.data(), responseString.length()));
691   bool expired;
692   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
693             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
694                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
695                                       response, expired));
696   ASSERT_FALSE(expired);
697 }
698 
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_byName_missing_signer)699 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
700        good_byName_missing_signer)
701 {
702   ScopedTestKeyPair missingSignerKeyPair(GenerateKeyPair());
703   ASSERT_TRUE(missingSignerKeyPair.get());
704   ByteString responseString(
705                CreateEncodedOCSPSuccessfulResponse(
706                          OCSPResponseContext::good, *endEntityCertID,
707                          "missing", *missingSignerKeyPair,
708                          oneDayBeforeNow, oneDayBeforeNow, nullptr,
709                          sha256WithRSAEncryption()));
710   Input response;
711   ASSERT_EQ(Success,
712             response.Init(responseString.data(), responseString.length()));
713   bool expired;
714   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
715             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
716                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
717                                       response, expired));
718   ASSERT_FALSE(expired);
719 }
720 
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_expired)721 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_expired)
722 {
723   static const char* signerName = "good_indirect_expired";
724 
725   const ByteString extensions[] = {
726     CreateEncodedEKUExtension(OCSPSigningEKUDER, Critical::No),
727     ByteString()
728   };
729 
730   ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
731   ByteString signerDER(CreateEncodedCertificate(
732                           ++rootIssuedCount, sha256WithRSAEncryption(),
733                           rootName,
734                           tenDaysBeforeNow,
735                           twoDaysBeforeNow,
736                           signerName, *signerKeyPair, extensions,
737                           *rootKeyPair));
738   ASSERT_FALSE(ENCODING_FAILED(signerDER));
739 
740   ByteString certs[] = { signerDER, ByteString() };
741   ByteString responseString(
742                CreateEncodedOCSPSuccessfulResponse(
743                          OCSPResponseContext::good, *endEntityCertID,
744                          signerName, *signerKeyPair, oneDayBeforeNow,
745                          oneDayBeforeNow, &oneDayAfterNow,
746                          sha256WithRSAEncryption(), certs));
747   Input response;
748   ASSERT_EQ(Success,
749             response.Init(responseString.data(), responseString.length()));
750   bool expired;
751   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
752             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
753                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
754                                       response, expired));
755 }
756 
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_future)757 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_future)
758 {
759   static const char* signerName = "good_indirect_future";
760 
761   const ByteString extensions[] = {
762     CreateEncodedEKUExtension(OCSPSigningEKUDER, Critical::No),
763     ByteString()
764   };
765 
766   ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
767   ByteString signerDER(CreateEncodedCertificate(
768                          ++rootIssuedCount, sha256WithRSAEncryption(),
769                          rootName,
770                          twoDaysAfterNow,
771                          tenDaysAfterNow,
772                          signerName, *signerKeyPair, extensions,
773                          *rootKeyPair));
774   ASSERT_FALSE(ENCODING_FAILED(signerDER));
775 
776   ByteString certs[] = { signerDER, ByteString() };
777   ByteString responseString(
778                CreateEncodedOCSPSuccessfulResponse(
779                          OCSPResponseContext::good, *endEntityCertID,
780                          signerName, *signerKeyPair, oneDayBeforeNow,
781                          oneDayBeforeNow, &oneDayAfterNow,
782                          sha256WithRSAEncryption(), certs));
783   Input response;
784   ASSERT_EQ(Success,
785             response.Init(responseString.data(), responseString.length()));
786   bool expired;
787   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
788             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
789                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
790                                       response, expired));
791   ASSERT_FALSE(expired);
792 }
793 
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_no_eku)794 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_no_eku)
795 {
796   ByteString responseString(
797                CreateEncodedIndirectOCSPSuccessfulResponse(
798                          "good_indirect_wrong_eku",
799                          OCSPResponseContext::good, byKey,
800                          sha256WithRSAEncryption(), nullptr));
801   Input response;
802   ASSERT_EQ(Success,
803             response.Init(responseString.data(), responseString.length()));
804   bool expired;
805   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
806             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
807                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
808                                       response, expired));
809   ASSERT_FALSE(expired);
810 }
811 
812 static const Input serverAuthEKUDER(tlv_id_kp_serverAuth);
813 
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_indirect_wrong_eku)814 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
815        good_indirect_wrong_eku)
816 {
817   ByteString responseString(
818                CreateEncodedIndirectOCSPSuccessfulResponse(
819                         "good_indirect_wrong_eku",
820                         OCSPResponseContext::good, byKey,
821                         sha256WithRSAEncryption(), &serverAuthEKUDER));
822   Input response;
823   ASSERT_EQ(Success,
824             response.Init(responseString.data(), responseString.length()));
825   bool expired;
826   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
827             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
828                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
829                                       response, expired));
830   ASSERT_FALSE(expired);
831 }
832 
833 // Test that signature of OCSP response signer cert is verified
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_tampered_eku)834 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_tampered_eku)
835 {
836   ByteString tamperedResponse(
837                CreateEncodedIndirectOCSPSuccessfulResponse(
838                          "good_indirect_tampered_eku",
839                          OCSPResponseContext::good, byKey,
840                          sha256WithRSAEncryption(), &serverAuthEKUDER));
841   ASSERT_EQ(Success,
842             TamperOnce(tamperedResponse,
843                        ByteString(tlv_id_kp_serverAuth,
844                                   sizeof(tlv_id_kp_serverAuth)),
845                        ByteString(tlv_id_kp_OCSPSigning,
846                                   sizeof(tlv_id_kp_OCSPSigning))));
847   Input tamperedResponseInput;
848   ASSERT_EQ(Success, tamperedResponseInput.Init(tamperedResponse.data(),
849                                                 tamperedResponse.length()));
850   bool expired;
851   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
852             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
853                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
854                                       tamperedResponseInput, expired));
855   ASSERT_FALSE(expired);
856 }
857 
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_unknown_issuer)858 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_unknown_issuer)
859 {
860   static const char* subCAName = "good_indirect_unknown_issuer sub-CA";
861   static const char* signerName = "good_indirect_unknown_issuer OCSP signer";
862 
863   // unknown issuer
864   ScopedTestKeyPair unknownKeyPair(GenerateKeyPair());
865   ASSERT_TRUE(unknownKeyPair.get());
866 
867   // Delegated responder cert signed by unknown issuer
868   const ByteString extensions[] = {
869     CreateEncodedEKUExtension(OCSPSigningEKUDER, Critical::No),
870     ByteString()
871   };
872   ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
873   ByteString signerDER(CreateEncodedCertificate(
874                          1, sha256WithRSAEncryption(), subCAName,
875                          oneDayBeforeNow, oneDayAfterNow, signerName,
876                          *signerKeyPair, extensions, *unknownKeyPair));
877   ASSERT_FALSE(ENCODING_FAILED(signerDER));
878 
879   // OCSP response signed by that delegated responder
880   ByteString certs[] = { signerDER, ByteString() };
881   ByteString responseString(
882                CreateEncodedOCSPSuccessfulResponse(
883                          OCSPResponseContext::good, *endEntityCertID,
884                          signerName, *signerKeyPair, oneDayBeforeNow,
885                          oneDayBeforeNow, &oneDayAfterNow,
886                          sha256WithRSAEncryption(), certs));
887   Input response;
888   ASSERT_EQ(Success,
889             response.Init(responseString.data(), responseString.length()));
890   bool expired;
891   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
892             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
893                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
894                                       response, expired));
895   ASSERT_FALSE(expired);
896 }
897 
898 // The CA that issued the OCSP responder cert is a sub-CA of the issuer of
899 // the certificate that the OCSP response is for. That sub-CA cert is included
900 // in the OCSP response before the OCSP responder cert.
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_indirect_subca_1_first)901 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
902        good_indirect_subca_1_first)
903 {
904   static const char* subCAName = "good_indirect_subca_1_first sub-CA";
905   static const char* signerName = "good_indirect_subca_1_first OCSP signer";
906   static const long zero = 0;
907 
908   // sub-CA of root (root is the direct issuer of endEntity)
909   const ByteString subCAExtensions[] = {
910     CreateEncodedBasicConstraints(true, &zero, Critical::No),
911     ByteString()
912   };
913   ScopedTestKeyPair subCAKeyPair(GenerateKeyPair());
914   ByteString subCADER(CreateEncodedCertificate(
915                         ++rootIssuedCount, sha256WithRSAEncryption(), rootName,
916                         oneDayBeforeNow, oneDayAfterNow, subCAName,
917                         *subCAKeyPair, subCAExtensions, *rootKeyPair));
918   ASSERT_FALSE(ENCODING_FAILED(subCADER));
919 
920   // Delegated responder cert signed by that sub-CA
921   const ByteString extensions[] = {
922     CreateEncodedEKUExtension(OCSPSigningEKUDER, Critical::No),
923     ByteString(),
924   };
925   ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
926   ByteString signerDER(CreateEncodedCertificate(
927                          1, sha256WithRSAEncryption(), subCAName,
928                          oneDayBeforeNow, oneDayAfterNow, signerName,
929                          *signerKeyPair, extensions, *subCAKeyPair));
930   ASSERT_FALSE(ENCODING_FAILED(signerDER));
931 
932   // OCSP response signed by the delegated responder issued by the sub-CA
933   // that is trying to impersonate the root.
934   ByteString certs[] = { subCADER, signerDER, ByteString() };
935   ByteString responseString(
936                CreateEncodedOCSPSuccessfulResponse(
937                          OCSPResponseContext::good, *endEntityCertID,
938                          signerName, *signerKeyPair, oneDayBeforeNow,
939                          oneDayBeforeNow, &oneDayAfterNow,
940                          sha256WithRSAEncryption(), certs));
941   Input response;
942   ASSERT_EQ(Success,
943             response.Init(responseString.data(), responseString.length()));
944   bool expired;
945   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
946             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
947                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
948                                       response, expired));
949   ASSERT_FALSE(expired);
950 }
951 
952 // The CA that issued the OCSP responder cert is a sub-CA of the issuer of
953 // the certificate that the OCSP response is for. That sub-CA cert is included
954 // in the OCSP response after the OCSP responder cert.
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_indirect_subca_1_second)955 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
956        good_indirect_subca_1_second)
957 {
958   static const char* subCAName = "good_indirect_subca_1_second sub-CA";
959   static const char* signerName = "good_indirect_subca_1_second OCSP signer";
960   static const long zero = 0;
961 
962   // sub-CA of root (root is the direct issuer of endEntity)
963   const ByteString subCAExtensions[] = {
964     CreateEncodedBasicConstraints(true, &zero, Critical::No),
965     ByteString()
966   };
967   ScopedTestKeyPair subCAKeyPair(GenerateKeyPair());
968   ByteString subCADER(CreateEncodedCertificate(++rootIssuedCount,
969                                                sha256WithRSAEncryption(),
970                                                rootName,
971                                                oneDayBeforeNow, oneDayAfterNow,
972                                                subCAName, *subCAKeyPair,
973                                                subCAExtensions, *rootKeyPair));
974   ASSERT_FALSE(ENCODING_FAILED(subCADER));
975 
976   // Delegated responder cert signed by that sub-CA
977   const ByteString extensions[] = {
978     CreateEncodedEKUExtension(OCSPSigningEKUDER, Critical::No),
979     ByteString()
980   };
981   ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
982   ByteString signerDER(CreateEncodedCertificate(
983                          1, sha256WithRSAEncryption(), subCAName,
984                          oneDayBeforeNow, oneDayAfterNow, signerName,
985                          *signerKeyPair, extensions, *subCAKeyPair));
986   ASSERT_FALSE(ENCODING_FAILED(signerDER));
987 
988   // OCSP response signed by the delegated responder issued by the sub-CA
989   // that is trying to impersonate the root.
990   ByteString certs[] = { signerDER, subCADER, ByteString() };
991   ByteString responseString(
992                  CreateEncodedOCSPSuccessfulResponse(
993                          OCSPResponseContext::good, *endEntityCertID,
994                          signerName, *signerKeyPair, oneDayBeforeNow,
995                          oneDayBeforeNow, &oneDayAfterNow,
996                          sha256WithRSAEncryption(), certs));
997   Input response;
998   ASSERT_EQ(Success,
999             response.Init(responseString.data(), responseString.length()));
1000   bool expired;
1001   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
1002             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
1003                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
1004                                       response, expired));
1005   ASSERT_FALSE(expired);
1006 }
1007 
TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,good_unsupportedSignatureAlgorithmOnResponder)1008 TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
1009        good_unsupportedSignatureAlgorithmOnResponder)
1010 {
1011   // Note that the algorithm ID (md5WithRSAEncryption) identifies the signature
1012   // algorithm that will be used to sign the certificate that issues the OCSP
1013   // responses, not the responses themselves.
1014   PRUint32 policyMd5;
1015   ASSERT_EQ(SECSuccess,NSS_GetAlgorithmPolicy(SEC_OID_MD5, &policyMd5));
1016 
1017   /* our encode won't work if MD5 isn't allowed by policy */
1018   ASSERT_EQ(SECSuccess,
1019             NSS_SetAlgorithmPolicy(SEC_OID_MD5, NSS_USE_ALG_IN_SIGNATURE, 0));
1020   ByteString responseString(
1021                CreateEncodedIndirectOCSPSuccessfulResponse(
1022                          "good_indirect_unsupportedSignatureAlgorithm",
1023                          OCSPResponseContext::good, byKey,
1024                          md5WithRSAEncryption()));
1025   Input response;
1026   /* now restore the existing policy */
1027   ASSERT_EQ(Success,
1028             response.Init(responseString.data(), responseString.length()));
1029   ASSERT_EQ(SECSuccess,
1030             NSS_SetAlgorithmPolicy(SEC_OID_MD5, policyMd5, NSS_USE_ALG_IN_SIGNATURE));
1031   bool expired;
1032   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
1033             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
1034                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
1035                                       response, expired));
1036 }
1037 
1038 class pkixocsp_VerifyEncodedResponse_GetCertTrust
1039   : public pkixocsp_VerifyEncodedResponse_DelegatedResponder {
1040 public:
SetUp()1041   void SetUp()
1042   {
1043     pkixocsp_VerifyEncodedResponse_DelegatedResponder::SetUp();
1044 
1045     responseString =
1046         CreateEncodedIndirectOCSPSuccessfulResponse(
1047           "OCSPGetCertTrustTest Signer", OCSPResponseContext::good,
1048           byKey, sha256WithRSAEncryption(), &OCSPSigningEKUDER,
1049           &signerCertDER);
1050     if (ENCODING_FAILED(responseString)) {
1051       abort();
1052     }
1053     if (response.Init(responseString.data(), responseString.length())
1054           != Success) {
1055       abort();
1056     }
1057     if (signerCertDER.length() == 0) {
1058       abort();
1059     }
1060   }
1061 
1062   class TrustDomain final : public OCSPTestTrustDomain
1063   {
1064   public:
TrustDomain()1065     TrustDomain()
1066       : certTrustLevel(TrustLevel::InheritsTrust)
1067     {
1068     }
1069 
SetCertTrust(const ByteString & aCertDER,TrustLevel aCertTrustLevel)1070     bool SetCertTrust(const ByteString& aCertDER, TrustLevel aCertTrustLevel)
1071     {
1072       this->certDER = aCertDER;
1073       this->certTrustLevel = aCertTrustLevel;
1074       return true;
1075     }
1076   private:
GetCertTrust(EndEntityOrCA endEntityOrCA,const CertPolicyId &,Input candidateCert,TrustLevel & trustLevel)1077     Result GetCertTrust(EndEntityOrCA endEntityOrCA, const CertPolicyId&,
1078                         Input candidateCert, /*out*/ TrustLevel& trustLevel)
1079                         override
1080     {
1081       EXPECT_EQ(endEntityOrCA, EndEntityOrCA::MustBeEndEntity);
1082       EXPECT_FALSE(certDER.empty());
1083       Input certDERInput;
1084       EXPECT_EQ(Success, certDERInput.Init(certDER.data(), certDER.length()));
1085       EXPECT_TRUE(InputsAreEqual(certDERInput, candidateCert));
1086       trustLevel = certTrustLevel;
1087       return Success;
1088     }
1089 
1090     ByteString certDER;
1091     TrustLevel certTrustLevel;
1092   };
1093 
1094 // trustDomain deliberately shadows the inherited field so that it isn't used
1095 // by accident. See bug 1339921.
1096 // Unfortunately GCC can't parse __has_warning("-Wshadow-field") even if it's
1097 // the latter part of a conjunction that would evaluate to false, so we have to
1098 // wrap it in a separate preprocessor conditional rather than using &&.
1099 #if defined(__clang__)
1100   #if __has_warning("-Wshadow-field")
1101     #pragma clang diagnostic push
1102     #pragma clang diagnostic ignored "-Wshadow-field"
1103   #endif
1104 #endif
1105   TrustDomain trustDomain;
1106 #if defined(__clang__)
1107   #if __has_warning("-Wshadow-field")
1108     #pragma clang diagnostic pop
1109   #endif
1110 #endif
1111   ByteString signerCertDER;
1112   ByteString responseString;
1113   Input response; // references data in responseString
1114 };
1115 
TEST_F(pkixocsp_VerifyEncodedResponse_GetCertTrust,InheritTrust)1116 TEST_F(pkixocsp_VerifyEncodedResponse_GetCertTrust, InheritTrust)
1117 {
1118   ASSERT_TRUE(trustDomain.SetCertTrust(signerCertDER,
1119                                        TrustLevel::InheritsTrust));
1120   bool expired;
1121   ASSERT_EQ(Success,
1122             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
1123                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
1124                                       response, expired));
1125   ASSERT_FALSE(expired);
1126 }
1127 
TEST_F(pkixocsp_VerifyEncodedResponse_GetCertTrust,TrustAnchor)1128 TEST_F(pkixocsp_VerifyEncodedResponse_GetCertTrust, TrustAnchor)
1129 {
1130   ASSERT_TRUE(trustDomain.SetCertTrust(signerCertDER,
1131                                        TrustLevel::TrustAnchor));
1132   bool expired;
1133   ASSERT_EQ(Success,
1134             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
1135                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
1136                                       response, expired));
1137   ASSERT_FALSE(expired);
1138 }
1139 
TEST_F(pkixocsp_VerifyEncodedResponse_GetCertTrust,ActivelyDistrusted)1140 TEST_F(pkixocsp_VerifyEncodedResponse_GetCertTrust, ActivelyDistrusted)
1141 {
1142   ASSERT_TRUE(trustDomain.SetCertTrust(signerCertDER,
1143                                        TrustLevel::ActivelyDistrusted));
1144   Input responseInput;
1145   ASSERT_EQ(Success,
1146             responseInput.Init(responseString.data(),
1147                                responseString.length()));
1148   bool expired;
1149   ASSERT_EQ(Result::ERROR_OCSP_INVALID_SIGNING_CERT,
1150             VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID, Now(),
1151                                       END_ENTITY_MAX_LIFETIME_IN_DAYS,
1152                                       responseInput, expired));
1153   ASSERT_FALSE(expired);
1154 }
1155