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