ocsp.c (203268B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 * Implementation of OCSP services, for both client and server. 7 * (XXX, really, mostly just for client right now, but intended to do both.) 8 */ 9 10 #include "prerror.h" 11 #include "prprf.h" 12 #include "plarena.h" 13 #include "prnetdb.h" 14 15 #include "seccomon.h" 16 #include "secitem.h" 17 #include "secoidt.h" 18 #include "secasn1.h" 19 #include "secder.h" 20 #include "cert.h" 21 #include "certi.h" 22 #include "xconst.h" 23 #include "secerr.h" 24 #include "secoid.h" 25 #include "hasht.h" 26 #include "sechash.h" 27 #include "secasn1.h" 28 #include "plbase64.h" 29 #include "keyhi.h" 30 #include "cryptohi.h" 31 #include "ocsp.h" 32 #include "ocspti.h" 33 #include "ocspi.h" 34 #include "genname.h" 35 #include "certxutl.h" 36 #include "pk11func.h" /* for PK11_HashBuf */ 37 #include <stdarg.h> 38 #include <plhash.h> 39 40 #define DEFAULT_OCSP_CACHE_SIZE 1000 41 #define DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 1 * 60 * 60L 42 #define DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 24 * 60 * 60L 43 #define DEFAULT_OSCP_TIMEOUT_SECONDS 60 44 #define MICROSECONDS_PER_SECOND 1000000L 45 46 typedef struct OCSPCacheItemStr OCSPCacheItem; 47 typedef struct OCSPCacheDataStr OCSPCacheData; 48 49 struct OCSPCacheItemStr { 50 /* LRU linking */ 51 OCSPCacheItem *moreRecent; 52 OCSPCacheItem *lessRecent; 53 54 /* key */ 55 CERTOCSPCertID *certID; 56 /* CertID's arena also used to allocate "this" cache item */ 57 58 /* cache control information */ 59 PRTime nextFetchAttemptTime; 60 61 /* Cached contents. Use a separate arena, because lifetime is different */ 62 PLArenaPool *certStatusArena; /* NULL means: no cert status cached */ 63 ocspCertStatus certStatus; 64 65 /* This may contain an error code when no OCSP response is available. */ 66 SECErrorCodes missingResponseError; 67 68 PRPackedBool haveThisUpdate; 69 PRPackedBool haveNextUpdate; 70 PRTime thisUpdate; 71 PRTime nextUpdate; 72 }; 73 74 struct OCSPCacheDataStr { 75 PLHashTable *entries; 76 PRUint32 numberOfEntries; 77 OCSPCacheItem *MRUitem; /* most recently used cache item */ 78 OCSPCacheItem *LRUitem; /* least recently used cache item */ 79 }; 80 81 static struct OCSPGlobalStruct { 82 PRMonitor *monitor; 83 const SEC_HttpClientFcn *defaultHttpClientFcn; 84 PRInt32 maxCacheEntries; 85 PRUint32 minimumSecondsToNextFetchAttempt; 86 PRUint32 maximumSecondsToNextFetchAttempt; 87 PRUint32 timeoutSeconds; 88 OCSPCacheData cache; 89 SEC_OcspFailureMode ocspFailureMode; 90 CERT_StringFromCertFcn alternateOCSPAIAFcn; 91 PRBool forcePost; 92 } OCSP_Global = { NULL, 93 NULL, 94 DEFAULT_OCSP_CACHE_SIZE, 95 DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT, 96 DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT, 97 DEFAULT_OSCP_TIMEOUT_SECONDS, 98 { NULL, 0, NULL, NULL }, 99 ocspMode_FailureIsVerificationFailure, 100 NULL, 101 PR_FALSE }; 102 103 /* Forward declarations */ 104 static SECItem * 105 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena, 106 CERTOCSPRequest *request, 107 const char *location, 108 const char *method, 109 PRTime time, 110 PRBool addServiceLocator, 111 void *pwArg, 112 CERTOCSPRequest **pRequest); 113 static SECStatus 114 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle, 115 CERTOCSPCertID *certID, 116 CERTCertificate *cert, 117 PRTime time, 118 void *pwArg, 119 PRBool *certIDWasConsumed, 120 SECStatus *rv_ocsp); 121 122 static SECStatus 123 ocsp_GetDecodedVerifiedSingleResponseForID(CERTCertDBHandle *handle, 124 CERTOCSPCertID *certID, 125 CERTCertificate *cert, 126 PRTime time, 127 void *pwArg, 128 const SECItem *encodedResponse, 129 CERTOCSPResponse **pDecodedResponse, 130 CERTOCSPSingleResponse **pSingle); 131 132 static SECStatus 133 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, PRTime time); 134 135 static CERTOCSPCertID * 136 cert_DupOCSPCertID(const CERTOCSPCertID *src); 137 138 #ifndef DEBUG 139 #define OCSP_TRACE(msg) 140 #define OCSP_TRACE_TIME(msg, time) 141 #define OCSP_TRACE_CERT(cert) 142 #define OCSP_TRACE_CERTID(certid) 143 #else 144 #define OCSP_TRACE(msg) ocsp_Trace msg 145 #define OCSP_TRACE_TIME(msg, time) ocsp_dumpStringWithTime(msg, time) 146 #define OCSP_TRACE_CERT(cert) dumpCertificate(cert) 147 #define OCSP_TRACE_CERTID(certid) dumpCertID(certid) 148 149 #if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_MACOSX) 150 #define NSS_HAVE_GETENV 1 151 #endif 152 153 static PRBool 154 wantOcspTrace(void) 155 { 156 static PRBool firstTime = PR_TRUE; 157 static PRBool wantTrace = PR_FALSE; 158 159 #ifdef NSS_HAVE_GETENV 160 if (firstTime) { 161 char *ev = PR_GetEnvSecure("NSS_TRACE_OCSP"); 162 if (ev && ev[0]) { 163 wantTrace = PR_TRUE; 164 } 165 firstTime = PR_FALSE; 166 } 167 #endif 168 return wantTrace; 169 } 170 171 static void 172 ocsp_Trace(const char *format, ...) 173 { 174 char buf[2000]; 175 va_list args; 176 177 if (!wantOcspTrace()) 178 return; 179 va_start(args, format); 180 PR_vsnprintf(buf, sizeof(buf), format, args); 181 va_end(args); 182 PR_LogPrint("%s", buf); 183 } 184 185 static void 186 ocsp_dumpStringWithTime(const char *str, PRTime time) 187 { 188 PRExplodedTime timePrintable; 189 char timestr[256]; 190 191 if (!wantOcspTrace()) 192 return; 193 PR_ExplodeTime(time, PR_GMTParameters, &timePrintable); 194 if (PR_FormatTime(timestr, 256, "%a %b %d %H:%M:%S %Y", &timePrintable)) { 195 ocsp_Trace("OCSP %s %s\n", str, timestr); 196 } 197 } 198 199 static void 200 printHexString(const char *prefix, SECItem *hexval) 201 { 202 unsigned int i; 203 char *hexbuf = NULL; 204 205 for (i = 0; i < hexval->len; i++) { 206 if (i != hexval->len - 1) { 207 hexbuf = PR_sprintf_append(hexbuf, "%02x:", hexval->data[i]); 208 } else { 209 hexbuf = PR_sprintf_append(hexbuf, "%02x", hexval->data[i]); 210 } 211 } 212 if (hexbuf) { 213 ocsp_Trace("%s %s\n", prefix, hexbuf); 214 PR_smprintf_free(hexbuf); 215 } 216 } 217 218 static void 219 dumpCertificate(CERTCertificate *cert) 220 { 221 if (!wantOcspTrace()) 222 return; 223 224 ocsp_Trace("OCSP ----------------\n"); 225 ocsp_Trace("OCSP ## SUBJECT: %s\n", cert->subjectName); 226 { 227 PRTime timeBefore, timeAfter; 228 PRExplodedTime beforePrintable, afterPrintable; 229 char beforestr[256], afterstr[256]; 230 PRStatus rv1, rv2; 231 DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore); 232 DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter); 233 PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable); 234 PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable); 235 rv1 = PR_FormatTime(beforestr, 256, "%a %b %d %H:%M:%S %Y", 236 &beforePrintable); 237 rv2 = PR_FormatTime(afterstr, 256, "%a %b %d %H:%M:%S %Y", 238 &afterPrintable); 239 ocsp_Trace("OCSP ## VALIDITY: %s to %s\n", rv1 ? beforestr : "", 240 rv2 ? afterstr : ""); 241 } 242 ocsp_Trace("OCSP ## ISSUER: %s\n", cert->issuerName); 243 printHexString("OCSP ## SERIAL NUMBER:", &cert->serialNumber); 244 } 245 246 static void 247 dumpCertID(CERTOCSPCertID *certID) 248 { 249 if (!wantOcspTrace()) 250 return; 251 252 printHexString("OCSP certID issuer", &certID->issuerNameHash); 253 printHexString("OCSP certID serial", &certID->serialNumber); 254 } 255 #endif 256 257 SECStatus 258 SEC_RegisterDefaultHttpClient(const SEC_HttpClientFcn *fcnTable) 259 { 260 if (!OCSP_Global.monitor) { 261 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 262 return SECFailure; 263 } 264 265 PR_EnterMonitor(OCSP_Global.monitor); 266 OCSP_Global.defaultHttpClientFcn = fcnTable; 267 PR_ExitMonitor(OCSP_Global.monitor); 268 269 return SECSuccess; 270 } 271 272 SECStatus 273 CERT_RegisterAlternateOCSPAIAInfoCallBack( 274 CERT_StringFromCertFcn newCallback, 275 CERT_StringFromCertFcn *oldCallback) 276 { 277 CERT_StringFromCertFcn old; 278 279 if (!OCSP_Global.monitor) { 280 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 281 return SECFailure; 282 } 283 284 PR_EnterMonitor(OCSP_Global.monitor); 285 old = OCSP_Global.alternateOCSPAIAFcn; 286 OCSP_Global.alternateOCSPAIAFcn = newCallback; 287 PR_ExitMonitor(OCSP_Global.monitor); 288 if (oldCallback) 289 *oldCallback = old; 290 return SECSuccess; 291 } 292 293 static PLHashNumber PR_CALLBACK 294 ocsp_CacheKeyHashFunction(const void *key) 295 { 296 CERTOCSPCertID *cid = (CERTOCSPCertID *)key; 297 PLHashNumber hash = 0; 298 unsigned int i; 299 unsigned char *walk; 300 301 /* a very simple hash calculation for the initial coding phase */ 302 walk = (unsigned char *)cid->issuerNameHash.data; 303 for (i = 0; i < cid->issuerNameHash.len; ++i, ++walk) { 304 hash += *walk; 305 } 306 walk = (unsigned char *)cid->issuerKeyHash.data; 307 for (i = 0; i < cid->issuerKeyHash.len; ++i, ++walk) { 308 hash += *walk; 309 } 310 walk = (unsigned char *)cid->serialNumber.data; 311 for (i = 0; i < cid->serialNumber.len; ++i, ++walk) { 312 hash += *walk; 313 } 314 return hash; 315 } 316 317 static PRIntn PR_CALLBACK 318 ocsp_CacheKeyCompareFunction(const void *v1, const void *v2) 319 { 320 CERTOCSPCertID *cid1 = (CERTOCSPCertID *)v1; 321 CERTOCSPCertID *cid2 = (CERTOCSPCertID *)v2; 322 323 return (SECEqual == SECITEM_CompareItem(&cid1->issuerNameHash, 324 &cid2->issuerNameHash) && 325 SECEqual == SECITEM_CompareItem(&cid1->issuerKeyHash, 326 &cid2->issuerKeyHash) && 327 SECEqual == SECITEM_CompareItem(&cid1->serialNumber, 328 &cid2->serialNumber)); 329 } 330 331 static SECStatus 332 ocsp_CopyRevokedInfo(PLArenaPool *arena, ocspCertStatus *dest, 333 ocspRevokedInfo *src) 334 { 335 SECStatus rv = SECFailure; 336 void *mark; 337 338 mark = PORT_ArenaMark(arena); 339 340 dest->certStatusInfo.revokedInfo = 341 (ocspRevokedInfo *)PORT_ArenaZAlloc(arena, sizeof(ocspRevokedInfo)); 342 if (!dest->certStatusInfo.revokedInfo) { 343 goto loser; 344 } 345 346 rv = SECITEM_CopyItem(arena, 347 &dest->certStatusInfo.revokedInfo->revocationTime, 348 &src->revocationTime); 349 if (rv != SECSuccess) { 350 goto loser; 351 } 352 353 if (src->revocationReason) { 354 dest->certStatusInfo.revokedInfo->revocationReason = 355 SECITEM_ArenaDupItem(arena, src->revocationReason); 356 if (!dest->certStatusInfo.revokedInfo->revocationReason) { 357 goto loser; 358 } 359 } else { 360 dest->certStatusInfo.revokedInfo->revocationReason = NULL; 361 } 362 363 PORT_ArenaUnmark(arena, mark); 364 return SECSuccess; 365 366 loser: 367 PORT_ArenaRelease(arena, mark); 368 return SECFailure; 369 } 370 371 static SECStatus 372 ocsp_CopyCertStatus(PLArenaPool *arena, ocspCertStatus *dest, 373 ocspCertStatus *src) 374 { 375 SECStatus rv = SECFailure; 376 dest->certStatusType = src->certStatusType; 377 378 switch (src->certStatusType) { 379 case ocspCertStatus_good: 380 dest->certStatusInfo.goodInfo = 381 SECITEM_ArenaDupItem(arena, src->certStatusInfo.goodInfo); 382 if (dest->certStatusInfo.goodInfo != NULL) { 383 rv = SECSuccess; 384 } 385 break; 386 case ocspCertStatus_revoked: 387 rv = ocsp_CopyRevokedInfo(arena, dest, 388 src->certStatusInfo.revokedInfo); 389 break; 390 case ocspCertStatus_unknown: 391 dest->certStatusInfo.unknownInfo = 392 SECITEM_ArenaDupItem(arena, src->certStatusInfo.unknownInfo); 393 if (dest->certStatusInfo.unknownInfo != NULL) { 394 rv = SECSuccess; 395 } 396 break; 397 case ocspCertStatus_other: 398 default: 399 PORT_Assert(src->certStatusType == ocspCertStatus_other); 400 dest->certStatusInfo.otherInfo = 401 SECITEM_ArenaDupItem(arena, src->certStatusInfo.otherInfo); 402 if (dest->certStatusInfo.otherInfo != NULL) { 403 rv = SECSuccess; 404 } 405 break; 406 } 407 return rv; 408 } 409 410 static void 411 ocsp_AddCacheItemToLinkedList(OCSPCacheData *cache, OCSPCacheItem *new_most_recent) 412 { 413 PR_EnterMonitor(OCSP_Global.monitor); 414 415 if (!cache->LRUitem) { 416 cache->LRUitem = new_most_recent; 417 } 418 new_most_recent->lessRecent = cache->MRUitem; 419 new_most_recent->moreRecent = NULL; 420 421 if (cache->MRUitem) { 422 cache->MRUitem->moreRecent = new_most_recent; 423 } 424 cache->MRUitem = new_most_recent; 425 426 PR_ExitMonitor(OCSP_Global.monitor); 427 } 428 429 static void 430 ocsp_RemoveCacheItemFromLinkedList(OCSPCacheData *cache, OCSPCacheItem *item) 431 { 432 PR_EnterMonitor(OCSP_Global.monitor); 433 434 if (!item->lessRecent && !item->moreRecent) { 435 /* 436 * Fail gracefully on attempts to remove an item from the list, 437 * which is currently not part of the list. 438 * But check for the edge case it is the single entry in the list. 439 */ 440 if (item == cache->LRUitem && 441 item == cache->MRUitem) { 442 /* remove the single entry */ 443 PORT_Assert(cache->numberOfEntries == 1); 444 PORT_Assert(item->moreRecent == NULL); 445 cache->MRUitem = NULL; 446 cache->LRUitem = NULL; 447 } 448 PR_ExitMonitor(OCSP_Global.monitor); 449 return; 450 } 451 452 PORT_Assert(cache->numberOfEntries > 1); 453 454 if (item == cache->LRUitem) { 455 PORT_Assert(item != cache->MRUitem); 456 PORT_Assert(item->lessRecent == NULL); 457 PORT_Assert(item->moreRecent != NULL); 458 PORT_Assert(item->moreRecent->lessRecent == item); 459 cache->LRUitem = item->moreRecent; 460 cache->LRUitem->lessRecent = NULL; 461 } else if (item == cache->MRUitem) { 462 PORT_Assert(item->moreRecent == NULL); 463 PORT_Assert(item->lessRecent != NULL); 464 PORT_Assert(item->lessRecent->moreRecent == item); 465 cache->MRUitem = item->lessRecent; 466 cache->MRUitem->moreRecent = NULL; 467 } else { 468 /* remove an entry in the middle of the list */ 469 PORT_Assert(item->moreRecent != NULL); 470 PORT_Assert(item->lessRecent != NULL); 471 PORT_Assert(item->lessRecent->moreRecent == item); 472 PORT_Assert(item->moreRecent->lessRecent == item); 473 item->moreRecent->lessRecent = item->lessRecent; 474 item->lessRecent->moreRecent = item->moreRecent; 475 } 476 477 item->lessRecent = NULL; 478 item->moreRecent = NULL; 479 480 PR_ExitMonitor(OCSP_Global.monitor); 481 } 482 483 static void 484 ocsp_MakeCacheEntryMostRecent(OCSPCacheData *cache, OCSPCacheItem *new_most_recent) 485 { 486 OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent THREADID %p\n", 487 PR_GetCurrentThread())); 488 PR_EnterMonitor(OCSP_Global.monitor); 489 if (cache->MRUitem == new_most_recent) { 490 OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent ALREADY MOST\n")); 491 PR_ExitMonitor(OCSP_Global.monitor); 492 return; 493 } 494 OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent NEW entry\n")); 495 ocsp_RemoveCacheItemFromLinkedList(cache, new_most_recent); 496 ocsp_AddCacheItemToLinkedList(cache, new_most_recent); 497 PR_ExitMonitor(OCSP_Global.monitor); 498 } 499 500 static PRBool 501 ocsp_IsCacheDisabled(void) 502 { 503 /* 504 * maxCacheEntries == 0 means unlimited cache entries 505 * maxCacheEntries < 0 means cache is disabled 506 */ 507 PRBool retval; 508 PR_EnterMonitor(OCSP_Global.monitor); 509 retval = (OCSP_Global.maxCacheEntries < 0); 510 PR_ExitMonitor(OCSP_Global.monitor); 511 return retval; 512 } 513 514 static OCSPCacheItem * 515 ocsp_FindCacheEntry(OCSPCacheData *cache, CERTOCSPCertID *certID) 516 { 517 OCSPCacheItem *found_ocsp_item = NULL; 518 OCSP_TRACE(("OCSP ocsp_FindCacheEntry\n")); 519 OCSP_TRACE_CERTID(certID); 520 PR_EnterMonitor(OCSP_Global.monitor); 521 if (ocsp_IsCacheDisabled()) 522 goto loser; 523 524 found_ocsp_item = (OCSPCacheItem *)PL_HashTableLookup( 525 cache->entries, certID); 526 if (!found_ocsp_item) 527 goto loser; 528 529 OCSP_TRACE(("OCSP ocsp_FindCacheEntry FOUND!\n")); 530 ocsp_MakeCacheEntryMostRecent(cache, found_ocsp_item); 531 532 loser: 533 PR_ExitMonitor(OCSP_Global.monitor); 534 return found_ocsp_item; 535 } 536 537 static void 538 ocsp_FreeCacheItem(OCSPCacheItem *item) 539 { 540 OCSP_TRACE(("OCSP ocsp_FreeCacheItem\n")); 541 if (item->certStatusArena) { 542 PORT_FreeArena(item->certStatusArena, PR_FALSE); 543 } 544 if (item->certID->poolp) { 545 /* freeing this poolp arena will also free item */ 546 PORT_FreeArena(item->certID->poolp, PR_FALSE); 547 } 548 } 549 550 static void 551 ocsp_RemoveCacheItem(OCSPCacheData *cache, OCSPCacheItem *item) 552 { 553 /* The item we're removing could be either the least recently used item, 554 * or it could be an item that couldn't get updated with newer status info 555 * because of an allocation failure, or it could get removed because we're 556 * cleaning up. 557 */ 558 OCSP_TRACE(("OCSP ocsp_RemoveCacheItem, THREADID %p\n", PR_GetCurrentThread())); 559 PR_EnterMonitor(OCSP_Global.monitor); 560 561 ocsp_RemoveCacheItemFromLinkedList(cache, item); 562 #ifdef DEBUG 563 { 564 PRBool couldRemoveFromHashTable = PL_HashTableRemove(cache->entries, 565 item->certID); 566 PORT_Assert(couldRemoveFromHashTable); 567 } 568 #else 569 PL_HashTableRemove(cache->entries, item->certID); 570 #endif 571 --cache->numberOfEntries; 572 ocsp_FreeCacheItem(item); 573 PR_ExitMonitor(OCSP_Global.monitor); 574 } 575 576 static void 577 ocsp_CheckCacheSize(OCSPCacheData *cache) 578 { 579 OCSP_TRACE(("OCSP ocsp_CheckCacheSize\n")); 580 PR_EnterMonitor(OCSP_Global.monitor); 581 if (OCSP_Global.maxCacheEntries > 0) { 582 /* Cache is not disabled. Number of cache entries is limited. 583 * The monitor ensures that maxCacheEntries remains positive. 584 */ 585 while (cache->numberOfEntries > 586 (PRUint32)OCSP_Global.maxCacheEntries) { 587 ocsp_RemoveCacheItem(cache, cache->LRUitem); 588 } 589 } 590 PR_ExitMonitor(OCSP_Global.monitor); 591 } 592 593 SECStatus 594 CERT_ClearOCSPCache(void) 595 { 596 OCSP_TRACE(("OCSP CERT_ClearOCSPCache\n")); 597 PR_EnterMonitor(OCSP_Global.monitor); 598 while (OCSP_Global.cache.numberOfEntries > 0) { 599 ocsp_RemoveCacheItem(&OCSP_Global.cache, 600 OCSP_Global.cache.LRUitem); 601 } 602 PR_ExitMonitor(OCSP_Global.monitor); 603 return SECSuccess; 604 } 605 606 static SECStatus 607 ocsp_CreateCacheItemAndConsumeCertID(OCSPCacheData *cache, 608 CERTOCSPCertID *certID, 609 OCSPCacheItem **pCacheItem) 610 { 611 PLArenaPool *arena; 612 void *mark; 613 PLHashEntry *new_hash_entry; 614 OCSPCacheItem *item; 615 616 PORT_Assert(pCacheItem != NULL); 617 *pCacheItem = NULL; 618 619 PR_EnterMonitor(OCSP_Global.monitor); 620 arena = certID->poolp; 621 mark = PORT_ArenaMark(arena); 622 623 /* ZAlloc will init all Bools to False and all Pointers to NULL 624 and all error codes to zero/good. */ 625 item = (OCSPCacheItem *)PORT_ArenaZAlloc(certID->poolp, 626 sizeof(OCSPCacheItem)); 627 if (!item) { 628 goto loser; 629 } 630 item->certID = certID; 631 new_hash_entry = PL_HashTableAdd(cache->entries, item->certID, 632 item); 633 if (!new_hash_entry) { 634 goto loser; 635 } 636 ++cache->numberOfEntries; 637 PORT_ArenaUnmark(arena, mark); 638 ocsp_AddCacheItemToLinkedList(cache, item); 639 *pCacheItem = item; 640 641 PR_ExitMonitor(OCSP_Global.monitor); 642 return SECSuccess; 643 644 loser: 645 PORT_ArenaRelease(arena, mark); 646 PR_ExitMonitor(OCSP_Global.monitor); 647 return SECFailure; 648 } 649 650 static SECStatus 651 ocsp_SetCacheItemResponse(OCSPCacheItem *item, 652 const CERTOCSPSingleResponse *response) 653 { 654 if (item->certStatusArena) { 655 PORT_FreeArena(item->certStatusArena, PR_FALSE); 656 item->certStatusArena = NULL; 657 } 658 item->haveThisUpdate = item->haveNextUpdate = PR_FALSE; 659 if (response) { 660 SECStatus rv; 661 item->certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 662 if (item->certStatusArena == NULL) { 663 return SECFailure; 664 } 665 rv = ocsp_CopyCertStatus(item->certStatusArena, &item->certStatus, 666 response->certStatus); 667 if (rv != SECSuccess) { 668 PORT_FreeArena(item->certStatusArena, PR_FALSE); 669 item->certStatusArena = NULL; 670 return rv; 671 } 672 item->missingResponseError = 0; 673 rv = DER_GeneralizedTimeToTime(&item->thisUpdate, 674 &response->thisUpdate); 675 item->haveThisUpdate = (rv == SECSuccess); 676 if (response->nextUpdate) { 677 rv = DER_GeneralizedTimeToTime(&item->nextUpdate, 678 response->nextUpdate); 679 item->haveNextUpdate = (rv == SECSuccess); 680 } else { 681 item->haveNextUpdate = PR_FALSE; 682 } 683 } 684 return SECSuccess; 685 } 686 687 static void 688 ocsp_FreshenCacheItemNextFetchAttemptTime(OCSPCacheItem *cacheItem) 689 { 690 PRTime now; 691 PRTime earliestAllowedNextFetchAttemptTime; 692 PRTime latestTimeWhenResponseIsConsideredFresh; 693 694 OCSP_TRACE(("OCSP ocsp_FreshenCacheItemNextFetchAttemptTime\n")); 695 696 PR_EnterMonitor(OCSP_Global.monitor); 697 698 now = PR_Now(); 699 OCSP_TRACE_TIME("now:", now); 700 701 if (cacheItem->haveThisUpdate) { 702 OCSP_TRACE_TIME("thisUpdate:", cacheItem->thisUpdate); 703 latestTimeWhenResponseIsConsideredFresh = cacheItem->thisUpdate + 704 OCSP_Global.maximumSecondsToNextFetchAttempt * 705 MICROSECONDS_PER_SECOND; 706 OCSP_TRACE_TIME("latestTimeWhenResponseIsConsideredFresh:", 707 latestTimeWhenResponseIsConsideredFresh); 708 } else { 709 latestTimeWhenResponseIsConsideredFresh = now + 710 OCSP_Global.minimumSecondsToNextFetchAttempt * 711 MICROSECONDS_PER_SECOND; 712 OCSP_TRACE_TIME("no thisUpdate, " 713 "latestTimeWhenResponseIsConsideredFresh:", 714 latestTimeWhenResponseIsConsideredFresh); 715 } 716 717 if (cacheItem->haveNextUpdate) { 718 OCSP_TRACE_TIME("have nextUpdate:", cacheItem->nextUpdate); 719 } 720 721 if (cacheItem->haveNextUpdate && 722 cacheItem->nextUpdate < latestTimeWhenResponseIsConsideredFresh) { 723 latestTimeWhenResponseIsConsideredFresh = cacheItem->nextUpdate; 724 OCSP_TRACE_TIME("nextUpdate is smaller than latestFresh, setting " 725 "latestTimeWhenResponseIsConsideredFresh:", 726 latestTimeWhenResponseIsConsideredFresh); 727 } 728 729 earliestAllowedNextFetchAttemptTime = now + 730 OCSP_Global.minimumSecondsToNextFetchAttempt * 731 MICROSECONDS_PER_SECOND; 732 OCSP_TRACE_TIME("earliestAllowedNextFetchAttemptTime:", 733 earliestAllowedNextFetchAttemptTime); 734 735 if (latestTimeWhenResponseIsConsideredFresh < 736 earliestAllowedNextFetchAttemptTime) { 737 latestTimeWhenResponseIsConsideredFresh = 738 earliestAllowedNextFetchAttemptTime; 739 OCSP_TRACE_TIME("latest < earliest, setting latest to:", 740 latestTimeWhenResponseIsConsideredFresh); 741 } 742 743 cacheItem->nextFetchAttemptTime = 744 latestTimeWhenResponseIsConsideredFresh; 745 OCSP_TRACE_TIME("nextFetchAttemptTime", 746 latestTimeWhenResponseIsConsideredFresh); 747 748 PR_ExitMonitor(OCSP_Global.monitor); 749 } 750 751 static PRBool 752 ocsp_IsCacheItemFresh(OCSPCacheItem *cacheItem) 753 { 754 PRTime now; 755 PRBool fresh; 756 757 now = PR_Now(); 758 759 fresh = cacheItem->nextFetchAttemptTime > now; 760 761 /* Work around broken OCSP responders that return unknown responses for 762 * certificates, especially certificates that were just recently issued. 763 */ 764 if (fresh && cacheItem->certStatusArena && 765 cacheItem->certStatus.certStatusType == ocspCertStatus_unknown) { 766 fresh = PR_FALSE; 767 } 768 769 OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", fresh)); 770 771 return fresh; 772 } 773 774 /* 775 * Status in *certIDWasConsumed will always be correct, regardless of 776 * return value. 777 * If the caller is unable to transfer ownership of certID, 778 * then the caller must set certIDWasConsumed to NULL, 779 * and this function will potentially duplicate the certID object. 780 */ 781 static SECStatus 782 ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache, 783 CERTOCSPCertID *certID, 784 CERTOCSPSingleResponse *single, 785 PRBool *certIDWasConsumed) 786 { 787 SECStatus rv; 788 OCSPCacheItem *cacheItem; 789 OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n")); 790 791 if (certIDWasConsumed) 792 *certIDWasConsumed = PR_FALSE; 793 794 PR_EnterMonitor(OCSP_Global.monitor); 795 PORT_Assert(OCSP_Global.maxCacheEntries >= 0); 796 797 cacheItem = ocsp_FindCacheEntry(cache, certID); 798 799 /* Don't replace an unknown or revoked entry with an error entry, even if 800 * the existing entry is expired. Instead, we'll continue to use the 801 * existing (possibly expired) cache entry until we receive a valid signed 802 * response to replace it. 803 */ 804 if (!single && cacheItem && cacheItem->certStatusArena && 805 (cacheItem->certStatus.certStatusType == ocspCertStatus_revoked || 806 cacheItem->certStatus.certStatusType == ocspCertStatus_unknown)) { 807 PR_ExitMonitor(OCSP_Global.monitor); 808 return SECSuccess; 809 } 810 811 if (!cacheItem) { 812 CERTOCSPCertID *myCertID; 813 if (certIDWasConsumed) { 814 myCertID = certID; 815 *certIDWasConsumed = PR_TRUE; 816 } else { 817 myCertID = cert_DupOCSPCertID(certID); 818 if (!myCertID) { 819 PR_ExitMonitor(OCSP_Global.monitor); 820 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); 821 return SECFailure; 822 } 823 } 824 825 rv = ocsp_CreateCacheItemAndConsumeCertID(cache, myCertID, 826 &cacheItem); 827 if (rv != SECSuccess) { 828 PR_ExitMonitor(OCSP_Global.monitor); 829 return rv; 830 } 831 } 832 if (single) { 833 PRTime thisUpdate; 834 rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate); 835 836 if (!cacheItem->haveThisUpdate || 837 (rv == SECSuccess && cacheItem->thisUpdate < thisUpdate)) { 838 rv = ocsp_SetCacheItemResponse(cacheItem, single); 839 if (rv != SECSuccess) { 840 ocsp_RemoveCacheItem(cache, cacheItem); 841 PR_ExitMonitor(OCSP_Global.monitor); 842 return rv; 843 } 844 } else { 845 OCSP_TRACE(("Not caching response because the response is not " 846 "newer than the cache")); 847 } 848 } else { 849 cacheItem->missingResponseError = PORT_GetError(); 850 if (cacheItem->certStatusArena) { 851 PORT_FreeArena(cacheItem->certStatusArena, PR_FALSE); 852 cacheItem->certStatusArena = NULL; 853 } 854 } 855 ocsp_FreshenCacheItemNextFetchAttemptTime(cacheItem); 856 ocsp_CheckCacheSize(cache); 857 858 PR_ExitMonitor(OCSP_Global.monitor); 859 return SECSuccess; 860 } 861 862 extern SECStatus 863 CERT_SetOCSPFailureMode(SEC_OcspFailureMode ocspFailureMode) 864 { 865 switch (ocspFailureMode) { 866 case ocspMode_FailureIsVerificationFailure: 867 case ocspMode_FailureIsNotAVerificationFailure: 868 break; 869 default: 870 PORT_SetError(SEC_ERROR_INVALID_ARGS); 871 return SECFailure; 872 } 873 874 PR_EnterMonitor(OCSP_Global.monitor); 875 OCSP_Global.ocspFailureMode = ocspFailureMode; 876 PR_ExitMonitor(OCSP_Global.monitor); 877 return SECSuccess; 878 } 879 880 SECStatus 881 CERT_OCSPCacheSettings(PRInt32 maxCacheEntries, 882 PRUint32 minimumSecondsToNextFetchAttempt, 883 PRUint32 maximumSecondsToNextFetchAttempt) 884 { 885 if (minimumSecondsToNextFetchAttempt > maximumSecondsToNextFetchAttempt || 886 maxCacheEntries < -1) { 887 PORT_SetError(SEC_ERROR_INVALID_ARGS); 888 return SECFailure; 889 } 890 891 PR_EnterMonitor(OCSP_Global.monitor); 892 893 if (maxCacheEntries < 0) { 894 OCSP_Global.maxCacheEntries = -1; /* disable cache */ 895 } else if (maxCacheEntries == 0) { 896 OCSP_Global.maxCacheEntries = 0; /* unlimited cache entries */ 897 } else { 898 OCSP_Global.maxCacheEntries = maxCacheEntries; 899 } 900 901 if (minimumSecondsToNextFetchAttempt < 902 OCSP_Global.minimumSecondsToNextFetchAttempt || 903 maximumSecondsToNextFetchAttempt < 904 OCSP_Global.maximumSecondsToNextFetchAttempt) { 905 /* 906 * Ensure our existing cache entries are not used longer than the 907 * new settings allow, we're lazy and just clear the cache 908 */ 909 CERT_ClearOCSPCache(); 910 } 911 912 OCSP_Global.minimumSecondsToNextFetchAttempt = 913 minimumSecondsToNextFetchAttempt; 914 OCSP_Global.maximumSecondsToNextFetchAttempt = 915 maximumSecondsToNextFetchAttempt; 916 ocsp_CheckCacheSize(&OCSP_Global.cache); 917 918 PR_ExitMonitor(OCSP_Global.monitor); 919 return SECSuccess; 920 } 921 922 SECStatus 923 CERT_SetOCSPTimeout(PRUint32 seconds) 924 { 925 /* no locking, see bug 406120 */ 926 OCSP_Global.timeoutSeconds = seconds; 927 return SECSuccess; 928 } 929 930 /* this function is called at NSS initialization time */ 931 SECStatus 932 OCSP_InitGlobal(void) 933 { 934 SECStatus rv = SECFailure; 935 936 if (OCSP_Global.monitor == NULL) { 937 OCSP_Global.monitor = PR_NewMonitor(); 938 } 939 if (!OCSP_Global.monitor) 940 return SECFailure; 941 942 PR_EnterMonitor(OCSP_Global.monitor); 943 if (!OCSP_Global.cache.entries) { 944 OCSP_Global.cache.entries = 945 PL_NewHashTable(0, 946 ocsp_CacheKeyHashFunction, 947 ocsp_CacheKeyCompareFunction, 948 PL_CompareValues, 949 NULL, 950 NULL); 951 OCSP_Global.ocspFailureMode = ocspMode_FailureIsVerificationFailure; 952 OCSP_Global.cache.numberOfEntries = 0; 953 OCSP_Global.cache.MRUitem = NULL; 954 OCSP_Global.cache.LRUitem = NULL; 955 } else { 956 /* 957 * NSS might call this function twice while attempting to init. 958 * But it's not allowed to call this again after any activity. 959 */ 960 PORT_Assert(OCSP_Global.cache.numberOfEntries == 0); 961 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 962 } 963 if (OCSP_Global.cache.entries) 964 rv = SECSuccess; 965 PR_ExitMonitor(OCSP_Global.monitor); 966 return rv; 967 } 968 969 SECStatus 970 OCSP_ShutdownGlobal(void) 971 { 972 if (!OCSP_Global.monitor) 973 return SECSuccess; 974 975 PR_EnterMonitor(OCSP_Global.monitor); 976 if (OCSP_Global.cache.entries) { 977 CERT_ClearOCSPCache(); 978 PL_HashTableDestroy(OCSP_Global.cache.entries); 979 OCSP_Global.cache.entries = NULL; 980 } 981 PORT_Assert(OCSP_Global.cache.numberOfEntries == 0); 982 OCSP_Global.cache.MRUitem = NULL; 983 OCSP_Global.cache.LRUitem = NULL; 984 985 OCSP_Global.defaultHttpClientFcn = NULL; 986 OCSP_Global.maxCacheEntries = DEFAULT_OCSP_CACHE_SIZE; 987 OCSP_Global.minimumSecondsToNextFetchAttempt = 988 DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT; 989 OCSP_Global.maximumSecondsToNextFetchAttempt = 990 DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT; 991 OCSP_Global.ocspFailureMode = 992 ocspMode_FailureIsVerificationFailure; 993 PR_ExitMonitor(OCSP_Global.monitor); 994 995 PR_DestroyMonitor(OCSP_Global.monitor); 996 OCSP_Global.monitor = NULL; 997 return SECSuccess; 998 } 999 1000 /* 1001 * A return value of NULL means: 1002 * The application did not register it's own HTTP client. 1003 */ 1004 const SEC_HttpClientFcn * 1005 SEC_GetRegisteredHttpClient(void) 1006 { 1007 const SEC_HttpClientFcn *retval; 1008 1009 if (!OCSP_Global.monitor) { 1010 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1011 return NULL; 1012 } 1013 1014 PR_EnterMonitor(OCSP_Global.monitor); 1015 retval = OCSP_Global.defaultHttpClientFcn; 1016 PR_ExitMonitor(OCSP_Global.monitor); 1017 1018 return retval; 1019 } 1020 1021 /* 1022 * The following structure is only used internally. It is allocated when 1023 * someone turns on OCSP checking, and hangs off of the status-configuration 1024 * structure in the certdb structure. We use it to keep configuration 1025 * information specific to OCSP checking. 1026 */ 1027 typedef struct ocspCheckingContextStr { 1028 PRBool useDefaultResponder; 1029 char *defaultResponderURI; 1030 char *defaultResponderNickname; 1031 CERTCertificate *defaultResponderCert; 1032 } ocspCheckingContext; 1033 1034 SEC_ASN1_MKSUB(SEC_AnyTemplate) 1035 SEC_ASN1_MKSUB(SEC_IntegerTemplate) 1036 SEC_ASN1_MKSUB(SEC_NullTemplate) 1037 SEC_ASN1_MKSUB(SEC_OctetStringTemplate) 1038 SEC_ASN1_MKSUB(SEC_PointerToAnyTemplate) 1039 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) 1040 SEC_ASN1_MKSUB(SEC_SequenceOfAnyTemplate) 1041 SEC_ASN1_MKSUB(SEC_PointerToGeneralizedTimeTemplate) 1042 SEC_ASN1_MKSUB(SEC_PointerToEnumeratedTemplate) 1043 1044 /* 1045 * Forward declarations of sub-types, so I can lay out the types in the 1046 * same order as the ASN.1 is laid out in the OCSP spec itself. 1047 * 1048 * These are in alphabetical order (case-insensitive); please keep it that way! 1049 */ 1050 extern const SEC_ASN1Template ocsp_CertIDTemplate[]; 1051 extern const SEC_ASN1Template ocsp_PointerToSignatureTemplate[]; 1052 extern const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[]; 1053 extern const SEC_ASN1Template ocsp_ResponseDataTemplate[]; 1054 extern const SEC_ASN1Template ocsp_RevokedInfoTemplate[]; 1055 extern const SEC_ASN1Template ocsp_SingleRequestTemplate[]; 1056 extern const SEC_ASN1Template ocsp_SingleResponseTemplate[]; 1057 extern const SEC_ASN1Template ocsp_TBSRequestTemplate[]; 1058 1059 /* 1060 * Request-related templates... 1061 */ 1062 1063 /* 1064 * OCSPRequest ::= SEQUENCE { 1065 * tbsRequest TBSRequest, 1066 * optionalSignature [0] EXPLICIT Signature OPTIONAL } 1067 */ 1068 static const SEC_ASN1Template ocsp_OCSPRequestTemplate[] = { 1069 { SEC_ASN1_SEQUENCE, 1070 0, NULL, sizeof(CERTOCSPRequest) }, 1071 { SEC_ASN1_POINTER, 1072 offsetof(CERTOCSPRequest, tbsRequest), 1073 ocsp_TBSRequestTemplate }, 1074 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1075 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1076 offsetof(CERTOCSPRequest, optionalSignature), 1077 ocsp_PointerToSignatureTemplate }, 1078 { 0 } 1079 }; 1080 1081 /* 1082 * TBSRequest ::= SEQUENCE { 1083 * version [0] EXPLICIT Version DEFAULT v1, 1084 * requestorName [1] EXPLICIT GeneralName OPTIONAL, 1085 * requestList SEQUENCE OF Request, 1086 * requestExtensions [2] EXPLICIT Extensions OPTIONAL } 1087 * 1088 * Version ::= INTEGER { v1(0) } 1089 * 1090 * Note: this should be static but the AIX compiler doesn't like it (because it 1091 * was forward-declared above); it is not meant to be exported, but this 1092 * is the only way it will compile. 1093 */ 1094 const SEC_ASN1Template ocsp_TBSRequestTemplate[] = { 1095 { SEC_ASN1_SEQUENCE, 1096 0, NULL, sizeof(ocspTBSRequest) }, 1097 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */ 1098 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 1099 offsetof(ocspTBSRequest, version), 1100 SEC_ASN1_SUB(SEC_IntegerTemplate) }, 1101 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1102 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, 1103 offsetof(ocspTBSRequest, derRequestorName), 1104 SEC_ASN1_SUB(SEC_PointerToAnyTemplate) }, 1105 { SEC_ASN1_SEQUENCE_OF, 1106 offsetof(ocspTBSRequest, requestList), 1107 ocsp_SingleRequestTemplate }, 1108 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1109 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2, 1110 offsetof(ocspTBSRequest, requestExtensions), 1111 CERT_SequenceOfCertExtensionTemplate }, 1112 { 0 } 1113 }; 1114 1115 /* 1116 * Signature ::= SEQUENCE { 1117 * signatureAlgorithm AlgorithmIdentifier, 1118 * signature BIT STRING, 1119 * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } 1120 */ 1121 static const SEC_ASN1Template ocsp_SignatureTemplate[] = { 1122 { SEC_ASN1_SEQUENCE, 1123 0, NULL, sizeof(ocspSignature) }, 1124 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1125 offsetof(ocspSignature, signatureAlgorithm), 1126 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1127 { SEC_ASN1_BIT_STRING, 1128 offsetof(ocspSignature, signature) }, 1129 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1130 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 1131 offsetof(ocspSignature, derCerts), 1132 SEC_ASN1_SUB(SEC_SequenceOfAnyTemplate) }, 1133 { 0 } 1134 }; 1135 1136 /* 1137 * This template is just an extra level to use in an explicitly-tagged 1138 * reference to a Signature. 1139 * 1140 * Note: this should be static but the AIX compiler doesn't like it (because it 1141 * was forward-declared above); it is not meant to be exported, but this 1142 * is the only way it will compile. 1143 */ 1144 const SEC_ASN1Template ocsp_PointerToSignatureTemplate[] = { 1145 { SEC_ASN1_POINTER, 0, ocsp_SignatureTemplate } 1146 }; 1147 1148 /* 1149 * Request ::= SEQUENCE { 1150 * reqCert CertID, 1151 * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } 1152 * 1153 * Note: this should be static but the AIX compiler doesn't like it (because it 1154 * was forward-declared above); it is not meant to be exported, but this 1155 * is the only way it will compile. 1156 */ 1157 const SEC_ASN1Template ocsp_SingleRequestTemplate[] = { 1158 { SEC_ASN1_SEQUENCE, 1159 0, NULL, sizeof(ocspSingleRequest) }, 1160 { SEC_ASN1_POINTER, 1161 offsetof(ocspSingleRequest, reqCert), 1162 ocsp_CertIDTemplate }, 1163 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1164 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1165 offsetof(ocspSingleRequest, singleRequestExtensions), 1166 CERT_SequenceOfCertExtensionTemplate }, 1167 { 0 } 1168 }; 1169 1170 /* 1171 * This data structure and template (CertID) is used by both OCSP 1172 * requests and responses. It is the only one that is shared. 1173 * 1174 * CertID ::= SEQUENCE { 1175 * hashAlgorithm AlgorithmIdentifier, 1176 * issuerNameHash OCTET STRING, -- Hash of Issuer DN 1177 * issuerKeyHash OCTET STRING, -- Hash of Issuer public key 1178 * serialNumber CertificateSerialNumber } 1179 * 1180 * CertificateSerialNumber ::= INTEGER 1181 * 1182 * Note: this should be static but the AIX compiler doesn't like it (because it 1183 * was forward-declared above); it is not meant to be exported, but this 1184 * is the only way it will compile. 1185 */ 1186 const SEC_ASN1Template ocsp_CertIDTemplate[] = { 1187 { SEC_ASN1_SEQUENCE, 1188 0, NULL, sizeof(CERTOCSPCertID) }, 1189 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1190 offsetof(CERTOCSPCertID, hashAlgorithm), 1191 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1192 { SEC_ASN1_OCTET_STRING, 1193 offsetof(CERTOCSPCertID, issuerNameHash) }, 1194 { SEC_ASN1_OCTET_STRING, 1195 offsetof(CERTOCSPCertID, issuerKeyHash) }, 1196 { SEC_ASN1_INTEGER, 1197 offsetof(CERTOCSPCertID, serialNumber) }, 1198 { 0 } 1199 }; 1200 1201 /* 1202 * Response-related templates... 1203 */ 1204 1205 /* 1206 * OCSPResponse ::= SEQUENCE { 1207 * responseStatus OCSPResponseStatus, 1208 * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } 1209 */ 1210 const SEC_ASN1Template ocsp_OCSPResponseTemplate[] = { 1211 { SEC_ASN1_SEQUENCE, 1212 0, NULL, sizeof(CERTOCSPResponse) }, 1213 { SEC_ASN1_ENUMERATED, 1214 offsetof(CERTOCSPResponse, responseStatus) }, 1215 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1216 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1217 offsetof(CERTOCSPResponse, responseBytes), 1218 ocsp_PointerToResponseBytesTemplate }, 1219 { 0 } 1220 }; 1221 1222 /* 1223 * ResponseBytes ::= SEQUENCE { 1224 * responseType OBJECT IDENTIFIER, 1225 * response OCTET STRING } 1226 */ 1227 const SEC_ASN1Template ocsp_ResponseBytesTemplate[] = { 1228 { SEC_ASN1_SEQUENCE, 1229 0, NULL, sizeof(ocspResponseBytes) }, 1230 { SEC_ASN1_OBJECT_ID, 1231 offsetof(ocspResponseBytes, responseType) }, 1232 { SEC_ASN1_OCTET_STRING, 1233 offsetof(ocspResponseBytes, response) }, 1234 { 0 } 1235 }; 1236 1237 /* 1238 * This template is just an extra level to use in an explicitly-tagged 1239 * reference to a ResponseBytes. 1240 * 1241 * Note: this should be static but the AIX compiler doesn't like it (because it 1242 * was forward-declared above); it is not meant to be exported, but this 1243 * is the only way it will compile. 1244 */ 1245 const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[] = { 1246 { SEC_ASN1_POINTER, 0, ocsp_ResponseBytesTemplate } 1247 }; 1248 1249 /* 1250 * BasicOCSPResponse ::= SEQUENCE { 1251 * tbsResponseData ResponseData, 1252 * signatureAlgorithm AlgorithmIdentifier, 1253 * signature BIT STRING, 1254 * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } 1255 */ 1256 static const SEC_ASN1Template ocsp_BasicOCSPResponseTemplate[] = { 1257 { SEC_ASN1_SEQUENCE, 1258 0, NULL, sizeof(ocspBasicOCSPResponse) }, 1259 { SEC_ASN1_ANY | SEC_ASN1_SAVE, 1260 offsetof(ocspBasicOCSPResponse, tbsResponseDataDER) }, 1261 { SEC_ASN1_POINTER, 1262 offsetof(ocspBasicOCSPResponse, tbsResponseData), 1263 ocsp_ResponseDataTemplate }, 1264 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1265 offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm), 1266 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1267 { SEC_ASN1_BIT_STRING, 1268 offsetof(ocspBasicOCSPResponse, responseSignature.signature) }, 1269 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1270 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 1271 offsetof(ocspBasicOCSPResponse, responseSignature.derCerts), 1272 SEC_ASN1_SUB(SEC_SequenceOfAnyTemplate) }, 1273 { 0 } 1274 }; 1275 1276 /* 1277 * ResponseData ::= SEQUENCE { 1278 * version [0] EXPLICIT Version DEFAULT v1, 1279 * responderID ResponderID, 1280 * producedAt GeneralizedTime, 1281 * responses SEQUENCE OF SingleResponse, 1282 * responseExtensions [1] EXPLICIT Extensions OPTIONAL } 1283 * 1284 * Note: this should be static but the AIX compiler doesn't like it (because it 1285 * was forward-declared above); it is not meant to be exported, but this 1286 * is the only way it will compile. 1287 */ 1288 const SEC_ASN1Template ocsp_ResponseDataTemplate[] = { 1289 { SEC_ASN1_SEQUENCE, 1290 0, NULL, sizeof(ocspResponseData) }, 1291 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */ 1292 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 1293 offsetof(ocspResponseData, version), 1294 SEC_ASN1_SUB(SEC_IntegerTemplate) }, 1295 { SEC_ASN1_ANY, 1296 offsetof(ocspResponseData, derResponderID) }, 1297 { SEC_ASN1_GENERALIZED_TIME, 1298 offsetof(ocspResponseData, producedAt) }, 1299 { SEC_ASN1_SEQUENCE_OF, 1300 offsetof(ocspResponseData, responses), 1301 ocsp_SingleResponseTemplate }, 1302 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1303 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1304 offsetof(ocspResponseData, responseExtensions), 1305 CERT_SequenceOfCertExtensionTemplate }, 1306 { 0 } 1307 }; 1308 1309 /* 1310 * ResponderID ::= CHOICE { 1311 * byName [1] EXPLICIT Name, 1312 * byKey [2] EXPLICIT KeyHash } 1313 * 1314 * KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key 1315 * (excluding the tag and length fields) 1316 * 1317 * XXX Because the ASN.1 encoder and decoder currently do not provide 1318 * a way to automatically handle a CHOICE, we need to do it in two 1319 * steps, looking at the type tag and feeding the exact choice back 1320 * to the ASN.1 code. Hopefully that will change someday and this 1321 * can all be simplified down into a single template. Anyway, for 1322 * now we list each choice as its own template: 1323 */ 1324 const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[] = { 1325 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1326 offsetof(ocspResponderID, responderIDValue.name), 1327 CERT_NameTemplate } 1328 }; 1329 const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[] = { 1330 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1331 SEC_ASN1_XTRN | 2, 1332 offsetof(ocspResponderID, responderIDValue.keyHash), 1333 SEC_ASN1_SUB(SEC_OctetStringTemplate) } 1334 }; 1335 static const SEC_ASN1Template ocsp_ResponderIDOtherTemplate[] = { 1336 { SEC_ASN1_ANY, 1337 offsetof(ocspResponderID, responderIDValue.other) } 1338 }; 1339 1340 /* Decode choice container, but leave x509 name object encoded */ 1341 static const SEC_ASN1Template ocsp_ResponderIDDerNameTemplate[] = { 1342 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1343 SEC_ASN1_XTRN | 1, 1344 0, SEC_ASN1_SUB(SEC_AnyTemplate) } 1345 }; 1346 1347 /* 1348 * SingleResponse ::= SEQUENCE { 1349 * certID CertID, 1350 * certStatus CertStatus, 1351 * thisUpdate GeneralizedTime, 1352 * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, 1353 * singleExtensions [1] EXPLICIT Extensions OPTIONAL } 1354 * 1355 * Note: this should be static but the AIX compiler doesn't like it (because it 1356 * was forward-declared above); it is not meant to be exported, but this 1357 * is the only way it will compile. 1358 */ 1359 const SEC_ASN1Template ocsp_SingleResponseTemplate[] = { 1360 { SEC_ASN1_SEQUENCE, 1361 0, NULL, sizeof(CERTOCSPSingleResponse) }, 1362 { SEC_ASN1_POINTER, 1363 offsetof(CERTOCSPSingleResponse, certID), 1364 ocsp_CertIDTemplate }, 1365 { SEC_ASN1_ANY, 1366 offsetof(CERTOCSPSingleResponse, derCertStatus) }, 1367 { SEC_ASN1_GENERALIZED_TIME, 1368 offsetof(CERTOCSPSingleResponse, thisUpdate) }, 1369 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1370 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 1371 offsetof(CERTOCSPSingleResponse, nextUpdate), 1372 SEC_ASN1_SUB(SEC_PointerToGeneralizedTimeTemplate) }, 1373 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1374 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1375 offsetof(CERTOCSPSingleResponse, singleExtensions), 1376 CERT_SequenceOfCertExtensionTemplate }, 1377 { 0 } 1378 }; 1379 1380 /* 1381 * CertStatus ::= CHOICE { 1382 * good [0] IMPLICIT NULL, 1383 * revoked [1] IMPLICIT RevokedInfo, 1384 * unknown [2] IMPLICIT UnknownInfo } 1385 * 1386 * Because the ASN.1 encoder and decoder currently do not provide 1387 * a way to automatically handle a CHOICE, we need to do it in two 1388 * steps, looking at the type tag and feeding the exact choice back 1389 * to the ASN.1 code. Hopefully that will change someday and this 1390 * can all be simplified down into a single template. Anyway, for 1391 * now we list each choice as its own template: 1392 */ 1393 static const SEC_ASN1Template ocsp_CertStatusGoodTemplate[] = { 1394 { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 1395 offsetof(ocspCertStatus, certStatusInfo.goodInfo), 1396 SEC_ASN1_SUB(SEC_NullTemplate) } 1397 }; 1398 static const SEC_ASN1Template ocsp_CertStatusRevokedTemplate[] = { 1399 { SEC_ASN1_POINTER | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1400 offsetof(ocspCertStatus, certStatusInfo.revokedInfo), 1401 ocsp_RevokedInfoTemplate } 1402 }; 1403 static const SEC_ASN1Template ocsp_CertStatusUnknownTemplate[] = { 1404 { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, 1405 offsetof(ocspCertStatus, certStatusInfo.unknownInfo), 1406 SEC_ASN1_SUB(SEC_NullTemplate) } 1407 }; 1408 static const SEC_ASN1Template ocsp_CertStatusOtherTemplate[] = { 1409 { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 1410 offsetof(ocspCertStatus, certStatusInfo.otherInfo), 1411 SEC_ASN1_SUB(SEC_AnyTemplate) } 1412 }; 1413 1414 /* 1415 * RevokedInfo ::= SEQUENCE { 1416 * revocationTime GeneralizedTime, 1417 * revocationReason [0] EXPLICIT CRLReason OPTIONAL } 1418 * 1419 * Note: this should be static but the AIX compiler doesn't like it (because it 1420 * was forward-declared above); it is not meant to be exported, but this 1421 * is the only way it will compile. 1422 */ 1423 const SEC_ASN1Template ocsp_RevokedInfoTemplate[] = { 1424 { SEC_ASN1_SEQUENCE, 1425 0, NULL, sizeof(ocspRevokedInfo) }, 1426 { SEC_ASN1_GENERALIZED_TIME, 1427 offsetof(ocspRevokedInfo, revocationTime) }, 1428 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1429 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1430 SEC_ASN1_XTRN | 0, 1431 offsetof(ocspRevokedInfo, revocationReason), 1432 SEC_ASN1_SUB(SEC_PointerToEnumeratedTemplate) }, 1433 { 0 } 1434 }; 1435 1436 /* 1437 * OCSP-specific extension templates: 1438 */ 1439 1440 /* 1441 * ServiceLocator ::= SEQUENCE { 1442 * issuer Name, 1443 * locator AuthorityInfoAccessSyntax OPTIONAL } 1444 */ 1445 static const SEC_ASN1Template ocsp_ServiceLocatorTemplate[] = { 1446 { SEC_ASN1_SEQUENCE, 1447 0, NULL, sizeof(ocspServiceLocator) }, 1448 { SEC_ASN1_POINTER, 1449 offsetof(ocspServiceLocator, issuer), 1450 CERT_NameTemplate }, 1451 { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, 1452 offsetof(ocspServiceLocator, locator) }, 1453 { 0 } 1454 }; 1455 1456 /* 1457 * REQUEST SUPPORT FUNCTIONS (encode/create/decode/destroy): 1458 */ 1459 1460 /* 1461 * FUNCTION: CERT_EncodeOCSPRequest 1462 * DER encodes an OCSP Request, possibly adding a signature as well. 1463 * XXX Signing is not yet supported, however; see comments in code. 1464 * INPUTS: 1465 * PLArenaPool *arena 1466 * The return value is allocated from here. 1467 * If a NULL is passed in, allocation is done from the heap instead. 1468 * CERTOCSPRequest *request 1469 * The request to be encoded. 1470 * void *pwArg 1471 * Pointer to argument for password prompting, if needed. (Definitely 1472 * not needed if not signing.) 1473 * RETURN: 1474 * Returns a NULL on error and a pointer to the SECItem with the 1475 * encoded value otherwise. Any error is likely to be low-level 1476 * (e.g. no memory). 1477 */ 1478 SECItem * 1479 CERT_EncodeOCSPRequest(PLArenaPool *arena, CERTOCSPRequest *request, 1480 void *pwArg) 1481 { 1482 SECStatus rv; 1483 1484 /* XXX All of these should generate errors if they fail. */ 1485 PORT_Assert(request); 1486 PORT_Assert(request->tbsRequest); 1487 1488 if (request->tbsRequest->extensionHandle != NULL) { 1489 rv = CERT_FinishExtensions(request->tbsRequest->extensionHandle); 1490 request->tbsRequest->extensionHandle = NULL; 1491 if (rv != SECSuccess) 1492 return NULL; 1493 } 1494 1495 /* 1496 * XXX When signed requests are supported and request->optionalSignature 1497 * is not NULL: 1498 * - need to encode tbsRequest->requestorName 1499 * - need to encode tbsRequest 1500 * - need to sign that encoded result (using cert in sig), filling in the 1501 * request->optionalSignature structure with the result, the signing 1502 * algorithm and (perhaps?) the cert (and its chain?) in derCerts 1503 */ 1504 1505 return SEC_ASN1EncodeItem(arena, NULL, request, ocsp_OCSPRequestTemplate); 1506 } 1507 1508 /* 1509 * FUNCTION: CERT_DecodeOCSPRequest 1510 * Decode a DER encoded OCSP Request. 1511 * INPUTS: 1512 * SECItem *src 1513 * Pointer to a SECItem holding DER encoded OCSP Request. 1514 * RETURN: 1515 * Returns a pointer to a CERTOCSPRequest containing the decoded request. 1516 * On error, returns NULL. Most likely error is trouble decoding 1517 * (SEC_ERROR_OCSP_MALFORMED_REQUEST), or low-level problem (no memory). 1518 */ 1519 CERTOCSPRequest * 1520 CERT_DecodeOCSPRequest(const SECItem *src) 1521 { 1522 PLArenaPool *arena = NULL; 1523 SECStatus rv = SECFailure; 1524 CERTOCSPRequest *dest = NULL; 1525 int i; 1526 SECItem newSrc; 1527 1528 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1529 if (arena == NULL) { 1530 goto loser; 1531 } 1532 dest = (CERTOCSPRequest *)PORT_ArenaZAlloc(arena, 1533 sizeof(CERTOCSPRequest)); 1534 if (dest == NULL) { 1535 goto loser; 1536 } 1537 dest->arena = arena; 1538 1539 /* copy the DER into the arena, since Quick DER returns data that points 1540 into the DER input, which may get freed by the caller */ 1541 rv = SECITEM_CopyItem(arena, &newSrc, src); 1542 if (rv != SECSuccess) { 1543 goto loser; 1544 } 1545 1546 rv = SEC_QuickDERDecodeItem(arena, dest, ocsp_OCSPRequestTemplate, &newSrc); 1547 if (rv != SECSuccess) { 1548 if (PORT_GetError() == SEC_ERROR_BAD_DER) 1549 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST); 1550 goto loser; 1551 } 1552 1553 /* 1554 * XXX I would like to find a way to get rid of the necessity 1555 * of doing this copying of the arena pointer. 1556 */ 1557 for (i = 0; dest->tbsRequest->requestList[i] != NULL; i++) { 1558 dest->tbsRequest->requestList[i]->arena = arena; 1559 } 1560 1561 return dest; 1562 1563 loser: 1564 if (arena != NULL) { 1565 PORT_FreeArena(arena, PR_FALSE); 1566 } 1567 return NULL; 1568 } 1569 1570 SECStatus 1571 CERT_DestroyOCSPCertID(CERTOCSPCertID *certID) 1572 { 1573 if (certID && certID->poolp) { 1574 PORT_FreeArena(certID->poolp, PR_FALSE); 1575 return SECSuccess; 1576 } 1577 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1578 return SECFailure; 1579 } 1580 1581 /* 1582 * Digest data using the specified algorithm. 1583 * The necessary storage for the digest data is allocated. If "fill" is 1584 * non-null, the data is put there, otherwise a SECItem is allocated. 1585 * Allocation from "arena" if it is non-null, heap otherwise. Any problem 1586 * results in a NULL being returned (and an appropriate error set). 1587 */ 1588 1589 SECItem * 1590 ocsp_DigestValue(PLArenaPool *arena, SECOidTag digestAlg, 1591 SECItem *fill, const SECItem *src) 1592 { 1593 const SECHashObject *digestObject; 1594 SECItem *result = NULL; 1595 void *mark = NULL; 1596 void *digestBuff = NULL; 1597 1598 if (arena != NULL) { 1599 mark = PORT_ArenaMark(arena); 1600 } 1601 1602 digestObject = HASH_GetHashObjectByOidTag(digestAlg); 1603 if (digestObject == NULL) { 1604 goto loser; 1605 } 1606 1607 if (fill == NULL || fill->data == NULL) { 1608 result = SECITEM_AllocItem(arena, fill, digestObject->length); 1609 if (result == NULL) { 1610 goto loser; 1611 } 1612 digestBuff = result->data; 1613 } else { 1614 if (fill->len < digestObject->length) { 1615 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1616 goto loser; 1617 } 1618 digestBuff = fill->data; 1619 } 1620 1621 if (PK11_HashBuf(digestAlg, digestBuff, 1622 src->data, src->len) != SECSuccess) { 1623 goto loser; 1624 } 1625 1626 if (arena != NULL) { 1627 PORT_ArenaUnmark(arena, mark); 1628 } 1629 1630 if (result == NULL) { 1631 result = fill; 1632 } 1633 return result; 1634 1635 loser: 1636 if (arena != NULL) { 1637 PORT_ArenaRelease(arena, mark); 1638 } else { 1639 if (result != NULL) { 1640 SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE); 1641 } 1642 } 1643 return (NULL); 1644 } 1645 1646 /* 1647 * Digest the cert's subject public key using the specified algorithm. 1648 * The necessary storage for the digest data is allocated. If "fill" is 1649 * non-null, the data is put there, otherwise a SECItem is allocated. 1650 * Allocation from "arena" if it is non-null, heap otherwise. Any problem 1651 * results in a NULL being returned (and an appropriate error set). 1652 */ 1653 SECItem * 1654 CERT_GetSubjectPublicKeyDigest(PLArenaPool *arena, const CERTCertificate *cert, 1655 SECOidTag digestAlg, SECItem *fill) 1656 { 1657 SECItem spk; 1658 1659 /* 1660 * Copy just the length and data pointer (nothing needs to be freed) 1661 * of the subject public key so we can convert the length from bits 1662 * to bytes, which is what the digest function expects. 1663 */ 1664 spk = cert->subjectPublicKeyInfo.subjectPublicKey; 1665 DER_ConvertBitString(&spk); 1666 1667 return ocsp_DigestValue(arena, digestAlg, fill, &spk); 1668 } 1669 1670 /* 1671 * Digest the cert's subject name using the specified algorithm. 1672 */ 1673 SECItem * 1674 CERT_GetSubjectNameDigest(PLArenaPool *arena, const CERTCertificate *cert, 1675 SECOidTag digestAlg, SECItem *fill) 1676 { 1677 SECItem name; 1678 1679 /* 1680 * Copy just the length and data pointer (nothing needs to be freed) 1681 * of the subject name 1682 */ 1683 name = cert->derSubject; 1684 1685 return ocsp_DigestValue(arena, digestAlg, fill, &name); 1686 } 1687 1688 /* 1689 * Create and fill-in a CertID. This function fills in the hash values 1690 * (issuerNameHash and issuerKeyHash), and is hardwired to use SHA1. 1691 * Someday it might need to be more flexible about hash algorithm, but 1692 * for now we have no intention/need to create anything else. 1693 * 1694 * Error causes a null to be returned; most likely cause is trouble 1695 * finding the certificate issuer (SEC_ERROR_UNKNOWN_ISSUER). 1696 * Other errors are low-level problems (no memory, bad database, etc.). 1697 */ 1698 static CERTOCSPCertID * 1699 ocsp_CreateCertID(PLArenaPool *arena, CERTCertificate *cert, PRTime time) 1700 { 1701 CERTOCSPCertID *certID; 1702 CERTCertificate *issuerCert = NULL; 1703 void *mark = PORT_ArenaMark(arena); 1704 SECStatus rv; 1705 1706 PORT_Assert(arena != NULL); 1707 1708 certID = PORT_ArenaZNew(arena, CERTOCSPCertID); 1709 if (certID == NULL) { 1710 goto loser; 1711 } 1712 1713 rv = SECOID_SetAlgorithmID(arena, &certID->hashAlgorithm, SEC_OID_SHA1, 1714 NULL); 1715 if (rv != SECSuccess) { 1716 goto loser; 1717 } 1718 1719 issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); 1720 if (issuerCert == NULL) { 1721 goto loser; 1722 } 1723 1724 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_SHA1, 1725 &(certID->issuerNameHash)) == NULL) { 1726 goto loser; 1727 } 1728 certID->issuerSHA1NameHash.data = certID->issuerNameHash.data; 1729 certID->issuerSHA1NameHash.len = certID->issuerNameHash.len; 1730 1731 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD5, 1732 &(certID->issuerMD5NameHash)) == NULL) { 1733 goto loser; 1734 } 1735 1736 if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD2, 1737 &(certID->issuerMD2NameHash)) == NULL) { 1738 goto loser; 1739 } 1740 1741 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_SHA1, 1742 &certID->issuerKeyHash) == NULL) { 1743 goto loser; 1744 } 1745 certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data; 1746 certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len; 1747 /* cache the other two hash algorithms as well */ 1748 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_MD5, 1749 &certID->issuerMD5KeyHash) == NULL) { 1750 goto loser; 1751 } 1752 if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_MD2, 1753 &certID->issuerMD2KeyHash) == NULL) { 1754 goto loser; 1755 } 1756 1757 /* now we are done with issuerCert */ 1758 CERT_DestroyCertificate(issuerCert); 1759 issuerCert = NULL; 1760 1761 rv = SECITEM_CopyItem(arena, &certID->serialNumber, &cert->serialNumber); 1762 if (rv != SECSuccess) { 1763 goto loser; 1764 } 1765 1766 PORT_ArenaUnmark(arena, mark); 1767 return certID; 1768 1769 loser: 1770 if (issuerCert != NULL) { 1771 CERT_DestroyCertificate(issuerCert); 1772 } 1773 PORT_ArenaRelease(arena, mark); 1774 return NULL; 1775 } 1776 1777 CERTOCSPCertID * 1778 CERT_CreateOCSPCertID(CERTCertificate *cert, PRTime time) 1779 { 1780 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1781 CERTOCSPCertID *certID; 1782 PORT_Assert(arena != NULL); 1783 if (!arena) 1784 return NULL; 1785 1786 certID = ocsp_CreateCertID(arena, cert, time); 1787 if (!certID) { 1788 PORT_FreeArena(arena, PR_FALSE); 1789 return NULL; 1790 } 1791 certID->poolp = arena; 1792 return certID; 1793 } 1794 1795 static CERTOCSPCertID * 1796 cert_DupOCSPCertID(const CERTOCSPCertID *src) 1797 { 1798 CERTOCSPCertID *dest; 1799 PLArenaPool *arena = NULL; 1800 1801 if (!src) { 1802 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1803 return NULL; 1804 } 1805 1806 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1807 if (!arena) 1808 goto loser; 1809 1810 dest = PORT_ArenaZNew(arena, CERTOCSPCertID); 1811 if (!dest) 1812 goto loser; 1813 1814 #define DUPHELP(element) \ 1815 if (src->element.data && \ 1816 SECITEM_CopyItem(arena, &dest->element, &src->element) != \ 1817 SECSuccess) { \ 1818 goto loser; \ 1819 } 1820 1821 DUPHELP(hashAlgorithm.algorithm) 1822 DUPHELP(hashAlgorithm.parameters) 1823 DUPHELP(issuerNameHash) 1824 DUPHELP(issuerKeyHash) 1825 DUPHELP(serialNumber) 1826 DUPHELP(issuerSHA1NameHash) 1827 DUPHELP(issuerMD5NameHash) 1828 DUPHELP(issuerMD2NameHash) 1829 DUPHELP(issuerSHA1KeyHash) 1830 DUPHELP(issuerMD5KeyHash) 1831 DUPHELP(issuerMD2KeyHash) 1832 1833 dest->poolp = arena; 1834 return dest; 1835 1836 loser: 1837 if (arena) 1838 PORT_FreeArena(arena, PR_FALSE); 1839 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); 1840 return NULL; 1841 } 1842 1843 /* 1844 * Callback to set Extensions in request object 1845 */ 1846 void 1847 SetSingleReqExts(void *object, CERTCertExtension **exts) 1848 { 1849 ocspSingleRequest *singleRequest = 1850 (ocspSingleRequest *)object; 1851 1852 singleRequest->singleRequestExtensions = exts; 1853 } 1854 1855 /* 1856 * Add the Service Locator extension to the singleRequestExtensions 1857 * for the given singleRequest. 1858 * 1859 * All errors are internal or low-level problems (e.g. no memory). 1860 */ 1861 static SECStatus 1862 ocsp_AddServiceLocatorExtension(ocspSingleRequest *singleRequest, 1863 CERTCertificate *cert) 1864 { 1865 ocspServiceLocator *serviceLocator = NULL; 1866 void *extensionHandle = NULL; 1867 SECStatus rv = SECFailure; 1868 1869 serviceLocator = PORT_ZNew(ocspServiceLocator); 1870 if (serviceLocator == NULL) 1871 goto loser; 1872 1873 /* 1874 * Normally it would be a bad idea to do a direct reference like 1875 * this rather than allocate and copy the name *or* at least dup 1876 * a reference of the cert. But all we need is to be able to read 1877 * the issuer name during the encoding we are about to do, so a 1878 * copy is just a waste of time. 1879 */ 1880 serviceLocator->issuer = &cert->issuer; 1881 1882 rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS, 1883 &serviceLocator->locator); 1884 if (rv != SECSuccess) { 1885 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) 1886 goto loser; 1887 } 1888 1889 /* prepare for following loser gotos */ 1890 rv = SECFailure; 1891 PORT_SetError(0); 1892 1893 extensionHandle = cert_StartExtensions(singleRequest, 1894 singleRequest->arena, SetSingleReqExts); 1895 if (extensionHandle == NULL) 1896 goto loser; 1897 1898 rv = CERT_EncodeAndAddExtension(extensionHandle, 1899 SEC_OID_PKIX_OCSP_SERVICE_LOCATOR, 1900 serviceLocator, PR_FALSE, 1901 ocsp_ServiceLocatorTemplate); 1902 1903 loser: 1904 if (extensionHandle != NULL) { 1905 /* 1906 * Either way we have to finish out the extension context (so it gets 1907 * freed). But careful not to override any already-set bad status. 1908 */ 1909 SECStatus tmprv = CERT_FinishExtensions(extensionHandle); 1910 if (rv == SECSuccess) 1911 rv = tmprv; 1912 } 1913 1914 /* 1915 * Finally, free the serviceLocator structure itself and we are done. 1916 */ 1917 if (serviceLocator != NULL) { 1918 if (serviceLocator->locator.data != NULL) 1919 SECITEM_FreeItem(&serviceLocator->locator, PR_FALSE); 1920 PORT_Free(serviceLocator); 1921 } 1922 1923 return rv; 1924 } 1925 1926 /* 1927 * Creates an array of ocspSingleRequest based on a list of certs. 1928 * Note that the code which later compares the request list with the 1929 * response expects this array to be in the exact same order as the 1930 * certs are found in the list. It would be harder to change that 1931 * order than preserve it, but since the requirement is not obvious, 1932 * it deserves to be mentioned. 1933 * 1934 * Any problem causes a null return and error set: 1935 * SEC_ERROR_UNKNOWN_ISSUER 1936 * Other errors are low-level problems (no memory, bad database, etc.). 1937 */ 1938 static ocspSingleRequest ** 1939 ocsp_CreateSingleRequestList(PLArenaPool *arena, CERTCertList *certList, 1940 PRTime time, PRBool includeLocator) 1941 { 1942 ocspSingleRequest **requestList = NULL; 1943 CERTCertListNode *node = NULL; 1944 int i, count; 1945 void *mark = PORT_ArenaMark(arena); 1946 1947 node = CERT_LIST_HEAD(certList); 1948 for (count = 0; !CERT_LIST_END(node, certList); count++) { 1949 node = CERT_LIST_NEXT(node); 1950 } 1951 1952 if (count == 0) 1953 goto loser; 1954 1955 requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, count + 1); 1956 if (requestList == NULL) 1957 goto loser; 1958 1959 node = CERT_LIST_HEAD(certList); 1960 for (i = 0; !CERT_LIST_END(node, certList); i++) { 1961 requestList[i] = PORT_ArenaZNew(arena, ocspSingleRequest); 1962 if (requestList[i] == NULL) 1963 goto loser; 1964 1965 OCSP_TRACE(("OCSP CERT_CreateOCSPRequest %s\n", node->cert->subjectName)); 1966 requestList[i]->arena = arena; 1967 requestList[i]->reqCert = ocsp_CreateCertID(arena, node->cert, time); 1968 if (requestList[i]->reqCert == NULL) 1969 goto loser; 1970 1971 if (includeLocator == PR_TRUE) { 1972 SECStatus rv; 1973 1974 rv = ocsp_AddServiceLocatorExtension(requestList[i], node->cert); 1975 if (rv != SECSuccess) 1976 goto loser; 1977 } 1978 1979 node = CERT_LIST_NEXT(node); 1980 } 1981 1982 PORT_Assert(i == count); 1983 1984 PORT_ArenaUnmark(arena, mark); 1985 requestList[i] = NULL; 1986 return requestList; 1987 1988 loser: 1989 PORT_ArenaRelease(arena, mark); 1990 return NULL; 1991 } 1992 1993 static ocspSingleRequest ** 1994 ocsp_CreateRequestFromCert(PLArenaPool *arena, 1995 CERTOCSPCertID *certID, 1996 CERTCertificate *singleCert, 1997 PRTime time, 1998 PRBool includeLocator) 1999 { 2000 ocspSingleRequest **requestList = NULL; 2001 void *mark = PORT_ArenaMark(arena); 2002 PORT_Assert(certID != NULL && singleCert != NULL); 2003 2004 /* meaning of value 2: one entry + one end marker */ 2005 requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, 2); 2006 if (requestList == NULL) 2007 goto loser; 2008 requestList[0] = PORT_ArenaZNew(arena, ocspSingleRequest); 2009 if (requestList[0] == NULL) 2010 goto loser; 2011 requestList[0]->arena = arena; 2012 /* certID will live longer than the request */ 2013 requestList[0]->reqCert = certID; 2014 2015 if (includeLocator == PR_TRUE) { 2016 SECStatus rv; 2017 rv = ocsp_AddServiceLocatorExtension(requestList[0], singleCert); 2018 if (rv != SECSuccess) 2019 goto loser; 2020 } 2021 2022 PORT_ArenaUnmark(arena, mark); 2023 requestList[1] = NULL; 2024 return requestList; 2025 2026 loser: 2027 PORT_ArenaRelease(arena, mark); 2028 return NULL; 2029 } 2030 2031 static CERTOCSPRequest * 2032 ocsp_prepareEmptyOCSPRequest(void) 2033 { 2034 PLArenaPool *arena = NULL; 2035 CERTOCSPRequest *request = NULL; 2036 ocspTBSRequest *tbsRequest = NULL; 2037 2038 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 2039 if (arena == NULL) { 2040 goto loser; 2041 } 2042 request = PORT_ArenaZNew(arena, CERTOCSPRequest); 2043 if (request == NULL) { 2044 goto loser; 2045 } 2046 request->arena = arena; 2047 2048 tbsRequest = PORT_ArenaZNew(arena, ocspTBSRequest); 2049 if (tbsRequest == NULL) { 2050 goto loser; 2051 } 2052 request->tbsRequest = tbsRequest; 2053 /* version 1 is the default, so we need not fill in a version number */ 2054 return request; 2055 2056 loser: 2057 if (arena != NULL) { 2058 PORT_FreeArena(arena, PR_FALSE); 2059 } 2060 return NULL; 2061 } 2062 2063 CERTOCSPRequest * 2064 cert_CreateSingleCertOCSPRequest(CERTOCSPCertID *certID, 2065 CERTCertificate *singleCert, 2066 PRTime time, 2067 PRBool addServiceLocator, 2068 CERTCertificate *signerCert) 2069 { 2070 CERTOCSPRequest *request; 2071 OCSP_TRACE(("OCSP cert_CreateSingleCertOCSPRequest %s\n", singleCert->subjectName)); 2072 2073 /* XXX Support for signerCert may be implemented later, 2074 * see also the comment in CERT_CreateOCSPRequest. 2075 */ 2076 if (signerCert != NULL) { 2077 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 2078 return NULL; 2079 } 2080 2081 request = ocsp_prepareEmptyOCSPRequest(); 2082 if (!request) 2083 return NULL; 2084 /* 2085 * Version 1 is the default, so we need not fill in a version number. 2086 * Now create the list of single requests, one for each cert. 2087 */ 2088 request->tbsRequest->requestList = 2089 ocsp_CreateRequestFromCert(request->arena, 2090 certID, 2091 singleCert, 2092 time, 2093 addServiceLocator); 2094 if (request->tbsRequest->requestList == NULL) { 2095 PORT_FreeArena(request->arena, PR_FALSE); 2096 return NULL; 2097 } 2098 return request; 2099 } 2100 2101 /* 2102 * FUNCTION: CERT_CreateOCSPRequest 2103 * Creates a CERTOCSPRequest, requesting the status of the certs in 2104 * the given list. 2105 * INPUTS: 2106 * CERTCertList *certList 2107 * A list of certs for which status will be requested. 2108 * Note that all of these certificates should have the same issuer, 2109 * or it's expected the response will be signed by a trusted responder. 2110 * If the certs need to be broken up into multiple requests, that 2111 * must be handled by the caller (and thus by having multiple calls 2112 * to this routine), who knows about where the request(s) are being 2113 * sent and whether there are any trusted responders in place. 2114 * PRTime time 2115 * Indicates the time for which the certificate status is to be 2116 * determined -- this may be used in the search for the cert's issuer 2117 * but has no effect on the request itself. 2118 * PRBool addServiceLocator 2119 * If true, the Service Locator extension should be added to the 2120 * single request(s) for each cert. 2121 * CERTCertificate *signerCert 2122 * If non-NULL, means sign the request using this cert. Otherwise, 2123 * do not sign. 2124 * XXX note that request signing is not yet supported; see comment in code 2125 * RETURN: 2126 * A pointer to a CERTOCSPRequest structure containing an OCSP request 2127 * for the cert list. On error, null is returned, with an error set 2128 * indicating the reason. This is likely SEC_ERROR_UNKNOWN_ISSUER. 2129 * (The issuer is needed to create a request for the certificate.) 2130 * Other errors are low-level problems (no memory, bad database, etc.). 2131 */ 2132 CERTOCSPRequest * 2133 CERT_CreateOCSPRequest(CERTCertList *certList, PRTime time, 2134 PRBool addServiceLocator, 2135 CERTCertificate *signerCert) 2136 { 2137 CERTOCSPRequest *request = NULL; 2138 2139 if (!certList) { 2140 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2141 return NULL; 2142 } 2143 /* 2144 * XXX When we are prepared to put signing of requests back in, 2145 * we will need to allocate a signature 2146 * structure for the request, fill in the "derCerts" field in it, 2147 * save the signerCert there, as well as fill in the "requestorName" 2148 * field of the tbsRequest. 2149 */ 2150 if (signerCert != NULL) { 2151 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 2152 return NULL; 2153 } 2154 request = ocsp_prepareEmptyOCSPRequest(); 2155 if (!request) 2156 return NULL; 2157 /* 2158 * Now create the list of single requests, one for each cert. 2159 */ 2160 request->tbsRequest->requestList = 2161 ocsp_CreateSingleRequestList(request->arena, 2162 certList, 2163 time, 2164 addServiceLocator); 2165 if (request->tbsRequest->requestList == NULL) { 2166 PORT_FreeArena(request->arena, PR_FALSE); 2167 return NULL; 2168 } 2169 return request; 2170 } 2171 2172 /* 2173 * FUNCTION: CERT_AddOCSPAcceptableResponses 2174 * Add the AcceptableResponses extension to an OCSP Request. 2175 * INPUTS: 2176 * CERTOCSPRequest *request 2177 * The request to which the extension should be added. 2178 * ... 2179 * A list (of one or more) of SECOidTag -- each of the response types 2180 * to be added. The last OID *must* be SEC_OID_PKIX_OCSP_BASIC_RESPONSE. 2181 * (This marks the end of the list, and it must be specified because a 2182 * client conforming to the OCSP standard is required to handle the basic 2183 * response type.) The OIDs are not checked in any way. 2184 * RETURN: 2185 * SECSuccess if the extension is added; SECFailure if anything goes wrong. 2186 * All errors are internal or low-level problems (e.g. no memory). 2187 */ 2188 2189 void 2190 SetRequestExts(void *object, CERTCertExtension **exts) 2191 { 2192 CERTOCSPRequest *request = (CERTOCSPRequest *)object; 2193 2194 request->tbsRequest->requestExtensions = exts; 2195 } 2196 2197 #if defined(__GNUC__) && !defined(NSS_NO_GCC48) 2198 #pragma GCC diagnostic push 2199 #pragma GCC diagnostic ignored "-Wvarargs" 2200 #endif 2201 SECStatus 2202 CERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request, 2203 SECOidTag responseType0, ...) 2204 { 2205 void *extHandle; 2206 va_list ap; 2207 int i, count; 2208 SECOidTag responseType; 2209 SECOidData *responseOid; 2210 SECItem **acceptableResponses = NULL; 2211 SECStatus rv = SECFailure; 2212 2213 extHandle = request->tbsRequest->extensionHandle; 2214 if (extHandle == NULL) { 2215 extHandle = cert_StartExtensions(request, request->arena, SetRequestExts); 2216 if (extHandle == NULL) 2217 goto loser; 2218 } 2219 2220 /* Count number of OIDS going into the extension value. */ 2221 count = 1; 2222 if (responseType0 != SEC_OID_PKIX_OCSP_BASIC_RESPONSE) { 2223 va_start(ap, responseType0); 2224 do { 2225 count++; 2226 responseType = va_arg(ap, SECOidTag); 2227 } while (responseType != SEC_OID_PKIX_OCSP_BASIC_RESPONSE); 2228 va_end(ap); 2229 } 2230 2231 acceptableResponses = PORT_NewArray(SECItem *, count + 1); 2232 if (acceptableResponses == NULL) 2233 goto loser; 2234 2235 i = 0; 2236 responseOid = SECOID_FindOIDByTag(responseType0); 2237 acceptableResponses[i++] = &(responseOid->oid); 2238 if (count > 1) { 2239 va_start(ap, responseType0); 2240 for (; i < count; i++) { 2241 responseType = va_arg(ap, SECOidTag); 2242 responseOid = SECOID_FindOIDByTag(responseType); 2243 acceptableResponses[i] = &(responseOid->oid); 2244 } 2245 va_end(ap); 2246 } 2247 acceptableResponses[i] = NULL; 2248 2249 rv = CERT_EncodeAndAddExtension(extHandle, SEC_OID_PKIX_OCSP_RESPONSE, 2250 &acceptableResponses, PR_FALSE, 2251 SEC_ASN1_GET(SEC_SequenceOfObjectIDTemplate)); 2252 if (rv != SECSuccess) 2253 goto loser; 2254 2255 PORT_Free(acceptableResponses); 2256 if (request->tbsRequest->extensionHandle == NULL) 2257 request->tbsRequest->extensionHandle = extHandle; 2258 return SECSuccess; 2259 2260 loser: 2261 if (acceptableResponses != NULL) 2262 PORT_Free(acceptableResponses); 2263 if (extHandle != NULL) 2264 (void)CERT_FinishExtensions(extHandle); 2265 return rv; 2266 } 2267 #if defined(__GNUC__) && !defined(NSS_NO_GCC48) 2268 #pragma GCC diagnostic pop 2269 #endif 2270 2271 /* 2272 * FUNCTION: CERT_DestroyOCSPRequest 2273 * Frees an OCSP Request structure. 2274 * INPUTS: 2275 * CERTOCSPRequest *request 2276 * Pointer to CERTOCSPRequest to be freed. 2277 * RETURN: 2278 * No return value; no errors. 2279 */ 2280 void 2281 CERT_DestroyOCSPRequest(CERTOCSPRequest *request) 2282 { 2283 if (request == NULL) 2284 return; 2285 2286 if (request->tbsRequest != NULL) { 2287 if (request->tbsRequest->requestorName != NULL) 2288 CERT_DestroyGeneralNameList(request->tbsRequest->requestorName); 2289 if (request->tbsRequest->extensionHandle != NULL) 2290 (void)CERT_FinishExtensions(request->tbsRequest->extensionHandle); 2291 } 2292 2293 if (request->optionalSignature != NULL) { 2294 if (request->optionalSignature->cert != NULL) 2295 CERT_DestroyCertificate(request->optionalSignature->cert); 2296 2297 /* 2298 * XXX Need to free derCerts? Or do they come out of arena? 2299 * (Currently we never fill in derCerts, which is why the 2300 * answer is not obvious. Once we do, add any necessary code 2301 * here and remove this comment.) 2302 */ 2303 } 2304 2305 /* 2306 * We should actually never have a request without an arena, 2307 * but check just in case. (If there isn't one, there is not 2308 * much we can do about it...) 2309 */ 2310 PORT_Assert(request->arena != NULL); 2311 if (request->arena != NULL) 2312 PORT_FreeArena(request->arena, PR_FALSE); 2313 } 2314 2315 /* 2316 * RESPONSE SUPPORT FUNCTIONS (encode/create/decode/destroy): 2317 */ 2318 2319 /* 2320 * Helper function for encoding or decoding a ResponderID -- based on the 2321 * given type, return the associated template for that choice. 2322 */ 2323 static const SEC_ASN1Template * 2324 ocsp_ResponderIDTemplateByType(CERTOCSPResponderIDType responderIDType) 2325 { 2326 const SEC_ASN1Template *responderIDTemplate; 2327 2328 switch (responderIDType) { 2329 case ocspResponderID_byName: 2330 responderIDTemplate = ocsp_ResponderIDByNameTemplate; 2331 break; 2332 case ocspResponderID_byKey: 2333 responderIDTemplate = ocsp_ResponderIDByKeyTemplate; 2334 break; 2335 case ocspResponderID_other: 2336 default: 2337 PORT_Assert(responderIDType == ocspResponderID_other); 2338 responderIDTemplate = ocsp_ResponderIDOtherTemplate; 2339 break; 2340 } 2341 2342 return responderIDTemplate; 2343 } 2344 2345 /* 2346 * Helper function for encoding or decoding a CertStatus -- based on the 2347 * given type, return the associated template for that choice. 2348 */ 2349 static const SEC_ASN1Template * 2350 ocsp_CertStatusTemplateByType(ocspCertStatusType certStatusType) 2351 { 2352 const SEC_ASN1Template *certStatusTemplate; 2353 2354 switch (certStatusType) { 2355 case ocspCertStatus_good: 2356 certStatusTemplate = ocsp_CertStatusGoodTemplate; 2357 break; 2358 case ocspCertStatus_revoked: 2359 certStatusTemplate = ocsp_CertStatusRevokedTemplate; 2360 break; 2361 case ocspCertStatus_unknown: 2362 certStatusTemplate = ocsp_CertStatusUnknownTemplate; 2363 break; 2364 case ocspCertStatus_other: 2365 default: 2366 PORT_Assert(certStatusType == ocspCertStatus_other); 2367 certStatusTemplate = ocsp_CertStatusOtherTemplate; 2368 break; 2369 } 2370 2371 return certStatusTemplate; 2372 } 2373 2374 /* 2375 * Helper function for decoding a certStatus -- turn the actual DER tag 2376 * into our local translation. 2377 */ 2378 static ocspCertStatusType 2379 ocsp_CertStatusTypeByTag(int derTag) 2380 { 2381 ocspCertStatusType certStatusType; 2382 2383 switch (derTag) { 2384 case 0: 2385 certStatusType = ocspCertStatus_good; 2386 break; 2387 case 1: 2388 certStatusType = ocspCertStatus_revoked; 2389 break; 2390 case 2: 2391 certStatusType = ocspCertStatus_unknown; 2392 break; 2393 default: 2394 certStatusType = ocspCertStatus_other; 2395 break; 2396 } 2397 2398 return certStatusType; 2399 } 2400 2401 /* 2402 * Helper function for decoding SingleResponses -- they each contain 2403 * a status which is encoded as CHOICE, which needs to be decoded "by hand". 2404 * 2405 * Note -- on error, this routine does not release the memory it may 2406 * have allocated; it expects its caller to do that. 2407 */ 2408 static SECStatus 2409 ocsp_FinishDecodingSingleResponses(PLArenaPool *reqArena, 2410 CERTOCSPSingleResponse **responses) 2411 { 2412 ocspCertStatus *certStatus; 2413 ocspCertStatusType certStatusType; 2414 const SEC_ASN1Template *certStatusTemplate; 2415 int derTag; 2416 int i; 2417 SECStatus rv = SECFailure; 2418 2419 if (!reqArena) { 2420 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2421 return SECFailure; 2422 } 2423 2424 if (responses == NULL) /* nothing to do */ 2425 return SECSuccess; 2426 2427 for (i = 0; responses[i] != NULL; i++) { 2428 SECItem *newStatus; 2429 /* 2430 * The following assert points out internal errors (problems in 2431 * the template definitions or in the ASN.1 decoder itself, etc.). 2432 */ 2433 PORT_Assert(responses[i]->derCertStatus.data != NULL); 2434 2435 derTag = responses[i]->derCertStatus.data[0] & SEC_ASN1_TAGNUM_MASK; 2436 certStatusType = ocsp_CertStatusTypeByTag(derTag); 2437 certStatusTemplate = ocsp_CertStatusTemplateByType(certStatusType); 2438 2439 certStatus = PORT_ArenaZAlloc(reqArena, sizeof(ocspCertStatus)); 2440 if (certStatus == NULL) { 2441 goto loser; 2442 } 2443 newStatus = SECITEM_ArenaDupItem(reqArena, &responses[i]->derCertStatus); 2444 if (!newStatus) { 2445 goto loser; 2446 } 2447 rv = SEC_QuickDERDecodeItem(reqArena, certStatus, certStatusTemplate, 2448 newStatus); 2449 if (rv != SECSuccess) { 2450 if (PORT_GetError() == SEC_ERROR_BAD_DER) 2451 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); 2452 goto loser; 2453 } 2454 2455 certStatus->certStatusType = certStatusType; 2456 responses[i]->certStatus = certStatus; 2457 } 2458 2459 return SECSuccess; 2460 2461 loser: 2462 return rv; 2463 } 2464 2465 /* 2466 * Helper function for decoding a responderID -- turn the actual DER tag 2467 * into our local translation. 2468 */ 2469 static CERTOCSPResponderIDType 2470 ocsp_ResponderIDTypeByTag(int derTag) 2471 { 2472 CERTOCSPResponderIDType responderIDType; 2473 2474 switch (derTag) { 2475 case 1: 2476 responderIDType = ocspResponderID_byName; 2477 break; 2478 case 2: 2479 responderIDType = ocspResponderID_byKey; 2480 break; 2481 default: 2482 responderIDType = ocspResponderID_other; 2483 break; 2484 } 2485 2486 return responderIDType; 2487 } 2488 2489 /* 2490 * Decode "src" as a BasicOCSPResponse, returning the result. 2491 */ 2492 static ocspBasicOCSPResponse * 2493 ocsp_DecodeBasicOCSPResponse(PLArenaPool *arena, SECItem *src) 2494 { 2495 void *mark; 2496 ocspBasicOCSPResponse *basicResponse; 2497 ocspResponseData *responseData; 2498 ocspResponderID *responderID; 2499 CERTOCSPResponderIDType responderIDType; 2500 const SEC_ASN1Template *responderIDTemplate; 2501 int derTag; 2502 SECStatus rv; 2503 SECItem newsrc; 2504 2505 mark = PORT_ArenaMark(arena); 2506 2507 basicResponse = PORT_ArenaZAlloc(arena, sizeof(ocspBasicOCSPResponse)); 2508 if (basicResponse == NULL) { 2509 goto loser; 2510 } 2511 2512 /* copy the DER into the arena, since Quick DER returns data that points 2513 into the DER input, which may get freed by the caller */ 2514 rv = SECITEM_CopyItem(arena, &newsrc, src); 2515 if (rv != SECSuccess) { 2516 goto loser; 2517 } 2518 2519 rv = SEC_QuickDERDecodeItem(arena, basicResponse, 2520 ocsp_BasicOCSPResponseTemplate, &newsrc); 2521 if (rv != SECSuccess) { 2522 if (PORT_GetError() == SEC_ERROR_BAD_DER) 2523 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); 2524 goto loser; 2525 } 2526 2527 responseData = basicResponse->tbsResponseData; 2528 2529 /* 2530 * The following asserts point out internal errors (problems in 2531 * the template definitions or in the ASN.1 decoder itself, etc.). 2532 */ 2533 PORT_Assert(responseData != NULL); 2534 PORT_Assert(responseData->derResponderID.data != NULL); 2535 2536 /* 2537 * XXX Because responderID is a CHOICE, which is not currently handled 2538 * by our ASN.1 decoder, we have to decode it "by hand". 2539 */ 2540 derTag = responseData->derResponderID.data[0] & SEC_ASN1_TAGNUM_MASK; 2541 responderIDType = ocsp_ResponderIDTypeByTag(derTag); 2542 responderIDTemplate = ocsp_ResponderIDTemplateByType(responderIDType); 2543 2544 responderID = PORT_ArenaZAlloc(arena, sizeof(ocspResponderID)); 2545 if (responderID == NULL) { 2546 goto loser; 2547 } 2548 2549 rv = SEC_QuickDERDecodeItem(arena, responderID, responderIDTemplate, 2550 &responseData->derResponderID); 2551 if (rv != SECSuccess) { 2552 if (PORT_GetError() == SEC_ERROR_BAD_DER) 2553 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); 2554 goto loser; 2555 } 2556 2557 responderID->responderIDType = responderIDType; 2558 responseData->responderID = responderID; 2559 2560 /* 2561 * XXX Each SingleResponse also contains a CHOICE, which has to be 2562 * fixed up by hand. 2563 */ 2564 rv = ocsp_FinishDecodingSingleResponses(arena, responseData->responses); 2565 if (rv != SECSuccess) { 2566 goto loser; 2567 } 2568 2569 PORT_ArenaUnmark(arena, mark); 2570 return basicResponse; 2571 2572 loser: 2573 PORT_ArenaRelease(arena, mark); 2574 return NULL; 2575 } 2576 2577 /* 2578 * Decode the responseBytes based on the responseType found in "rbytes", 2579 * leaving the resulting translated/decoded information in there as well. 2580 */ 2581 static SECStatus 2582 ocsp_DecodeResponseBytes(PLArenaPool *arena, ocspResponseBytes *rbytes) 2583 { 2584 if (rbytes == NULL) { 2585 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE); 2586 return SECFailure; 2587 } 2588 2589 rbytes->responseTypeTag = SECOID_FindOIDTag(&rbytes->responseType); 2590 switch (rbytes->responseTypeTag) { 2591 case SEC_OID_PKIX_OCSP_BASIC_RESPONSE: { 2592 ocspBasicOCSPResponse *basicResponse; 2593 2594 basicResponse = ocsp_DecodeBasicOCSPResponse(arena, 2595 &rbytes->response); 2596 if (basicResponse == NULL) 2597 return SECFailure; 2598 2599 rbytes->decodedResponse.basic = basicResponse; 2600 } break; 2601 2602 /* 2603 * Add new/future response types here. 2604 */ 2605 2606 default: 2607 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE); 2608 return SECFailure; 2609 } 2610 2611 return SECSuccess; 2612 } 2613 2614 /* 2615 * FUNCTION: CERT_DecodeOCSPResponse 2616 * Decode a DER encoded OCSP Response. 2617 * INPUTS: 2618 * SECItem *src 2619 * Pointer to a SECItem holding DER encoded OCSP Response. 2620 * RETURN: 2621 * Returns a pointer to a CERTOCSPResponse (the decoded OCSP Response); 2622 * the caller is responsible for destroying it. Or NULL if error (either 2623 * response could not be decoded (SEC_ERROR_OCSP_MALFORMED_RESPONSE), 2624 * it was of an unexpected type (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE), 2625 * or a low-level or internal error occurred). 2626 */ 2627 CERTOCSPResponse * 2628 CERT_DecodeOCSPResponse(const SECItem *src) 2629 { 2630 PLArenaPool *arena = NULL; 2631 CERTOCSPResponse *response = NULL; 2632 SECStatus rv = SECFailure; 2633 ocspResponseStatus sv; 2634 SECItem newSrc; 2635 2636 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 2637 if (arena == NULL) { 2638 goto loser; 2639 } 2640 response = (CERTOCSPResponse *)PORT_ArenaZAlloc(arena, 2641 sizeof(CERTOCSPResponse)); 2642 if (response == NULL) { 2643 goto loser; 2644 } 2645 response->arena = arena; 2646 2647 /* copy the DER into the arena, since Quick DER returns data that points 2648 into the DER input, which may get freed by the caller */ 2649 rv = SECITEM_CopyItem(arena, &newSrc, src); 2650 if (rv != SECSuccess) { 2651 goto loser; 2652 } 2653 2654 rv = SEC_QuickDERDecodeItem(arena, response, ocsp_OCSPResponseTemplate, &newSrc); 2655 if (rv != SECSuccess) { 2656 if (PORT_GetError() == SEC_ERROR_BAD_DER) 2657 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); 2658 goto loser; 2659 } 2660 2661 sv = (ocspResponseStatus)DER_GetInteger(&response->responseStatus); 2662 response->statusValue = sv; 2663 if (sv != ocspResponse_successful) { 2664 /* 2665 * If the response status is anything but successful, then we 2666 * are all done with decoding; the status is all there is. 2667 */ 2668 return response; 2669 } 2670 2671 /* 2672 * A successful response contains much more information, still encoded. 2673 * Now we need to decode that. 2674 */ 2675 rv = ocsp_DecodeResponseBytes(arena, response->responseBytes); 2676 if (rv != SECSuccess) { 2677 goto loser; 2678 } 2679 2680 return response; 2681 2682 loser: 2683 if (arena != NULL) { 2684 PORT_FreeArena(arena, PR_FALSE); 2685 } 2686 return NULL; 2687 } 2688 2689 /* 2690 * The way an OCSPResponse is defined, there are many levels to descend 2691 * before getting to the actual response information. And along the way 2692 * we need to check that the response *type* is recognizable, which for 2693 * now means that it is a BasicOCSPResponse, because that is the only 2694 * type currently defined. Rather than force all routines to perform 2695 * a bunch of sanity checking every time they want to work on a response, 2696 * this function isolates that and gives back the interesting part. 2697 * Note that no copying is done, this just returns a pointer into the 2698 * substructure of the response which is passed in. 2699 * 2700 * XXX This routine only works when a valid response structure is passed 2701 * into it; this is checked with many assertions. Assuming the response 2702 * was creating by decoding, it wouldn't make it this far without being 2703 * okay. That is a sufficient assumption since the entire OCSP interface 2704 * is only used internally. When this interface is officially exported, 2705 * each assertion below will need to be followed-up with setting an error 2706 * and returning (null). 2707 * 2708 * FUNCTION: ocsp_GetResponseData 2709 * Returns ocspResponseData structure and a pointer to tbs response 2710 * data DER from a valid ocsp response. 2711 * INPUTS: 2712 * CERTOCSPResponse *response 2713 * structure of a valid ocsp response 2714 * RETURN: 2715 * Returns a pointer to ocspResponseData structure: decoded OCSP response 2716 * data, and a pointer(tbsResponseDataDER) to its undecoded data DER. 2717 */ 2718 ocspResponseData * 2719 ocsp_GetResponseData(CERTOCSPResponse *response, SECItem **tbsResponseDataDER) 2720 { 2721 ocspBasicOCSPResponse *basic; 2722 ocspResponseData *responseData; 2723 2724 PORT_Assert(response != NULL); 2725 2726 PORT_Assert(response->responseBytes != NULL); 2727 2728 PORT_Assert(response->responseBytes->responseTypeTag == 2729 SEC_OID_PKIX_OCSP_BASIC_RESPONSE); 2730 2731 basic = response->responseBytes->decodedResponse.basic; 2732 PORT_Assert(basic != NULL); 2733 2734 responseData = basic->tbsResponseData; 2735 PORT_Assert(responseData != NULL); 2736 2737 if (tbsResponseDataDER) { 2738 *tbsResponseDataDER = &basic->tbsResponseDataDER; 2739 2740 PORT_Assert((*tbsResponseDataDER)->data != NULL); 2741 PORT_Assert((*tbsResponseDataDER)->len != 0); 2742 } 2743 2744 return responseData; 2745 } 2746 2747 /* 2748 * Much like the routine above, except it returns the response signature. 2749 * Again, no copy is done. 2750 */ 2751 ocspSignature * 2752 ocsp_GetResponseSignature(CERTOCSPResponse *response) 2753 { 2754 ocspBasicOCSPResponse *basic; 2755 2756 PORT_Assert(response != NULL); 2757 if (NULL == response->responseBytes) { 2758 return NULL; 2759 } 2760 if (response->responseBytes->responseTypeTag != 2761 SEC_OID_PKIX_OCSP_BASIC_RESPONSE) { 2762 return NULL; 2763 } 2764 basic = response->responseBytes->decodedResponse.basic; 2765 PORT_Assert(basic != NULL); 2766 2767 return &(basic->responseSignature); 2768 } 2769 2770 /* 2771 * FUNCTION: CERT_DestroyOCSPResponse 2772 * Frees an OCSP Response structure. 2773 * INPUTS: 2774 * CERTOCSPResponse *request 2775 * Pointer to CERTOCSPResponse to be freed. 2776 * RETURN: 2777 * No return value; no errors. 2778 */ 2779 void 2780 CERT_DestroyOCSPResponse(CERTOCSPResponse *response) 2781 { 2782 if (response != NULL) { 2783 ocspSignature *signature = ocsp_GetResponseSignature(response); 2784 if (signature && signature->cert != NULL) 2785 CERT_DestroyCertificate(signature->cert); 2786 2787 /* 2788 * We should actually never have a response without an arena, 2789 * but check just in case. (If there isn't one, there is not 2790 * much we can do about it...) 2791 */ 2792 PORT_Assert(response->arena != NULL); 2793 if (response->arena != NULL) { 2794 PORT_FreeArena(response->arena, PR_FALSE); 2795 } 2796 } 2797 } 2798 2799 /* 2800 * OVERALL OCSP CLIENT SUPPORT (make and send a request, verify a response): 2801 */ 2802 2803 /* 2804 * Pick apart a URL, saving the important things in the passed-in pointers. 2805 * 2806 * We expect to find "http://<hostname>[:<port>]/[path]", though we will 2807 * tolerate that final slash character missing, as well as beginning and 2808 * trailing whitespace, and any-case-characters for "http". All of that 2809 * tolerance is what complicates this routine. What we want is just to 2810 * pick out the hostname, the port, and the path. 2811 * 2812 * On a successful return, the caller will need to free the output pieces 2813 * of hostname and path, which are copies of the values found in the url. 2814 */ 2815 static SECStatus 2816 ocsp_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath) 2817 { 2818 unsigned short port = 80; /* default, in case not in url */ 2819 char *hostname = NULL; 2820 char *path = NULL; 2821 const char *save; 2822 char c; 2823 int len; 2824 2825 if (url == NULL) 2826 goto loser; 2827 2828 /* 2829 * Skip beginning whitespace. 2830 */ 2831 c = *url; 2832 while ((c == ' ' || c == '\t') && c != '\0') { 2833 url++; 2834 c = *url; 2835 } 2836 if (c == '\0') 2837 goto loser; 2838 2839 /* 2840 * Confirm, then skip, protocol. (Since we only know how to do http, 2841 * that is all we will accept). 2842 */ 2843 if (PORT_Strncasecmp(url, "http://", 7) != 0) 2844 goto loser; 2845 url += 7; 2846 2847 /* 2848 * Whatever comes next is the hostname (or host IP address). We just 2849 * save it aside and then search for its end so we can determine its 2850 * length and copy it. 2851 * 2852 * XXX Note that because we treat a ':' as a terminator character 2853 * (and below, we expect that to mean there is a port specification 2854 * immediately following), we will not handle IPv6 addresses. That is 2855 * apparently an acceptable limitation, for the time being. Some day, 2856 * when there is a clear way to specify a URL with an IPv6 address that 2857 * can be parsed unambiguously, this code should be made to do that. 2858 */ 2859 save = url; 2860 c = *url; 2861 while (c != '/' && c != ':' && c != '\0' && c != ' ' && c != '\t') { 2862 url++; 2863 c = *url; 2864 } 2865 len = url - save; 2866 hostname = PORT_Alloc(len + 1); 2867 if (hostname == NULL) 2868 goto loser; 2869 PORT_Memcpy(hostname, save, len); 2870 hostname[len] = '\0'; 2871 2872 /* 2873 * Now we figure out if there was a port specified or not. 2874 * If so, we need to parse it (as a number) and skip it. 2875 */ 2876 if (c == ':') { 2877 url++; 2878 port = (unsigned short)PORT_Atoi(url); 2879 c = *url; 2880 while (c != '/' && c != '\0' && c != ' ' && c != '\t') { 2881 if (c < '0' || c > '9') 2882 goto loser; 2883 url++; 2884 c = *url; 2885 } 2886 } 2887 2888 /* 2889 * Last thing to find is a path. There *should* be a slash, 2890 * if nothing else -- but if there is not we provide one. 2891 */ 2892 if (c == '/') { 2893 save = url; 2894 while (c != '\0' && c != ' ' && c != '\t') { 2895 url++; 2896 c = *url; 2897 } 2898 len = url - save; 2899 path = PORT_Alloc(len + 1); 2900 if (path == NULL) 2901 goto loser; 2902 PORT_Memcpy(path, save, len); 2903 path[len] = '\0'; 2904 } else { 2905 path = PORT_Strdup("/"); 2906 if (path == NULL) 2907 goto loser; 2908 } 2909 2910 *pHostname = hostname; 2911 *pPort = port; 2912 *pPath = path; 2913 return SECSuccess; 2914 2915 loser: 2916 if (hostname != NULL) 2917 PORT_Free(hostname); 2918 PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); 2919 return SECFailure; 2920 } 2921 2922 /* 2923 * Open a socket to the specified host on the specified port, and return it. 2924 * The host is either a hostname or an IP address. 2925 */ 2926 static PRFileDesc * 2927 ocsp_ConnectToHost(const char *host, PRUint16 port) 2928 { 2929 #ifdef MOZ_PROXY_BYPASS_PROTECTION 2930 return NULL; 2931 #else 2932 PRFileDesc *sock = NULL; 2933 PRIntervalTime timeout; 2934 PRNetAddr addr; 2935 char *netdbbuf = NULL; 2936 2937 sock = PR_NewTCPSocket(); 2938 if (sock == NULL) 2939 goto loser; 2940 2941 /* XXX Some day need a way to set (and get?) the following value */ 2942 timeout = PR_SecondsToInterval(30); 2943 2944 /* 2945 * If the following converts an IP address string in "dot notation" 2946 * into a PRNetAddr. If it fails, we assume that is because we do not 2947 * have such an address, but instead a host *name*. In that case we 2948 * then lookup the host by name. Using the NSPR function this way 2949 * means we do not have to have our own logic for distinguishing a 2950 * valid numerical IP address from a hostname. 2951 */ 2952 if (PR_StringToNetAddr(host, &addr) != PR_SUCCESS) { 2953 PRIntn hostIndex; 2954 PRHostEnt hostEntry; 2955 2956 netdbbuf = PORT_Alloc(PR_NETDB_BUF_SIZE); 2957 if (netdbbuf == NULL) 2958 goto loser; 2959 2960 if (PR_GetHostByName(host, netdbbuf, PR_NETDB_BUF_SIZE, 2961 &hostEntry) != PR_SUCCESS) 2962 goto loser; 2963 2964 hostIndex = 0; 2965 do { 2966 hostIndex = PR_EnumerateHostEnt(hostIndex, &hostEntry, port, &addr); 2967 if (hostIndex <= 0) 2968 goto loser; 2969 } while (PR_Connect(sock, &addr, timeout) != PR_SUCCESS); 2970 2971 PORT_Free(netdbbuf); 2972 } else { 2973 /* 2974 * First put the port into the address, then connect. 2975 */ 2976 if (PR_InitializeNetAddr(PR_IpAddrNull, port, &addr) != PR_SUCCESS) 2977 goto loser; 2978 if (PR_Connect(sock, &addr, timeout) != PR_SUCCESS) 2979 goto loser; 2980 } 2981 2982 return sock; 2983 2984 loser: 2985 if (sock != NULL) 2986 PR_Close(sock); 2987 if (netdbbuf != NULL) 2988 PORT_Free(netdbbuf); 2989 return NULL; 2990 #endif 2991 } 2992 2993 /* 2994 * Sends an encoded OCSP request to the server identified by "location", 2995 * and returns the socket on which it was sent (so can listen for the reply). 2996 * "location" is expected to be a valid URL -- an error parsing it produces 2997 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION. Other errors are likely problems 2998 * connecting to it, or writing to it, or allocating memory, and the low-level 2999 * errors appropriate to the problem will be set. 3000 * if (encodedRequest == NULL) 3001 * then location MUST already include the full request, 3002 * including base64 and urlencode, 3003 * and the request will be sent with GET 3004 * if (encodedRequest != NULL) 3005 * then the request will be sent with POST 3006 */ 3007 static PRFileDesc * 3008 ocsp_SendEncodedRequest(const char *location, const SECItem *encodedRequest) 3009 { 3010 char *hostname = NULL; 3011 char *path = NULL; 3012 PRUint16 port; 3013 SECStatus rv; 3014 PRFileDesc *sock = NULL; 3015 PRFileDesc *returnSock = NULL; 3016 char *header = NULL; 3017 char portstr[16]; 3018 3019 /* 3020 * Take apart the location, getting the hostname, port, and path. 3021 */ 3022 rv = ocsp_ParseURL(location, &hostname, &port, &path); 3023 if (rv != SECSuccess) 3024 goto loser; 3025 3026 PORT_Assert(hostname != NULL); 3027 PORT_Assert(path != NULL); 3028 3029 sock = ocsp_ConnectToHost(hostname, port); 3030 if (sock == NULL) 3031 goto loser; 3032 3033 portstr[0] = '\0'; 3034 if (port != 80) { 3035 PR_snprintf(portstr, sizeof(portstr), ":%d", port); 3036 } 3037 3038 if (!encodedRequest) { 3039 header = PR_smprintf("GET %s HTTP/1.0\r\n" 3040 "Host: %s%s\r\n\r\n", 3041 path, hostname, portstr); 3042 if (header == NULL) 3043 goto loser; 3044 3045 /* 3046 * The NSPR documentation promises that if it can, it will write the full 3047 * amount; this will not return a partial value expecting us to loop. 3048 */ 3049 if (PR_Write(sock, header, (PRInt32)PORT_Strlen(header)) < 0) 3050 goto loser; 3051 } else { 3052 header = PR_smprintf("POST %s HTTP/1.0\r\n" 3053 "Host: %s%s\r\n" 3054 "Content-Type: application/ocsp-request\r\n" 3055 "Content-Length: %u\r\n\r\n", 3056 path, hostname, portstr, encodedRequest->len); 3057 if (header == NULL) 3058 goto loser; 3059 3060 /* 3061 * The NSPR documentation promises that if it can, it will write the full 3062 * amount; this will not return a partial value expecting us to loop. 3063 */ 3064 if (PR_Write(sock, header, (PRInt32)PORT_Strlen(header)) < 0) 3065 goto loser; 3066 3067 if (PR_Write(sock, encodedRequest->data, 3068 (PRInt32)encodedRequest->len) < 0) 3069 goto loser; 3070 } 3071 3072 returnSock = sock; 3073 sock = NULL; 3074 3075 loser: 3076 if (header != NULL) 3077 PORT_Free(header); 3078 if (sock != NULL) 3079 PR_Close(sock); 3080 if (path != NULL) 3081 PORT_Free(path); 3082 if (hostname != NULL) 3083 PORT_Free(hostname); 3084 3085 return returnSock; 3086 } 3087 3088 /* 3089 * Read from "fd" into "buf" -- expect/attempt to read a given number of bytes 3090 * Obviously, stop if hit end-of-stream. Timeout is passed in. 3091 */ 3092 3093 static int 3094 ocsp_read(PRFileDesc *fd, char *buf, int toread, PRIntervalTime timeout) 3095 { 3096 int total = 0; 3097 3098 while (total < toread) { 3099 PRInt32 got; 3100 3101 got = PR_Recv(fd, buf + total, (PRInt32)(toread - total), 0, timeout); 3102 if (got < 0) { 3103 if (0 == total) { 3104 total = -1; /* report the error if we didn't read anything yet */ 3105 } 3106 break; 3107 } else if (got == 0) { /* EOS */ 3108 break; 3109 } 3110 3111 total += got; 3112 } 3113 3114 return total; 3115 } 3116 3117 #define OCSP_BUFSIZE 1024 3118 3119 #define AbortHttpDecode(error) \ 3120 { \ 3121 if (inBuffer) \ 3122 PORT_Free(inBuffer); \ 3123 PORT_SetError(error); \ 3124 return NULL; \ 3125 } 3126 3127 /* 3128 * Reads on the given socket and returns an encoded response when received. 3129 * Properly formatted HTTP/1.0 response headers are expected to be read 3130 * from the socket, preceding a binary-encoded OCSP response. Problems 3131 * with parsing cause the error SEC_ERROR_OCSP_BAD_HTTP_RESPONSE to be 3132 * set; any other problems are likely low-level i/o or memory allocation 3133 * errors. 3134 */ 3135 static SECItem * 3136 ocsp_GetEncodedResponse(PLArenaPool *arena, PRFileDesc *sock) 3137 { 3138 /* first read HTTP status line and headers */ 3139 3140 char *inBuffer = NULL; 3141 PRInt32 offset = 0; 3142 PRInt32 inBufsize = 0; 3143 const PRInt32 bufSizeIncrement = OCSP_BUFSIZE; /* 1 KB at a time */ 3144 const PRInt32 maxBufSize = 8 * bufSizeIncrement; /* 8 KB max */ 3145 const char *CRLF = "\r\n"; 3146 const PRInt32 CRLFlen = strlen(CRLF); 3147 const char *headerEndMark = "\r\n\r\n"; 3148 const PRInt32 markLen = strlen(headerEndMark); 3149 const PRIntervalTime ocsptimeout = 3150 PR_SecondsToInterval(30); /* hardcoded to 30s for now */ 3151 char *headerEnd = NULL; 3152 PRBool EOS = PR_FALSE; 3153 const char *httpprotocol = "HTTP/"; 3154 const PRInt32 httplen = strlen(httpprotocol); 3155 const char *httpcode = NULL; 3156 const char *contenttype = NULL; 3157 PRInt32 contentlength = 0; 3158 PRInt32 bytesRead = 0; 3159 char *statusLineEnd = NULL; 3160 char *space = NULL; 3161 char *nextHeader = NULL; 3162 SECItem *result = NULL; 3163 3164 /* read up to at least the end of the HTTP headers */ 3165 do { 3166 inBufsize += bufSizeIncrement; 3167 inBuffer = PORT_Realloc(inBuffer, inBufsize + 1); 3168 if (NULL == inBuffer) { 3169 AbortHttpDecode(SEC_ERROR_NO_MEMORY); 3170 } 3171 bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement, 3172 ocsptimeout); 3173 if (bytesRead > 0) { 3174 PRInt32 searchOffset = (offset - markLen) > 0 ? offset - markLen : 0; 3175 offset += bytesRead; 3176 *(inBuffer + offset) = '\0'; /* NULL termination */ 3177 headerEnd = strstr((const char *)inBuffer + searchOffset, headerEndMark); 3178 if (bytesRead < bufSizeIncrement) { 3179 /* we read less data than requested, therefore we are at 3180 EOS or there was a read error */ 3181 EOS = PR_TRUE; 3182 } 3183 } else { 3184 /* recv error or EOS */ 3185 EOS = PR_TRUE; 3186 } 3187 } while ((!headerEnd) && (PR_FALSE == EOS) && 3188 (inBufsize < maxBufSize)); 3189 3190 if (!headerEnd) { 3191 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); 3192 } 3193 3194 /* parse the HTTP status line */ 3195 statusLineEnd = strstr((const char *)inBuffer, CRLF); 3196 if (!statusLineEnd) { 3197 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); 3198 } 3199 *statusLineEnd = '\0'; 3200 3201 /* check for HTTP/ response */ 3202 space = strchr((const char *)inBuffer, ' '); 3203 if (!space || PORT_Strncasecmp((const char *)inBuffer, httpprotocol, httplen) != 0) { 3204 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); 3205 } 3206 3207 /* check the HTTP status code of 200 */ 3208 httpcode = space + 1; 3209 space = strchr(httpcode, ' '); 3210 if (!space) { 3211 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); 3212 } 3213 *space = 0; 3214 if (0 != strcmp(httpcode, "200")) { 3215 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); 3216 } 3217 3218 /* parse the HTTP headers in the buffer . We only care about 3219 content-type and content-length 3220 */ 3221 3222 nextHeader = statusLineEnd + CRLFlen; 3223 *headerEnd = '\0'; /* terminate */ 3224 do { 3225 char *thisHeaderEnd = NULL; 3226 char *value = NULL; 3227 char *colon = strchr(nextHeader, ':'); 3228 3229 if (!colon) { 3230 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); 3231 } 3232 3233 *colon = '\0'; 3234 value = colon + 1; 3235 3236 /* jpierre - note : the following code will only handle the basic form 3237 of HTTP/1.0 response headers, of the form "name: value" . Headers 3238 split among multiple lines are not supported. This is not common 3239 and should not be an issue, but it could become one in the 3240 future */ 3241 3242 if (*value != ' ') { 3243 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); 3244 } 3245 3246 value++; 3247 thisHeaderEnd = strstr(value, CRLF); 3248 if (thisHeaderEnd) { 3249 *thisHeaderEnd = '\0'; 3250 } 3251 3252 if (0 == PORT_Strcasecmp(nextHeader, "content-type")) { 3253 contenttype = value; 3254 } else if (0 == PORT_Strcasecmp(nextHeader, "content-length")) { 3255 contentlength = atoi(value); 3256 } 3257 3258 if (thisHeaderEnd) { 3259 nextHeader = thisHeaderEnd + CRLFlen; 3260 } else { 3261 nextHeader = NULL; 3262 } 3263 3264 } while (nextHeader && (nextHeader < (headerEnd + CRLFlen))); 3265 3266 /* check content-type */ 3267 if (!contenttype || 3268 (0 != PORT_Strcasecmp(contenttype, "application/ocsp-response"))) { 3269 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); 3270 } 3271 3272 /* read the body of the OCSP response */ 3273 offset = offset - (PRInt32)(headerEnd - (const char *)inBuffer) - markLen; 3274 if (offset) { 3275 /* move all data to the beginning of the buffer */ 3276 PORT_Memmove(inBuffer, headerEnd + markLen, offset); 3277 } 3278 3279 /* resize buffer to only what's needed to hold the current response */ 3280 inBufsize = (1 + (offset - 1) / bufSizeIncrement) * bufSizeIncrement; 3281 3282 while ((PR_FALSE == EOS) && 3283 ((contentlength == 0) || (offset < contentlength)) && 3284 (inBufsize < maxBufSize)) { 3285 /* we still need to receive more body data */ 3286 inBufsize += bufSizeIncrement; 3287 inBuffer = PORT_Realloc(inBuffer, inBufsize + 1); 3288 if (NULL == inBuffer) { 3289 AbortHttpDecode(SEC_ERROR_NO_MEMORY); 3290 } 3291 bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement, 3292 ocsptimeout); 3293 if (bytesRead > 0) { 3294 offset += bytesRead; 3295 if (bytesRead < bufSizeIncrement) { 3296 /* we read less data than requested, therefore we are at 3297 EOS or there was a read error */ 3298 EOS = PR_TRUE; 3299 } 3300 } else { 3301 /* recv error or EOS */ 3302 EOS = PR_TRUE; 3303 } 3304 } 3305 3306 if (0 == offset) { 3307 AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); 3308 } 3309 3310 /* 3311 * Now allocate the item to hold the data. 3312 */ 3313 result = SECITEM_AllocItem(arena, NULL, offset); 3314 if (NULL == result) { 3315 AbortHttpDecode(SEC_ERROR_NO_MEMORY); 3316 } 3317 3318 /* 3319 * And copy the data left in the buffer. 3320 */ 3321 PORT_Memcpy(result->data, inBuffer, offset); 3322 3323 /* and free the temporary buffer */ 3324 PORT_Free(inBuffer); 3325 return result; 3326 } 3327 3328 SECStatus 3329 CERT_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath) 3330 { 3331 return ocsp_ParseURL(url, pHostname, pPort, pPath); 3332 } 3333 3334 /* 3335 * Limit the size of http responses we are willing to accept. 3336 */ 3337 #define MAX_WANTED_OCSP_RESPONSE_LEN 64 * 1024 3338 3339 /* if (encodedRequest == NULL) 3340 * then location MUST already include the full request, 3341 * including base64 and urlencode, 3342 * and the request will be sent with GET 3343 * if (encodedRequest != NULL) 3344 * then the request will be sent with POST 3345 */ 3346 static SECItem * 3347 fetchOcspHttpClientV1(PLArenaPool *arena, 3348 const SEC_HttpClientFcnV1 *hcv1, 3349 const char *location, 3350 const SECItem *encodedRequest) 3351 { 3352 char *hostname = NULL; 3353 char *path = NULL; 3354 PRUint16 port; 3355 SECItem *encodedResponse = NULL; 3356 SEC_HTTP_SERVER_SESSION pServerSession = NULL; 3357 SEC_HTTP_REQUEST_SESSION pRequestSession = NULL; 3358 PRUint16 myHttpResponseCode; 3359 const char *myHttpResponseData; 3360 PRUint32 myHttpResponseDataLen; 3361 3362 if (ocsp_ParseURL(location, &hostname, &port, &path) == SECFailure) { 3363 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST); 3364 goto loser; 3365 } 3366 3367 PORT_Assert(hostname != NULL); 3368 PORT_Assert(path != NULL); 3369 3370 if ((*hcv1->createSessionFcn)( 3371 hostname, 3372 port, 3373 &pServerSession) != SECSuccess) { 3374 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); 3375 goto loser; 3376 } 3377 3378 /* We use a non-zero timeout, which means: 3379 - the client will use blocking I/O 3380 - TryFcn will not return WOULD_BLOCK nor a poll descriptor 3381 - it's sufficient to call TryFcn once 3382 No lock for accessing OCSP_Global.timeoutSeconds, bug 406120 3383 */ 3384 3385 if ((*hcv1->createFcn)( 3386 pServerSession, 3387 "http", 3388 path, 3389 encodedRequest ? "POST" : "GET", 3390 PR_TicksPerSecond() * OCSP_Global.timeoutSeconds, 3391 &pRequestSession) != SECSuccess) { 3392 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); 3393 goto loser; 3394 } 3395 3396 if (encodedRequest && 3397 (*hcv1->setPostDataFcn)( 3398 pRequestSession, 3399 (char *)encodedRequest->data, 3400 encodedRequest->len, 3401 "application/ocsp-request") != SECSuccess) { 3402 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); 3403 goto loser; 3404 } 3405 3406 /* we don't want result objects larger than this: */ 3407 myHttpResponseDataLen = MAX_WANTED_OCSP_RESPONSE_LEN; 3408 3409 OCSP_TRACE(("OCSP trySendAndReceive %s\n", location)); 3410 3411 if ((*hcv1->trySendAndReceiveFcn)( 3412 pRequestSession, 3413 NULL, 3414 &myHttpResponseCode, 3415 NULL, 3416 NULL, 3417 &myHttpResponseData, 3418 &myHttpResponseDataLen) != SECSuccess) { 3419 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); 3420 goto loser; 3421 } 3422 3423 OCSP_TRACE(("OCSP trySendAndReceive result http %d\n", myHttpResponseCode)); 3424 3425 if (myHttpResponseCode != 200) { 3426 PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); 3427 goto loser; 3428 } 3429 3430 encodedResponse = SECITEM_AllocItem(arena, NULL, myHttpResponseDataLen); 3431 3432 if (!encodedResponse) { 3433 PORT_SetError(SEC_ERROR_NO_MEMORY); 3434 goto loser; 3435 } 3436 3437 PORT_Memcpy(encodedResponse->data, myHttpResponseData, myHttpResponseDataLen); 3438 3439 loser: 3440 if (pRequestSession != NULL) 3441 (*hcv1->freeFcn)(pRequestSession); 3442 if (pServerSession != NULL) 3443 (*hcv1->freeSessionFcn)(pServerSession); 3444 if (path != NULL) 3445 PORT_Free(path); 3446 if (hostname != NULL) 3447 PORT_Free(hostname); 3448 3449 return encodedResponse; 3450 } 3451 3452 /* 3453 * FUNCTION: CERT_GetEncodedOCSPResponseByMethod 3454 * Creates and sends a request to an OCSP responder, then reads and 3455 * returns the (encoded) response. 3456 * INPUTS: 3457 * PLArenaPool *arena 3458 * Pointer to arena from which return value will be allocated. 3459 * If NULL, result will be allocated from the heap (and thus should 3460 * be freed via SECITEM_FreeItem). 3461 * CERTCertList *certList 3462 * A list of certs for which status will be requested. 3463 * Note that all of these certificates should have the same issuer, 3464 * or it's expected the response will be signed by a trusted responder. 3465 * If the certs need to be broken up into multiple requests, that 3466 * must be handled by the caller (and thus by having multiple calls 3467 * to this routine), who knows about where the request(s) are being 3468 * sent and whether there are any trusted responders in place. 3469 * const char *location 3470 * The location of the OCSP responder (a URL). 3471 * const char *method 3472 * The protocol method used when retrieving the OCSP response. 3473 * Currently support: "GET" (http GET) and "POST" (http POST). 3474 * Additionals methods for http or other protocols might be added 3475 * in the future. 3476 * PRTime time 3477 * Indicates the time for which the certificate status is to be 3478 * determined -- this may be used in the search for the cert's issuer 3479 * but has no other bearing on the operation. 3480 * PRBool addServiceLocator 3481 * If true, the Service Locator extension should be added to the 3482 * single request(s) for each cert. 3483 * CERTCertificate *signerCert 3484 * If non-NULL, means sign the request using this cert. Otherwise, 3485 * do not sign. 3486 * void *pwArg 3487 * Pointer to argument for password prompting, if needed. (Definitely 3488 * not needed if not signing.) 3489 * OUTPUTS: 3490 * CERTOCSPRequest **pRequest 3491 * Pointer in which to store the OCSP request created for the given 3492 * list of certificates. It is only filled in if the entire operation 3493 * is successful and the pointer is not null -- and in that case the 3494 * caller is then reponsible for destroying it. 3495 * RETURN: 3496 * Returns a pointer to the SECItem holding the response. 3497 * On error, returns null with error set describing the reason: 3498 * SEC_ERROR_UNKNOWN_ISSUER 3499 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION 3500 * SEC_ERROR_OCSP_BAD_HTTP_RESPONSE 3501 * Other errors are low-level problems (no memory, bad database, etc.). 3502 */ 3503 SECItem * 3504 CERT_GetEncodedOCSPResponseByMethod(PLArenaPool *arena, CERTCertList *certList, 3505 const char *location, const char *method, 3506 PRTime time, PRBool addServiceLocator, 3507 CERTCertificate *signerCert, void *pwArg, 3508 CERTOCSPRequest **pRequest) 3509 { 3510 CERTOCSPRequest *request; 3511 request = CERT_CreateOCSPRequest(certList, time, addServiceLocator, 3512 signerCert); 3513 if (!request) 3514 return NULL; 3515 return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, 3516 method, time, addServiceLocator, 3517 pwArg, pRequest); 3518 } 3519 3520 /* 3521 * FUNCTION: CERT_GetEncodedOCSPResponse 3522 * Creates and sends a request to an OCSP responder, then reads and 3523 * returns the (encoded) response. 3524 * 3525 * This is a legacy API that behaves identically to 3526 * CERT_GetEncodedOCSPResponseByMethod using the "POST" method. 3527 */ 3528 SECItem * 3529 CERT_GetEncodedOCSPResponse(PLArenaPool *arena, CERTCertList *certList, 3530 const char *location, PRTime time, 3531 PRBool addServiceLocator, 3532 CERTCertificate *signerCert, void *pwArg, 3533 CERTOCSPRequest **pRequest) 3534 { 3535 return CERT_GetEncodedOCSPResponseByMethod(arena, certList, location, 3536 "POST", time, addServiceLocator, 3537 signerCert, pwArg, pRequest); 3538 } 3539 3540 /* URL encode a buffer that consists of base64-characters, only, 3541 * which means we can use a simple encoding logic. 3542 * 3543 * No output buffer size checking is performed. 3544 * You should call the function twice, to calculate the required buffer size. 3545 * 3546 * If the outpufBuf parameter is NULL, the function will calculate the 3547 * required size, including the trailing zero termination char. 3548 * 3549 * The function returns the number of bytes calculated or produced. 3550 */ 3551 size_t 3552 ocsp_UrlEncodeBase64Buf(const char *base64Buf, char *outputBuf) 3553 { 3554 const char *walkInput = NULL; 3555 char *walkOutput = outputBuf; 3556 size_t count = 0; 3557 3558 for (walkInput = base64Buf; *walkInput; ++walkInput) { 3559 char c = *walkInput; 3560 if (isspace((unsigned char)c)) 3561 continue; 3562 switch (c) { 3563 case '+': 3564 if (outputBuf) { 3565 strcpy(walkOutput, "%2B"); 3566 walkOutput += 3; 3567 } 3568 count += 3; 3569 break; 3570 case '/': 3571 if (outputBuf) { 3572 strcpy(walkOutput, "%2F"); 3573 walkOutput += 3; 3574 } 3575 count += 3; 3576 break; 3577 case '=': 3578 if (outputBuf) { 3579 strcpy(walkOutput, "%3D"); 3580 walkOutput += 3; 3581 } 3582 count += 3; 3583 break; 3584 default: 3585 if (outputBuf) { 3586 *walkOutput = *walkInput; 3587 ++walkOutput; 3588 } 3589 ++count; 3590 break; 3591 } 3592 } 3593 if (outputBuf) { 3594 *walkOutput = 0; 3595 } 3596 ++count; 3597 return count; 3598 } 3599 3600 enum { max_get_request_size = 255 }; /* defined by RFC2560 */ 3601 3602 static SECItem * 3603 cert_GetOCSPResponse(PLArenaPool *arena, const char *location, 3604 const SECItem *encodedRequest); 3605 3606 static SECItem * 3607 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena, 3608 CERTOCSPRequest *request, 3609 const char *location, 3610 const char *method, 3611 PRTime time, 3612 PRBool addServiceLocator, 3613 void *pwArg, 3614 CERTOCSPRequest **pRequest) 3615 { 3616 SECItem *encodedRequest = NULL; 3617 SECItem *encodedResponse = NULL; 3618 SECStatus rv; 3619 3620 if (!location || !*location) /* location should be at least one byte */ 3621 goto loser; 3622 3623 rv = CERT_AddOCSPAcceptableResponses(request, 3624 SEC_OID_PKIX_OCSP_BASIC_RESPONSE); 3625 if (rv != SECSuccess) 3626 goto loser; 3627 3628 encodedRequest = CERT_EncodeOCSPRequest(NULL, request, pwArg); 3629 if (encodedRequest == NULL) 3630 goto loser; 3631 3632 if (!strcmp(method, "GET")) { 3633 encodedResponse = cert_GetOCSPResponse(arena, location, encodedRequest); 3634 } else if (!strcmp(method, "POST")) { 3635 encodedResponse = CERT_PostOCSPRequest(arena, location, encodedRequest); 3636 } else { 3637 goto loser; 3638 } 3639 3640 if (encodedResponse != NULL && pRequest != NULL) { 3641 *pRequest = request; 3642 request = NULL; /* avoid destroying below */ 3643 } 3644 3645 loser: 3646 if (request != NULL) 3647 CERT_DestroyOCSPRequest(request); 3648 if (encodedRequest != NULL) 3649 SECITEM_FreeItem(encodedRequest, PR_TRUE); 3650 return encodedResponse; 3651 } 3652 3653 static SECItem * 3654 cert_FetchOCSPResponse(PLArenaPool *arena, const char *location, 3655 const SECItem *encodedRequest); 3656 3657 /* using HTTP GET method */ 3658 static SECItem * 3659 cert_GetOCSPResponse(PLArenaPool *arena, const char *location, 3660 const SECItem *encodedRequest) 3661 { 3662 char *walkOutput = NULL; 3663 char *fullGetPath = NULL; 3664 size_t pathLength; 3665 PRInt32 urlEncodedBufLength; 3666 size_t base64size; 3667 char b64ReqBuf[max_get_request_size + 1]; 3668 size_t slashLengthIfNeeded = 0; 3669 size_t getURLLength; 3670 SECItem *item; 3671 3672 if (!location || !*location) { 3673 return NULL; 3674 } 3675 3676 pathLength = strlen(location); 3677 if (location[pathLength - 1] != '/') { 3678 slashLengthIfNeeded = 1; 3679 } 3680 3681 /* Calculation as documented by PL_Base64Encode function. 3682 * Use integer conversion to avoid having to use function ceil(). 3683 */ 3684 base64size = (((encodedRequest->len + 2) / 3) * 4); 3685 if (base64size > max_get_request_size) { 3686 return NULL; 3687 } 3688 memset(b64ReqBuf, 0, sizeof(b64ReqBuf)); 3689 PL_Base64Encode((const char *)encodedRequest->data, encodedRequest->len, 3690 b64ReqBuf); 3691 3692 urlEncodedBufLength = ocsp_UrlEncodeBase64Buf(b64ReqBuf, NULL); 3693 getURLLength = pathLength + urlEncodedBufLength + slashLengthIfNeeded; 3694 3695 /* urlEncodedBufLength already contains room for the zero terminator. 3696 * Add another if we must add the '/' char. 3697 */ 3698 if (arena) { 3699 fullGetPath = (char *)PORT_ArenaAlloc(arena, getURLLength); 3700 } else { 3701 fullGetPath = (char *)PORT_Alloc(getURLLength); 3702 } 3703 if (!fullGetPath) { 3704 return NULL; 3705 } 3706 3707 strcpy(fullGetPath, location); 3708 walkOutput = fullGetPath + pathLength; 3709 3710 if (walkOutput > fullGetPath && slashLengthIfNeeded) { 3711 strcpy(walkOutput, "/"); 3712 ++walkOutput; 3713 } 3714 ocsp_UrlEncodeBase64Buf(b64ReqBuf, walkOutput); 3715 3716 item = cert_FetchOCSPResponse(arena, fullGetPath, NULL); 3717 if (!arena) { 3718 PORT_Free(fullGetPath); 3719 } 3720 return item; 3721 } 3722 3723 SECItem * 3724 CERT_PostOCSPRequest(PLArenaPool *arena, const char *location, 3725 const SECItem *encodedRequest) 3726 { 3727 return cert_FetchOCSPResponse(arena, location, encodedRequest); 3728 } 3729 3730 SECItem * 3731 cert_FetchOCSPResponse(PLArenaPool *arena, const char *location, 3732 const SECItem *encodedRequest) 3733 { 3734 const SEC_HttpClientFcn *registeredHttpClient; 3735 SECItem *encodedResponse = NULL; 3736 3737 registeredHttpClient = SEC_GetRegisteredHttpClient(); 3738 3739 if (registeredHttpClient && registeredHttpClient->version == 1) { 3740 encodedResponse = fetchOcspHttpClientV1( 3741 arena, 3742 ®isteredHttpClient->fcnTable.ftable1, 3743 location, 3744 encodedRequest); 3745 } else { 3746 /* use internal http client */ 3747 PRFileDesc *sock = ocsp_SendEncodedRequest(location, encodedRequest); 3748 if (sock) { 3749 encodedResponse = ocsp_GetEncodedResponse(arena, sock); 3750 PR_Close(sock); 3751 } 3752 } 3753 3754 return encodedResponse; 3755 } 3756 3757 static SECItem * 3758 ocsp_GetEncodedOCSPResponseForSingleCert(PLArenaPool *arena, 3759 CERTOCSPCertID *certID, 3760 CERTCertificate *singleCert, 3761 const char *location, 3762 const char *method, 3763 PRTime time, 3764 PRBool addServiceLocator, 3765 void *pwArg, 3766 CERTOCSPRequest **pRequest) 3767 { 3768 CERTOCSPRequest *request; 3769 request = cert_CreateSingleCertOCSPRequest(certID, singleCert, time, 3770 addServiceLocator, NULL); 3771 if (!request) 3772 return NULL; 3773 return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, 3774 method, time, addServiceLocator, 3775 pwArg, pRequest); 3776 } 3777 3778 /* Checks a certificate for the key usage extension of OCSP signer. */ 3779 static PRBool 3780 ocsp_CertIsOCSPDesignatedResponder(CERTCertificate *cert) 3781 { 3782 SECStatus rv; 3783 SECItem extItem; 3784 SECItem **oids; 3785 SECItem *oid; 3786 SECOidTag oidTag; 3787 PRBool retval; 3788 CERTOidSequence *oidSeq = NULL; 3789 3790 extItem.data = NULL; 3791 rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem); 3792 if (rv != SECSuccess) { 3793 goto loser; 3794 } 3795 3796 oidSeq = CERT_DecodeOidSequence(&extItem); 3797 if (oidSeq == NULL) { 3798 goto loser; 3799 } 3800 3801 oids = oidSeq->oids; 3802 while (*oids != NULL) { 3803 oid = *oids; 3804 3805 oidTag = SECOID_FindOIDTag(oid); 3806 3807 if (oidTag == SEC_OID_OCSP_RESPONDER) { 3808 goto success; 3809 } 3810 3811 oids++; 3812 } 3813 3814 loser: 3815 retval = PR_FALSE; 3816 PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT); 3817 goto done; 3818 success: 3819 retval = PR_TRUE; 3820 done: 3821 if (extItem.data != NULL) { 3822 PORT_Free(extItem.data); 3823 } 3824 if (oidSeq != NULL) { 3825 CERT_DestroyOidSequence(oidSeq); 3826 } 3827 3828 return (retval); 3829 } 3830 3831 #ifdef LATER /* \ 3832 * XXX This function is not currently used, but will \ 3833 * be needed later when we do revocation checking of \ 3834 * the responder certificate. Of course, it may need \ 3835 * revising then, if the cert extension interface has \ 3836 * changed. (Hopefully it will!) \ 3837 */ 3838 3839 /* Checks a certificate to see if it has the OCSP no check extension. */ 3840 static PRBool 3841 ocsp_CertHasNoCheckExtension(CERTCertificate *cert) 3842 { 3843 SECStatus rv; 3844 3845 rv = CERT_FindCertExtension(cert, SEC_OID_PKIX_OCSP_NO_CHECK, 3846 NULL); 3847 if (rv == SECSuccess) { 3848 return PR_TRUE; 3849 } 3850 return PR_FALSE; 3851 } 3852 #endif /* LATER */ 3853 3854 static PRBool 3855 ocsp_matchcert(SECItem *certIndex, CERTCertificate *testCert) 3856 { 3857 SECItem item; 3858 unsigned char buf[HASH_LENGTH_MAX]; 3859 3860 item.data = buf; 3861 item.len = SHA1_LENGTH; 3862 3863 if (CERT_GetSubjectPublicKeyDigest(NULL, testCert, SEC_OID_SHA1, 3864 &item) == NULL) { 3865 return PR_FALSE; 3866 } 3867 if (SECITEM_ItemsAreEqual(certIndex, &item)) { 3868 return PR_TRUE; 3869 } 3870 if (CERT_GetSubjectPublicKeyDigest(NULL, testCert, SEC_OID_MD5, 3871 &item) == NULL) { 3872 return PR_FALSE; 3873 } 3874 if (SECITEM_ItemsAreEqual(certIndex, &item)) { 3875 return PR_TRUE; 3876 } 3877 if (CERT_GetSubjectPublicKeyDigest(NULL, testCert, SEC_OID_MD2, 3878 &item) == NULL) { 3879 return PR_FALSE; 3880 } 3881 if (SECITEM_ItemsAreEqual(certIndex, &item)) { 3882 return PR_TRUE; 3883 } 3884 3885 return PR_FALSE; 3886 } 3887 3888 static CERTCertificate * 3889 ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle, CERTOCSPCertID *certID); 3890 3891 CERTCertificate * 3892 ocsp_GetSignerCertificate(CERTCertDBHandle *handle, ocspResponseData *tbsData, 3893 ocspSignature *signature, CERTCertificate *issuer) 3894 { 3895 CERTCertificate **certs = NULL; 3896 CERTCertificate *signerCert = NULL; 3897 SECStatus rv = SECFailure; 3898 PRBool lookupByName = PR_TRUE; 3899 void *certIndex = NULL; 3900 int certCount = 0; 3901 3902 PORT_Assert(tbsData->responderID != NULL); 3903 switch (tbsData->responderID->responderIDType) { 3904 case ocspResponderID_byName: 3905 lookupByName = PR_TRUE; 3906 certIndex = &tbsData->derResponderID; 3907 break; 3908 case ocspResponderID_byKey: 3909 lookupByName = PR_FALSE; 3910 certIndex = &tbsData->responderID->responderIDValue.keyHash; 3911 break; 3912 case ocspResponderID_other: 3913 default: 3914 PORT_Assert(0); 3915 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); 3916 return NULL; 3917 } 3918 3919 /* 3920 * If the signature contains some certificates as well, temporarily 3921 * import them in case they are needed for verification. 3922 * 3923 * Note that the result of this is that each cert in "certs" needs 3924 * to be destroyed. 3925 */ 3926 if (signature->derCerts != NULL) { 3927 for (; signature->derCerts[certCount] != NULL; certCount++) { 3928 /* just counting */ 3929 } 3930 rv = CERT_ImportCerts(handle, certUsageStatusResponder, certCount, 3931 signature->derCerts, &certs, 3932 PR_FALSE, PR_FALSE, NULL); 3933 if (rv != SECSuccess) 3934 goto finish; 3935 } 3936 3937 /* 3938 * Now look up the certificate that did the signing. 3939 * The signer can be specified either by name or by key hash. 3940 */ 3941 if (lookupByName) { 3942 SECItem *crIndex = (SECItem *)certIndex; 3943 SECItem encodedName; 3944 PLArenaPool *arena; 3945 3946 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 3947 if (arena != NULL) { 3948 3949 rv = SEC_QuickDERDecodeItem(arena, &encodedName, 3950 ocsp_ResponderIDDerNameTemplate, 3951 crIndex); 3952 if (rv != SECSuccess) { 3953 if (PORT_GetError() == SEC_ERROR_BAD_DER) 3954 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); 3955 } else { 3956 signerCert = CERT_FindCertByName(handle, &encodedName); 3957 } 3958 PORT_FreeArena(arena, PR_FALSE); 3959 } 3960 } else { 3961 /* 3962 * The signer is either 1) a known issuer CA we passed in, 3963 * 2) the default OCSP responder, or 3) an intermediate CA 3964 * passed in the cert list to use. Figure out which it is. 3965 */ 3966 int i; 3967 CERTCertificate *responder = 3968 ocsp_CertGetDefaultResponder(handle, NULL); 3969 if (responder && ocsp_matchcert(certIndex, responder)) { 3970 signerCert = CERT_DupCertificate(responder); 3971 } else if (issuer && ocsp_matchcert(certIndex, issuer)) { 3972 signerCert = CERT_DupCertificate(issuer); 3973 } 3974 for (i = 0; (signerCert == NULL) && (i < certCount); i++) { 3975 if (ocsp_matchcert(certIndex, certs[i])) { 3976 signerCert = CERT_DupCertificate(certs[i]); 3977 } 3978 } 3979 if (signerCert == NULL) { 3980 PORT_SetError(SEC_ERROR_UNKNOWN_CERT); 3981 } 3982 } 3983 3984 finish: 3985 if (certs != NULL) { 3986 CERT_DestroyCertArray(certs, certCount); 3987 } 3988 3989 return signerCert; 3990 } 3991 3992 SECStatus 3993 ocsp_VerifyResponseSignature(CERTCertificate *signerCert, 3994 ocspSignature *signature, 3995 SECItem *tbsResponseDataDER, 3996 void *pwArg) 3997 { 3998 SECKEYPublicKey *signerKey = NULL; 3999 SECStatus rv = SECFailure; 4000 CERTSignedData signedData; 4001 4002 /* 4003 * Now get the public key from the signer's certificate; we need 4004 * it to perform the verification. 4005 */ 4006 signerKey = CERT_ExtractPublicKey(signerCert); 4007 if (signerKey == NULL) { 4008 return SECFailure; 4009 } 4010 4011 /* 4012 * We copy the signature data *pointer* and length, so that we can 4013 * modify the length without damaging the original copy. This is a 4014 * simple copy, not a dup, so no destroy/free is necessary. 4015 */ 4016 signedData.signature = signature->signature; 4017 signedData.signatureAlgorithm = signature->signatureAlgorithm; 4018 signedData.data = *tbsResponseDataDER; 4019 4020 rv = CERT_VerifySignedDataWithPublicKey(&signedData, signerKey, pwArg); 4021 if (rv != SECSuccess && 4022 (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE || 4023 PORT_GetError() == SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED)) { 4024 PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE); 4025 } 4026 4027 if (signerKey != NULL) { 4028 SECKEY_DestroyPublicKey(signerKey); 4029 } 4030 4031 return rv; 4032 } 4033 4034 /* 4035 * FUNCTION: CERT_VerifyOCSPResponseSignature 4036 * Check the signature on an OCSP Response. Will also perform a 4037 * verification of the signer's certificate. Note, however, that a 4038 * successful verification does not make any statement about the 4039 * signer's *authority* to provide status for the certificate(s), 4040 * that must be checked individually for each certificate. 4041 * INPUTS: 4042 * CERTOCSPResponse *response 4043 * Pointer to response structure with signature to be checked. 4044 * CERTCertDBHandle *handle 4045 * Pointer to CERTCertDBHandle for certificate DB to use for verification. 4046 * void *pwArg 4047 * Pointer to argument for password prompting, if needed. 4048 * OUTPUTS: 4049 * CERTCertificate **pSignerCert 4050 * Pointer in which to store signer's certificate; only filled-in if 4051 * non-null. 4052 * RETURN: 4053 * Returns SECSuccess when signature is valid, anything else means invalid. 4054 * Possible errors set: 4055 * SEC_ERROR_OCSP_MALFORMED_RESPONSE - unknown type of ResponderID 4056 * SEC_ERROR_INVALID_TIME - bad format of "ProducedAt" time 4057 * SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found 4058 * SEC_ERROR_BAD_SIGNATURE - the signature did not verify 4059 * Other errors are any of the many possible failures in cert verification 4060 * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when 4061 * verifying the signer's cert, or low-level problems (no memory, etc.) 4062 */ 4063 SECStatus 4064 CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response, 4065 CERTCertDBHandle *handle, void *pwArg, 4066 CERTCertificate **pSignerCert, 4067 CERTCertificate *issuer) 4068 { 4069 SECItem *tbsResponseDataDER; 4070 CERTCertificate *signerCert = NULL; 4071 SECStatus rv = SECFailure; 4072 PRTime producedAt; 4073 4074 /* ocsp_DecodeBasicOCSPResponse will fail if asn1 decoder is unable 4075 * to properly decode tbsData (see the function and 4076 * ocsp_BasicOCSPResponseTemplate). Thus, tbsData can not be 4077 * equal to null */ 4078 ocspResponseData *tbsData = ocsp_GetResponseData(response, 4079 &tbsResponseDataDER); 4080 ocspSignature *signature = ocsp_GetResponseSignature(response); 4081 4082 if (!signature) { 4083 PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE); 4084 return SECFailure; 4085 } 4086 4087 /* 4088 * If this signature has already gone through verification, just 4089 * return the cached result. 4090 */ 4091 if (signature->wasChecked) { 4092 if (signature->status == SECSuccess) { 4093 if (pSignerCert != NULL) 4094 *pSignerCert = CERT_DupCertificate(signature->cert); 4095 } else { 4096 PORT_SetError(signature->failureReason); 4097 } 4098 return signature->status; 4099 } 4100 4101 signerCert = ocsp_GetSignerCertificate(handle, tbsData, 4102 signature, issuer); 4103 if (signerCert == NULL) { 4104 rv = SECFailure; 4105 if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) { 4106 /* Make the error a little more specific. */ 4107 PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT); 4108 } 4109 goto finish; 4110 } 4111 4112 /* 4113 * We could mark this true at the top of this function, or always 4114 * below at "finish", but if the problem was just that we could not 4115 * find the signer's cert, leave that as if the signature hasn't 4116 * been checked in case a subsequent call might have better luck. 4117 */ 4118 signature->wasChecked = PR_TRUE; 4119 4120 /* 4121 * The function will also verify the signer certificate; we 4122 * need to tell it *when* that certificate must be valid -- for our 4123 * purposes we expect it to be valid when the response was signed. 4124 * The value of "producedAt" is the signing time. 4125 */ 4126 rv = DER_GeneralizedTimeToTime(&producedAt, &tbsData->producedAt); 4127 if (rv != SECSuccess) 4128 goto finish; 4129 4130 /* 4131 * Just because we have a cert does not mean it is any good; check 4132 * it for validity, trust and usage. 4133 */ 4134 if (!ocsp_CertIsOCSPDefaultResponder(handle, signerCert)) { 4135 SECCertUsage certUsage; 4136 if (CERT_IsCACert(signerCert, NULL)) { 4137 certUsage = certUsageAnyCA; 4138 } else { 4139 certUsage = certUsageStatusResponder; 4140 } 4141 rv = cert_VerifyCertWithFlags(handle, signerCert, PR_TRUE, certUsage, 4142 producedAt, CERT_VERIFYCERT_SKIP_OCSP, 4143 pwArg, NULL); 4144 if (rv != SECSuccess) { 4145 PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT); 4146 goto finish; 4147 } 4148 } 4149 4150 rv = ocsp_VerifyResponseSignature(signerCert, signature, 4151 tbsResponseDataDER, 4152 pwArg); 4153 4154 finish: 4155 if (signature->wasChecked) 4156 signature->status = rv; 4157 4158 if (rv != SECSuccess) { 4159 signature->failureReason = PORT_GetError(); 4160 if (signerCert != NULL) 4161 CERT_DestroyCertificate(signerCert); 4162 } else { 4163 /* 4164 * Save signer's certificate in signature. 4165 */ 4166 signature->cert = signerCert; 4167 if (pSignerCert != NULL) { 4168 /* 4169 * Pass pointer to signer's certificate back to our caller, 4170 * who is also now responsible for destroying it. 4171 */ 4172 *pSignerCert = CERT_DupCertificate(signerCert); 4173 } 4174 } 4175 4176 return rv; 4177 } 4178 4179 /* 4180 * See if the request's certID and the single response's certID match. 4181 * This can be easy or difficult, depending on whether the same hash 4182 * algorithm was used. 4183 */ 4184 static PRBool 4185 ocsp_CertIDsMatch(CERTOCSPCertID *requestCertID, 4186 CERTOCSPCertID *responseCertID) 4187 { 4188 PRBool match = PR_FALSE; 4189 SECOidTag hashAlg; 4190 SECItem *keyHash = NULL; 4191 SECItem *nameHash = NULL; 4192 4193 /* 4194 * In order to match, they must have the same issuer and the same 4195 * serial number. 4196 * 4197 * We just compare the easier things first. 4198 */ 4199 if (SECITEM_CompareItem(&requestCertID->serialNumber, 4200 &responseCertID->serialNumber) != SECEqual) { 4201 goto done; 4202 } 4203 4204 /* 4205 * Make sure the "parameters" are not too bogus. Since we encoded 4206 * requestCertID->hashAlgorithm, we don't need to check it. 4207 */ 4208 if (responseCertID->hashAlgorithm.parameters.len > 2) { 4209 goto done; 4210 } 4211 if (SECITEM_CompareItem(&requestCertID->hashAlgorithm.algorithm, 4212 &responseCertID->hashAlgorithm.algorithm) == 4213 SECEqual) { 4214 /* 4215 * If the hash algorithms match then we can do a simple compare 4216 * of the hash values themselves. 4217 */ 4218 if ((SECITEM_CompareItem(&requestCertID->issuerNameHash, 4219 &responseCertID->issuerNameHash) == SECEqual) && 4220 (SECITEM_CompareItem(&requestCertID->issuerKeyHash, 4221 &responseCertID->issuerKeyHash) == SECEqual)) { 4222 match = PR_TRUE; 4223 } 4224 goto done; 4225 } 4226 4227 hashAlg = SECOID_FindOIDTag(&responseCertID->hashAlgorithm.algorithm); 4228 switch (hashAlg) { 4229 case SEC_OID_SHA1: 4230 keyHash = &requestCertID->issuerSHA1KeyHash; 4231 nameHash = &requestCertID->issuerSHA1NameHash; 4232 break; 4233 case SEC_OID_MD5: 4234 keyHash = &requestCertID->issuerMD5KeyHash; 4235 nameHash = &requestCertID->issuerMD5NameHash; 4236 break; 4237 case SEC_OID_MD2: 4238 keyHash = &requestCertID->issuerMD2KeyHash; 4239 nameHash = &requestCertID->issuerMD2NameHash; 4240 break; 4241 default: 4242 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 4243 return PR_FALSE; 4244 } 4245 4246 if ((keyHash != NULL) && 4247 (SECITEM_CompareItem(nameHash, 4248 &responseCertID->issuerNameHash) == SECEqual) && 4249 (SECITEM_CompareItem(keyHash, 4250 &responseCertID->issuerKeyHash) == SECEqual)) { 4251 match = PR_TRUE; 4252 } 4253 4254 done: 4255 return match; 4256 } 4257 4258 /* 4259 * Find the single response for the cert specified by certID. 4260 * No copying is done; this just returns a pointer to the appropriate 4261 * response within responses, if it is found (and null otherwise). 4262 * This is fine, of course, since this function is internal-use only. 4263 */ 4264 static CERTOCSPSingleResponse * 4265 ocsp_GetSingleResponseForCertID(CERTOCSPSingleResponse **responses, 4266 CERTCertDBHandle *handle, 4267 CERTOCSPCertID *certID) 4268 { 4269 CERTOCSPSingleResponse *single; 4270 int i; 4271 4272 if (responses == NULL) 4273 return NULL; 4274 4275 for (i = 0; responses[i] != NULL; i++) { 4276 single = responses[i]; 4277 if (ocsp_CertIDsMatch(certID, single->certID)) { 4278 return single; 4279 } 4280 } 4281 4282 /* 4283 * The OCSP server should have included a response even if it knew 4284 * nothing about the certificate in question. Since it did not, 4285 * this will make it look as if it had. 4286 * 4287 * XXX Should we make this a separate error to notice the server's 4288 * bad behavior? 4289 */ 4290 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT); 4291 return NULL; 4292 } 4293 4294 static ocspCheckingContext * 4295 ocsp_GetCheckingContext(CERTCertDBHandle *handle) 4296 { 4297 CERTStatusConfig *statusConfig; 4298 ocspCheckingContext *ocspcx = NULL; 4299 4300 statusConfig = CERT_GetStatusConfig(handle); 4301 if (statusConfig != NULL) { 4302 ocspcx = statusConfig->statusContext; 4303 4304 /* 4305 * This is actually an internal error, because we should never 4306 * have a good statusConfig without a good statusContext, too. 4307 * For lack of anything better, though, we just assert and use 4308 * the same error as if there were no statusConfig (set below). 4309 */ 4310 PORT_Assert(ocspcx != NULL); 4311 } 4312 4313 if (ocspcx == NULL) 4314 PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED); 4315 4316 return ocspcx; 4317 } 4318 4319 /* 4320 * Return cert reference if the given signerCert is the default responder for 4321 * the given certID. If not, or if any error, return NULL. 4322 */ 4323 static CERTCertificate * 4324 ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle, CERTOCSPCertID *certID) 4325 { 4326 ocspCheckingContext *ocspcx; 4327 4328 ocspcx = ocsp_GetCheckingContext(handle); 4329 if (ocspcx == NULL) 4330 goto loser; 4331 4332 /* 4333 * Right now we have only one default responder. It applies to 4334 * all certs when it is used, so the check is simple and certID 4335 * has no bearing on the answer. Someday in the future we may 4336 * allow configuration of different responders for different 4337 * issuers, and then we would have to use the issuer specified 4338 * in certID to determine if signerCert is the right one. 4339 */ 4340 if (ocspcx->useDefaultResponder) { 4341 PORT_Assert(ocspcx->defaultResponderCert != NULL); 4342 return ocspcx->defaultResponderCert; 4343 } 4344 4345 loser: 4346 return NULL; 4347 } 4348 4349 /* 4350 * Return true if the cert is one of the default responders configured for 4351 * ocsp context. If not, or if any error, return false. 4352 */ 4353 PRBool 4354 ocsp_CertIsOCSPDefaultResponder(CERTCertDBHandle *handle, CERTCertificate *cert) 4355 { 4356 ocspCheckingContext *ocspcx; 4357 4358 ocspcx = ocsp_GetCheckingContext(handle); 4359 if (ocspcx == NULL) 4360 return PR_FALSE; 4361 4362 /* 4363 * Right now we have only one default responder. It applies to 4364 * all certs when it is used, so the check is simple and certID 4365 * has no bearing on the answer. Someday in the future we may 4366 * allow configuration of different responders for different 4367 * issuers, and then we would have to use the issuer specified 4368 * in certID to determine if signerCert is the right one. 4369 */ 4370 if (ocspcx->useDefaultResponder && 4371 CERT_CompareCerts(ocspcx->defaultResponderCert, cert)) { 4372 return PR_TRUE; 4373 } 4374 4375 return PR_FALSE; 4376 } 4377 4378 /* 4379 * Check that the given signer certificate is authorized to sign status 4380 * information for the given certID. Return true if it is, false if not 4381 * (or if there is any error along the way). If false is returned because 4382 * the signer is not authorized, the following error will be set: 4383 * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE 4384 * Other errors are low-level problems (no memory, bad database, etc.). 4385 * 4386 * There are three ways to be authorized. In the order in which we check, 4387 * using the terms used in the OCSP spec, the signer must be one of: 4388 * 1. A "trusted responder" -- it matches a local configuration 4389 * of OCSP signing authority for the certificate in question. 4390 * 2. The CA who issued the certificate in question. 4391 * 3. A "CA designated responder", aka an "authorized responder" -- it 4392 * must be represented by a special cert issued by the CA who issued 4393 * the certificate in question. 4394 */ 4395 static PRBool 4396 ocsp_AuthorizedResponderForCertID(CERTCertDBHandle *handle, 4397 CERTCertificate *signerCert, 4398 CERTOCSPCertID *certID, 4399 PRTime thisUpdate) 4400 { 4401 CERTCertificate *issuerCert = NULL, *defRespCert; 4402 SECItem *keyHash = NULL; 4403 SECItem *nameHash = NULL; 4404 SECOidTag hashAlg; 4405 PRBool keyHashEQ = PR_FALSE, nameHashEQ = PR_FALSE; 4406 4407 /* 4408 * Check first for a trusted responder, which overrides everything else. 4409 */ 4410 if ((defRespCert = ocsp_CertGetDefaultResponder(handle, certID)) && 4411 CERT_CompareCerts(defRespCert, signerCert)) { 4412 return PR_TRUE; 4413 } 4414 4415 /* 4416 * In the other two cases, we need to do an issuer comparison. 4417 * How we do it depends on whether the signer certificate has the 4418 * special extension (for a designated responder) or not. 4419 * 4420 * First, lets check if signer of the response is the actual issuer 4421 * of the cert. For that we will use signer cert key hash and cert subj 4422 * name hash and will compare them with already calculated issuer key 4423 * hash and issuer name hash. The hash algorithm is picked from response 4424 * certID hash to avoid second hash calculation. 4425 */ 4426 4427 hashAlg = SECOID_FindOIDTag(&certID->hashAlgorithm.algorithm); 4428 4429 keyHash = CERT_GetSubjectPublicKeyDigest(NULL, signerCert, hashAlg, NULL); 4430 if (keyHash != NULL) { 4431 4432 keyHashEQ = 4433 (SECITEM_CompareItem(keyHash, 4434 &certID->issuerKeyHash) == SECEqual); 4435 SECITEM_FreeItem(keyHash, PR_TRUE); 4436 } 4437 if (keyHashEQ && 4438 (nameHash = CERT_GetSubjectNameDigest(NULL, signerCert, 4439 hashAlg, NULL))) { 4440 nameHashEQ = 4441 (SECITEM_CompareItem(nameHash, 4442 &certID->issuerNameHash) == SECEqual); 4443 4444 SECITEM_FreeItem(nameHash, PR_TRUE); 4445 if (nameHashEQ) { 4446 /* The issuer of the cert is the the signer of the response */ 4447 return PR_TRUE; 4448 } 4449 } 4450 4451 keyHashEQ = PR_FALSE; 4452 nameHashEQ = PR_FALSE; 4453 4454 if (!ocsp_CertIsOCSPDesignatedResponder(signerCert)) { 4455 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE); 4456 return PR_FALSE; 4457 } 4458 4459 /* 4460 * The signer is a designated responder. Its issuer must match 4461 * the issuer of the cert being checked. 4462 */ 4463 issuerCert = CERT_FindCertIssuer(signerCert, thisUpdate, 4464 certUsageAnyCA); 4465 if (issuerCert == NULL) { 4466 /* 4467 * We could leave the SEC_ERROR_UNKNOWN_ISSUER error alone, 4468 * but the following will give slightly more information. 4469 * Once we have an error stack, things will be much better. 4470 */ 4471 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE); 4472 return PR_FALSE; 4473 } 4474 4475 keyHash = CERT_GetSubjectPublicKeyDigest(NULL, issuerCert, hashAlg, NULL); 4476 nameHash = CERT_GetSubjectNameDigest(NULL, issuerCert, hashAlg, NULL); 4477 4478 CERT_DestroyCertificate(issuerCert); 4479 4480 if (keyHash != NULL && nameHash != NULL) { 4481 keyHashEQ = 4482 (SECITEM_CompareItem(keyHash, 4483 &certID->issuerKeyHash) == SECEqual); 4484 4485 nameHashEQ = 4486 (SECITEM_CompareItem(nameHash, 4487 &certID->issuerNameHash) == SECEqual); 4488 } 4489 4490 if (keyHash) { 4491 SECITEM_FreeItem(keyHash, PR_TRUE); 4492 } 4493 if (nameHash) { 4494 SECITEM_FreeItem(nameHash, PR_TRUE); 4495 } 4496 4497 if (keyHashEQ && nameHashEQ) { 4498 return PR_TRUE; 4499 } 4500 4501 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE); 4502 return PR_FALSE; 4503 } 4504 4505 /* 4506 * We need to check that a responder gives us "recent" information. 4507 * Since a responder can pre-package responses, we need to pick an amount 4508 * of time that is acceptable to us, and reject any response that is 4509 * older than that. 4510 * 4511 * XXX This *should* be based on some configuration parameter, so that 4512 * different usages could specify exactly what constitutes "sufficiently 4513 * recent". But that is not going to happen right away. For now, we 4514 * want something from within the last 24 hours. This macro defines that 4515 * number in seconds. 4516 */ 4517 #define OCSP_ALLOWABLE_LAPSE_SECONDS (24L * 60L * 60L) 4518 4519 static PRBool 4520 ocsp_TimeIsRecent(PRTime checkTime) 4521 { 4522 PRTime now = PR_Now(); 4523 PRTime lapse, tmp; 4524 4525 LL_I2L(lapse, OCSP_ALLOWABLE_LAPSE_SECONDS); 4526 LL_I2L(tmp, PR_USEC_PER_SEC); 4527 LL_MUL(lapse, lapse, tmp); /* allowable lapse in microseconds */ 4528 4529 LL_ADD(checkTime, checkTime, lapse); 4530 if (LL_CMP(now, >, checkTime)) 4531 return PR_FALSE; 4532 4533 return PR_TRUE; 4534 } 4535 4536 #define OCSP_SLOP (5L * 60L) /* OCSP responses are allowed to be 5 minutes \ 4537 in the future by default */ 4538 4539 static PRUint32 ocspsloptime = OCSP_SLOP; /* seconds */ 4540 4541 /* 4542 * If an old response contains the revoked certificate status, we want 4543 * to return SECSuccess so the response will be used. 4544 */ 4545 static SECStatus 4546 ocsp_HandleOldSingleResponse(CERTOCSPSingleResponse *single, PRTime time) 4547 { 4548 SECStatus rv; 4549 ocspCertStatus *status = single->certStatus; 4550 if (status->certStatusType == ocspCertStatus_revoked) { 4551 rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time); 4552 if (rv != SECSuccess && 4553 PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE) { 4554 /* 4555 * Return SECSuccess now. The subsequent ocsp_CertRevokedAfter 4556 * call in ocsp_CertHasGoodStatus will cause 4557 * ocsp_CertHasGoodStatus to fail with 4558 * SEC_ERROR_REVOKED_CERTIFICATE. 4559 */ 4560 return SECSuccess; 4561 } 4562 } 4563 PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE); 4564 return SECFailure; 4565 } 4566 4567 /* 4568 * Check that this single response is okay. A return of SECSuccess means: 4569 * 1. The signer (represented by "signerCert") is authorized to give status 4570 * for the cert represented by the individual response in "single". 4571 * 2. The value of thisUpdate is earlier than now. 4572 * 3. The value of producedAt is later than or the same as thisUpdate. 4573 * 4. If nextUpdate is given: 4574 * - The value of nextUpdate is later than now. 4575 * - The value of producedAt is earlier than nextUpdate. 4576 * Else if no nextUpdate: 4577 * - The value of thisUpdate is fairly recent. 4578 * - The value of producedAt is fairly recent. 4579 * However we do not need to perform an explicit check for this last 4580 * constraint because it is already guaranteed by checking that 4581 * producedAt is later than thisUpdate and thisUpdate is recent. 4582 * Oh, and any responder is "authorized" to say that a cert is unknown to it. 4583 * 4584 * If any of those checks fail, SECFailure is returned and an error is set: 4585 * SEC_ERROR_OCSP_FUTURE_RESPONSE 4586 * SEC_ERROR_OCSP_OLD_RESPONSE 4587 * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE 4588 * Other errors are low-level problems (no memory, bad database, etc.). 4589 */ 4590 static SECStatus 4591 ocsp_VerifySingleResponse(CERTOCSPSingleResponse *single, 4592 CERTCertDBHandle *handle, 4593 CERTCertificate *signerCert, 4594 PRTime producedAt) 4595 { 4596 CERTOCSPCertID *certID = single->certID; 4597 PRTime now, thisUpdate, nextUpdate, tmstamp, tmp; 4598 SECStatus rv; 4599 4600 OCSP_TRACE(("OCSP ocsp_VerifySingleResponse, nextUpdate: %d\n", 4601 ((single->nextUpdate) != 0))); 4602 /* 4603 * If all the responder said was that the given cert was unknown to it, 4604 * that is a valid response. Not very interesting to us, of course, 4605 * but all this function is concerned with is validity of the response, 4606 * not the status of the cert. 4607 */ 4608 PORT_Assert(single->certStatus != NULL); 4609 if (single->certStatus->certStatusType == ocspCertStatus_unknown) 4610 return SECSuccess; 4611 4612 /* 4613 * We need to extract "thisUpdate" for use below and to pass along 4614 * to AuthorizedResponderForCertID in case it needs it for doing an 4615 * issuer look-up. 4616 */ 4617 rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate); 4618 if (rv != SECSuccess) 4619 return rv; 4620 4621 /* 4622 * First confirm that signerCert is authorized to give this status. 4623 */ 4624 if (ocsp_AuthorizedResponderForCertID(handle, signerCert, certID, 4625 thisUpdate) != PR_TRUE) 4626 return SECFailure; 4627 4628 /* 4629 * Now check the time stuff, as described above. 4630 */ 4631 now = PR_Now(); 4632 /* allow slop time for future response */ 4633 LL_UI2L(tmstamp, ocspsloptime); /* get slop time in seconds */ 4634 LL_UI2L(tmp, PR_USEC_PER_SEC); 4635 LL_MUL(tmp, tmstamp, tmp); /* convert the slop time to PRTime */ 4636 LL_ADD(tmstamp, tmp, now); /* add current time to it */ 4637 4638 if (LL_CMP(thisUpdate, >, tmstamp) || LL_CMP(producedAt, <, thisUpdate)) { 4639 PORT_SetError(SEC_ERROR_OCSP_FUTURE_RESPONSE); 4640 return SECFailure; 4641 } 4642 if (single->nextUpdate != NULL) { 4643 rv = DER_GeneralizedTimeToTime(&nextUpdate, single->nextUpdate); 4644 if (rv != SECSuccess) 4645 return rv; 4646 4647 LL_ADD(tmp, tmp, nextUpdate); 4648 if (LL_CMP(tmp, <, now) || LL_CMP(producedAt, >, nextUpdate)) 4649 return ocsp_HandleOldSingleResponse(single, now); 4650 } else if (ocsp_TimeIsRecent(thisUpdate) != PR_TRUE) { 4651 return ocsp_HandleOldSingleResponse(single, now); 4652 } 4653 4654 return SECSuccess; 4655 } 4656 4657 /* 4658 * FUNCTION: CERT_GetOCSPAuthorityInfoAccessLocation 4659 * Get the value of the URI of the OCSP responder for the given cert. 4660 * This is found in the (optional) Authority Information Access extension 4661 * in the cert. 4662 * INPUTS: 4663 * CERTCertificate *cert 4664 * The certificate being examined. 4665 * RETURN: 4666 * char * 4667 * A copy of the URI for the OCSP method, if found. If either the 4668 * extension is not present or it does not contain an entry for OCSP, 4669 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION will be set and a NULL returned. 4670 * Any other error will also result in a NULL being returned. 4671 * 4672 * This result should be freed (via PORT_Free) when no longer in use. 4673 */ 4674 char * 4675 CERT_GetOCSPAuthorityInfoAccessLocation(const CERTCertificate *cert) 4676 { 4677 CERTGeneralName *locname = NULL; 4678 SECItem *location = NULL; 4679 SECItem *encodedAuthInfoAccess = NULL; 4680 CERTAuthInfoAccess **authInfoAccess = NULL; 4681 char *locURI = NULL; 4682 PLArenaPool *arena = NULL; 4683 SECStatus rv; 4684 int i; 4685 4686 /* 4687 * Allocate this one from the heap because it will get filled in 4688 * by CERT_FindCertExtension which will also allocate from the heap, 4689 * and we can free the entire thing on our way out. 4690 */ 4691 encodedAuthInfoAccess = SECITEM_AllocItem(NULL, NULL, 0); 4692 if (encodedAuthInfoAccess == NULL) 4693 goto loser; 4694 4695 rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS, 4696 encodedAuthInfoAccess); 4697 if (rv == SECFailure) { 4698 PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); 4699 goto loser; 4700 } 4701 4702 /* 4703 * The rest of the things allocated in the routine will come out of 4704 * this arena, which is temporary just for us to decode and get at the 4705 * AIA extension. The whole thing will be destroyed on our way out, 4706 * after we have copied the location string (url) itself (if found). 4707 */ 4708 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 4709 if (arena == NULL) 4710 goto loser; 4711 4712 authInfoAccess = CERT_DecodeAuthInfoAccessExtension(arena, 4713 encodedAuthInfoAccess); 4714 if (authInfoAccess == NULL) 4715 goto loser; 4716 4717 for (i = 0; authInfoAccess[i] != NULL; i++) { 4718 if (SECOID_FindOIDTag(&authInfoAccess[i]->method) == SEC_OID_PKIX_OCSP) 4719 locname = authInfoAccess[i]->location; 4720 } 4721 4722 /* 4723 * If we found an AIA extension, but it did not include an OCSP method, 4724 * that should look to our caller as if we did not find the extension 4725 * at all, because it is only an OCSP method that we care about. 4726 * So set the same error that would be set if the AIA extension was 4727 * not there at all. 4728 */ 4729 if (locname == NULL) { 4730 PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); 4731 goto loser; 4732 } 4733 4734 /* 4735 * The following is just a pointer back into locname (i.e. not a copy); 4736 * thus it should not be freed. 4737 */ 4738 location = CERT_GetGeneralNameByType(locname, certURI, PR_FALSE); 4739 if (location == NULL) { 4740 /* 4741 * XXX Appears that CERT_GetGeneralNameByType does not set an 4742 * error if there is no name by that type. For lack of anything 4743 * better, act as if the extension was not found. In the future 4744 * this should probably be something more like the extension was 4745 * badly formed. 4746 */ 4747 PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION); 4748 goto loser; 4749 } 4750 4751 /* 4752 * That location is really a string, but it has a specified length 4753 * without a null-terminator. We need a real string that does have 4754 * a null-terminator, and we need a copy of it anyway to return to 4755 * our caller -- so allocate and copy. 4756 */ 4757 locURI = PORT_Alloc(location->len + 1); 4758 if (locURI == NULL) { 4759 goto loser; 4760 } 4761 PORT_Memcpy(locURI, location->data, location->len); 4762 locURI[location->len] = '\0'; 4763 4764 loser: 4765 if (arena != NULL) 4766 PORT_FreeArena(arena, PR_FALSE); 4767 4768 if (encodedAuthInfoAccess != NULL) 4769 SECITEM_FreeItem(encodedAuthInfoAccess, PR_TRUE); 4770 4771 return locURI; 4772 } 4773 4774 /* 4775 * Figure out where we should go to find out the status of the given cert 4776 * via OCSP. If allowed to use a default responder uri and a default 4777 * responder is set up, then that is our answer. 4778 * If not, see if the certificate has an Authority Information Access (AIA) 4779 * extension for OCSP, and return the value of that. Otherwise return NULL. 4780 * We also let our caller know whether or not the responder chosen was 4781 * a default responder or not through the output variable isDefault; 4782 * its value has no meaning unless a good (non-null) value is returned 4783 * for the location. 4784 * 4785 * The result needs to be freed (PORT_Free) when no longer in use. 4786 */ 4787 char * 4788 ocsp_GetResponderLocation(CERTCertDBHandle *handle, CERTCertificate *cert, 4789 PRBool canUseDefault, PRBool *isDefault) 4790 { 4791 ocspCheckingContext *ocspcx = NULL; 4792 char *ocspUrl = NULL; 4793 4794 if (canUseDefault) { 4795 ocspcx = ocsp_GetCheckingContext(handle); 4796 } 4797 if (ocspcx != NULL && ocspcx->useDefaultResponder) { 4798 /* 4799 * A default responder wins out, if specified. 4800 * XXX Someday this may be a more complicated determination based 4801 * on the cert's issuer. (That is, we could have different default 4802 * responders configured for different issuers.) 4803 */ 4804 PORT_Assert(ocspcx->defaultResponderURI != NULL); 4805 *isDefault = PR_TRUE; 4806 return (PORT_Strdup(ocspcx->defaultResponderURI)); 4807 } 4808 4809 /* 4810 * No default responder set up, so go see if we can find an AIA 4811 * extension that has a value for OCSP, and get the url from that. 4812 */ 4813 *isDefault = PR_FALSE; 4814 ocspUrl = CERT_GetOCSPAuthorityInfoAccessLocation(cert); 4815 if (!ocspUrl) { 4816 CERT_StringFromCertFcn altFcn; 4817 4818 PR_EnterMonitor(OCSP_Global.monitor); 4819 altFcn = OCSP_Global.alternateOCSPAIAFcn; 4820 PR_ExitMonitor(OCSP_Global.monitor); 4821 if (altFcn) { 4822 ocspUrl = (*altFcn)(cert); 4823 if (ocspUrl) 4824 *isDefault = PR_TRUE; 4825 } 4826 } 4827 return ocspUrl; 4828 } 4829 4830 /* 4831 * Return SECSuccess if the cert was revoked *after* "time", 4832 * SECFailure otherwise. 4833 */ 4834 static SECStatus 4835 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, PRTime time) 4836 { 4837 PRTime revokedTime; 4838 SECStatus rv; 4839 4840 rv = DER_GeneralizedTimeToTime(&revokedTime, &revokedInfo->revocationTime); 4841 if (rv != SECSuccess) 4842 return rv; 4843 4844 /* 4845 * Set the error even if we will return success; someone might care. 4846 */ 4847 PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); 4848 4849 if (LL_CMP(revokedTime, >, time)) 4850 return SECSuccess; 4851 4852 return SECFailure; 4853 } 4854 4855 /* 4856 * See if the cert represented in the single response had a good status 4857 * at the specified time. 4858 */ 4859 SECStatus 4860 ocsp_CertHasGoodStatus(ocspCertStatus *status, PRTime time) 4861 { 4862 SECStatus rv; 4863 switch (status->certStatusType) { 4864 case ocspCertStatus_good: 4865 rv = SECSuccess; 4866 break; 4867 case ocspCertStatus_revoked: 4868 rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time); 4869 break; 4870 case ocspCertStatus_unknown: 4871 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT); 4872 rv = SECFailure; 4873 break; 4874 case ocspCertStatus_other: 4875 default: 4876 PORT_Assert(0); 4877 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); 4878 rv = SECFailure; 4879 break; 4880 } 4881 return rv; 4882 } 4883 4884 static SECStatus 4885 ocsp_SingleResponseCertHasGoodStatus(CERTOCSPSingleResponse *single, 4886 PRTime time) 4887 { 4888 return ocsp_CertHasGoodStatus(single->certStatus, time); 4889 } 4890 4891 /* SECFailure means the arguments were invalid. 4892 * On SECSuccess, the out parameters contain the OCSP status. 4893 * rvOcsp contains the overall result of the OCSP operation. 4894 * Depending on input parameter ignoreGlobalOcspFailureSetting, 4895 * a soft failure might be converted into *rvOcsp=SECSuccess. 4896 * If the cached attempt to obtain OCSP information had resulted 4897 * in a failure, missingResponseError shows the error code of 4898 * that failure. 4899 * cacheFreshness is ocspMissing if no entry was found, 4900 * ocspFresh if a fresh entry was found, or 4901 * ocspStale if a stale entry was found. 4902 */ 4903 SECStatus 4904 ocsp_GetCachedOCSPResponseStatus(CERTOCSPCertID *certID, 4905 PRTime time, 4906 PRBool ignoreGlobalOcspFailureSetting, 4907 SECStatus *rvOcsp, 4908 SECErrorCodes *missingResponseError, 4909 OCSPFreshness *cacheFreshness) 4910 { 4911 OCSPCacheItem *cacheItem = NULL; 4912 4913 if (!certID || !missingResponseError || !rvOcsp || !cacheFreshness) { 4914 PORT_SetError(SEC_ERROR_INVALID_ARGS); 4915 return SECFailure; 4916 } 4917 *rvOcsp = SECFailure; 4918 *missingResponseError = 0; 4919 *cacheFreshness = ocspMissing; 4920 4921 PR_EnterMonitor(OCSP_Global.monitor); 4922 cacheItem = ocsp_FindCacheEntry(&OCSP_Global.cache, certID); 4923 if (cacheItem) { 4924 *cacheFreshness = ocsp_IsCacheItemFresh(cacheItem) ? ocspFresh 4925 : ocspStale; 4926 /* having an arena means, we have a cached certStatus */ 4927 if (cacheItem->certStatusArena) { 4928 *rvOcsp = ocsp_CertHasGoodStatus(&cacheItem->certStatus, time); 4929 if (*rvOcsp != SECSuccess) { 4930 *missingResponseError = PORT_GetError(); 4931 } 4932 } else { 4933 /* 4934 * No status cached, the previous attempt failed. 4935 * If OCSP is required, we never decide based on a failed attempt 4936 * However, if OCSP is optional, a recent OCSP failure is 4937 * an allowed good state. 4938 */ 4939 if (*cacheFreshness == ocspFresh && 4940 !ignoreGlobalOcspFailureSetting && 4941 OCSP_Global.ocspFailureMode == 4942 ocspMode_FailureIsNotAVerificationFailure) { 4943 *rvOcsp = SECSuccess; 4944 } 4945 *missingResponseError = cacheItem->missingResponseError; 4946 } 4947 } 4948 PR_ExitMonitor(OCSP_Global.monitor); 4949 return SECSuccess; 4950 } 4951 4952 PRBool 4953 ocsp_FetchingFailureIsVerificationFailure(void) 4954 { 4955 PRBool isFailure; 4956 4957 PR_EnterMonitor(OCSP_Global.monitor); 4958 isFailure = 4959 OCSP_Global.ocspFailureMode == ocspMode_FailureIsVerificationFailure; 4960 PR_ExitMonitor(OCSP_Global.monitor); 4961 return isFailure; 4962 } 4963 4964 /* 4965 * FUNCTION: CERT_CheckOCSPStatus 4966 * Checks the status of a certificate via OCSP. Will only check status for 4967 * a certificate that has an AIA (Authority Information Access) extension 4968 * for OCSP *or* when a "default responder" is specified and enabled. 4969 * (If no AIA extension for OCSP and no default responder in place, the 4970 * cert is considered to have a good status and SECSuccess is returned.) 4971 * INPUTS: 4972 * CERTCertDBHandle *handle 4973 * certificate DB of the cert that is being checked 4974 * CERTCertificate *cert 4975 * the certificate being checked 4976 * XXX in the long term also need a boolean parameter that specifies 4977 * whether to check the cert chain, as well; for now we check only 4978 * the leaf (the specified certificate) 4979 * PRTime time 4980 * time for which status is to be determined 4981 * void *pwArg 4982 * argument for password prompting, if needed 4983 * RETURN: 4984 * Returns SECSuccess if an approved OCSP responder "knows" the cert 4985 * *and* returns a non-revoked status for it; SECFailure otherwise, 4986 * with an error set describing the reason: 4987 * 4988 * SEC_ERROR_OCSP_BAD_HTTP_RESPONSE 4989 * SEC_ERROR_OCSP_FUTURE_RESPONSE 4990 * SEC_ERROR_OCSP_MALFORMED_REQUEST 4991 * SEC_ERROR_OCSP_MALFORMED_RESPONSE 4992 * SEC_ERROR_OCSP_OLD_RESPONSE 4993 * SEC_ERROR_OCSP_REQUEST_NEEDS_SIG 4994 * SEC_ERROR_OCSP_SERVER_ERROR 4995 * SEC_ERROR_OCSP_TRY_SERVER_LATER 4996 * SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST 4997 * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE 4998 * SEC_ERROR_OCSP_UNKNOWN_CERT 4999 * SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS 5000 * SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE 5001 * 5002 * SEC_ERROR_BAD_SIGNATURE 5003 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION 5004 * SEC_ERROR_INVALID_TIME 5005 * SEC_ERROR_REVOKED_CERTIFICATE 5006 * SEC_ERROR_UNKNOWN_ISSUER 5007 * SEC_ERROR_UNKNOWN_SIGNER 5008 * 5009 * Other errors are any of the many possible failures in cert verification 5010 * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when 5011 * verifying the signer's cert, or low-level problems (error allocating 5012 * memory, error performing ASN.1 decoding, etc.). 5013 */ 5014 SECStatus 5015 CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, 5016 PRTime time, void *pwArg) 5017 { 5018 CERTOCSPCertID *certID; 5019 PRBool certIDWasConsumed = PR_FALSE; 5020 SECStatus rv; 5021 SECStatus rvOcsp; 5022 SECErrorCodes cachedErrorCode; 5023 OCSPFreshness cachedResponseFreshness; 5024 5025 OCSP_TRACE_CERT(cert); 5026 OCSP_TRACE_TIME("## requested validity time:", time); 5027 5028 certID = CERT_CreateOCSPCertID(cert, time); 5029 if (!certID) 5030 return SECFailure; 5031 rv = ocsp_GetCachedOCSPResponseStatus( 5032 certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */ 5033 &rvOcsp, &cachedErrorCode, &cachedResponseFreshness); 5034 if (rv != SECSuccess) { 5035 CERT_DestroyOCSPCertID(certID); 5036 return SECFailure; 5037 } 5038 if (cachedResponseFreshness == ocspFresh) { 5039 CERT_DestroyOCSPCertID(certID); 5040 if (rvOcsp != SECSuccess) { 5041 PORT_SetError(cachedErrorCode); 5042 } 5043 return rvOcsp; 5044 } 5045 5046 rv = ocsp_GetOCSPStatusFromNetwork(handle, certID, cert, time, pwArg, 5047 &certIDWasConsumed, 5048 &rvOcsp); 5049 if (rv != SECSuccess) { 5050 PRErrorCode err = PORT_GetError(); 5051 if (ocsp_FetchingFailureIsVerificationFailure()) { 5052 PORT_SetError(err); 5053 rvOcsp = SECFailure; 5054 } else if (cachedResponseFreshness == ocspStale && 5055 (cachedErrorCode == SEC_ERROR_OCSP_UNKNOWN_CERT || 5056 cachedErrorCode == SEC_ERROR_REVOKED_CERTIFICATE)) { 5057 /* If we couldn't get a response for a certificate that the OCSP 5058 * responder previously told us was bad, then assume it is still 5059 * bad until we hear otherwise, as it is very unlikely that the 5060 * certificate status has changed from "revoked" to "good" and it 5061 * is also unlikely that the certificate status has changed from 5062 * "unknown" to "good", except for some buggy OCSP responders. 5063 */ 5064 PORT_SetError(cachedErrorCode); 5065 rvOcsp = SECFailure; 5066 } else { 5067 rvOcsp = SECSuccess; 5068 } 5069 } 5070 if (!certIDWasConsumed) { 5071 CERT_DestroyOCSPCertID(certID); 5072 } 5073 return rvOcsp; 5074 } 5075 5076 /* 5077 * FUNCTION: CERT_CacheOCSPResponseFromSideChannel 5078 * First, this function checks the OCSP cache to see if a good response 5079 * for the given certificate already exists. If it does, then the function 5080 * returns successfully. 5081 * 5082 * If not, then it validates that the given OCSP response is a valid, 5083 * good response for the given certificate and inserts it into the 5084 * cache. 5085 * 5086 * This function is intended for use when OCSP responses are provided via a 5087 * side-channel, i.e. TLS OCSP stapling (a.k.a. the status_request extension). 5088 * 5089 * INPUTS: 5090 * CERTCertDBHandle *handle 5091 * certificate DB of the cert that is being checked 5092 * CERTCertificate *cert 5093 * the certificate being checked 5094 * PRTime time 5095 * time for which status is to be determined 5096 * SECItem *encodedResponse 5097 * the DER encoded bytes of the OCSP response 5098 * void *pwArg 5099 * argument for password prompting, if needed 5100 * RETURN: 5101 * SECSuccess if the cert was found in the cache, or if the OCSP response was 5102 * found to be valid and inserted into the cache. SECFailure otherwise. 5103 */ 5104 SECStatus 5105 CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle, 5106 CERTCertificate *cert, 5107 PRTime time, 5108 const SECItem *encodedResponse, 5109 void *pwArg) 5110 { 5111 CERTOCSPCertID *certID = NULL; 5112 PRBool certIDWasConsumed = PR_FALSE; 5113 SECStatus rv = SECFailure; 5114 SECStatus rvOcsp = SECFailure; 5115 SECErrorCodes dummy_error_code; /* we ignore this */ 5116 CERTOCSPResponse *decodedResponse = NULL; 5117 CERTOCSPSingleResponse *singleResponse = NULL; 5118 OCSPFreshness freshness; 5119 5120 /* The OCSP cache can be in three states regarding this certificate: 5121 * + Good (cached, timely, 'good' response, or revoked in the future) 5122 * + Revoked (cached, timely, but doesn't fit in the last category) 5123 * + Miss (no knowledge) 5124 * 5125 * Likewise, the side-channel information can be 5126 * + Good (timely, 'good' response, or revoked in the future) 5127 * + Revoked (timely, but doesn't fit in the last category) 5128 * + Invalid (bad syntax, bad signature, not timely etc) 5129 * 5130 * The common case is that the cache result is Good and so is the 5131 * side-channel information. We want to save processing time in this case 5132 * so we say that any time we see a Good result from the cache we return 5133 * early. 5134 * 5135 * Cache result 5136 * | Good Revoked Miss 5137 * ---+-------------------------------------------- 5138 * G | noop Cache more Cache it 5139 * S | recent result 5140 * i | 5141 * d | 5142 * e | 5143 * R | noop Cache more Cache it 5144 * C | recent result 5145 * h | 5146 * a | 5147 * n | 5148 * n I | noop Noop Noop 5149 * e | 5150 * l | 5151 * 5152 * When we fetch from the network we might choose to cache a negative 5153 * result when the response is invalid. This saves us hammering, uselessly, 5154 * at a broken responder. However, side channels are commonly attacker 5155 * controlled and so we must not cache a negative result for an Invalid 5156 * side channel. 5157 */ 5158 5159 if (!cert || !encodedResponse) { 5160 PORT_SetError(SEC_ERROR_INVALID_ARGS); 5161 return SECFailure; 5162 } 5163 certID = CERT_CreateOCSPCertID(cert, time); 5164 if (!certID) 5165 return SECFailure; 5166 5167 /* We pass PR_TRUE for ignoreGlobalOcspFailureSetting so that a cached 5168 * error entry is not interpreted as being a 'Good' entry here. 5169 */ 5170 rv = ocsp_GetCachedOCSPResponseStatus( 5171 certID, time, PR_TRUE, /* ignoreGlobalOcspFailureSetting */ 5172 &rvOcsp, &dummy_error_code, &freshness); 5173 if (rv == SECSuccess && rvOcsp == SECSuccess && freshness == ocspFresh) { 5174 /* The cached value is good. We don't want to waste time validating 5175 * this OCSP response. This is the first column in the table above. */ 5176 CERT_DestroyOCSPCertID(certID); 5177 return rv; 5178 } 5179 5180 /* The logic for caching the more recent response is handled in 5181 * ocsp_CacheSingleResponse. */ 5182 5183 rv = ocsp_GetDecodedVerifiedSingleResponseForID(handle, certID, cert, 5184 time, pwArg, 5185 encodedResponse, 5186 &decodedResponse, 5187 &singleResponse); 5188 if (rv == SECSuccess) { 5189 rvOcsp = ocsp_SingleResponseCertHasGoodStatus(singleResponse, time); 5190 /* Cache any valid singleResponse, regardless of status. */ 5191 ocsp_CacheSingleResponse(certID, singleResponse, &certIDWasConsumed); 5192 } 5193 if (decodedResponse) { 5194 CERT_DestroyOCSPResponse(decodedResponse); 5195 } 5196 if (!certIDWasConsumed) { 5197 CERT_DestroyOCSPCertID(certID); 5198 } 5199 return rv == SECSuccess ? rvOcsp : rv; 5200 } 5201 5202 /* 5203 * Status in *certIDWasConsumed will always be correct, regardless of 5204 * return value. 5205 */ 5206 static SECStatus 5207 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle, 5208 CERTOCSPCertID *certID, 5209 CERTCertificate *cert, 5210 PRTime time, 5211 void *pwArg, 5212 PRBool *certIDWasConsumed, 5213 SECStatus *rv_ocsp) 5214 { 5215 char *location = NULL; 5216 PRBool locationIsDefault; 5217 SECItem *encodedResponse = NULL; 5218 CERTOCSPRequest *request = NULL; 5219 SECStatus rv = SECFailure; 5220 5221 CERTOCSPResponse *decodedResponse = NULL; 5222 CERTOCSPSingleResponse *singleResponse = NULL; 5223 enum { stageGET, 5224 stagePOST } currentStage; 5225 PRBool retry = PR_FALSE; 5226 5227 if (!certIDWasConsumed || !rv_ocsp) { 5228 PORT_SetError(SEC_ERROR_INVALID_ARGS); 5229 return SECFailure; 5230 } 5231 *certIDWasConsumed = PR_FALSE; 5232 *rv_ocsp = SECFailure; 5233 5234 if (!OCSP_Global.monitor) { 5235 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 5236 return SECFailure; 5237 } 5238 PR_EnterMonitor(OCSP_Global.monitor); 5239 if (OCSP_Global.forcePost) { 5240 currentStage = stagePOST; 5241 } else { 5242 currentStage = stageGET; 5243 } 5244 PR_ExitMonitor(OCSP_Global.monitor); 5245 5246 /* 5247 * The first thing we need to do is find the location of the responder. 5248 * This will be the value of the default responder (if enabled), else 5249 * it will come out of the AIA extension in the cert (if present). 5250 * If we have no such location, then this cert does not "deserve" to 5251 * be checked -- that is, we consider it a success and just return. 5252 * The way we tell that is by looking at the error number to see if 5253 * the problem was no AIA extension was found; any other error was 5254 * a true failure that we unfortunately have to treat as an overall 5255 * failure here. 5256 */ 5257 location = ocsp_GetResponderLocation(handle, cert, PR_TRUE, 5258 &locationIsDefault); 5259 if (location == NULL) { 5260 int err = PORT_GetError(); 5261 if (err == SEC_ERROR_EXTENSION_NOT_FOUND || 5262 err == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) { 5263 PORT_SetError(0); 5264 *rv_ocsp = SECSuccess; 5265 return SECSuccess; 5266 } 5267 return SECFailure; 5268 } 5269 5270 /* 5271 * XXX In the fullness of time, we will want/need to handle a 5272 * certificate chain. This will be done either when a new parameter 5273 * tells us to, or some configuration variable tells us to. In any 5274 * case, handling it is complicated because we may need to send as 5275 * many requests (and receive as many responses) as we have certs 5276 * in the chain. If we are going to talk to a default responder, 5277 * and we only support one default responder, we can put all of the 5278 * certs together into one request. Otherwise, we must break them up 5279 * into multiple requests. (Even if all of the requests will go to 5280 * the same location, the signature on each response will be different, 5281 * because each issuer is different. Carefully read the OCSP spec 5282 * if you do not understand this.) 5283 */ 5284 5285 /* 5286 * XXX If/when signing of requests is supported, that second NULL 5287 * should be changed to be the signer certificate. Not sure if that 5288 * should be passed into this function or retrieved via some operation 5289 * on the handle/context. 5290 */ 5291 5292 do { 5293 const char *method; 5294 PRBool validResponseWithAccurateInfo = PR_FALSE; 5295 retry = PR_FALSE; 5296 *rv_ocsp = SECFailure; 5297 5298 if (currentStage == stageGET) { 5299 method = "GET"; 5300 } else { 5301 PORT_Assert(currentStage == stagePOST); 5302 method = "POST"; 5303 } 5304 5305 encodedResponse = 5306 ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert, 5307 location, method, 5308 time, locationIsDefault, 5309 pwArg, &request); 5310 5311 if (encodedResponse) { 5312 rv = ocsp_GetDecodedVerifiedSingleResponseForID(handle, certID, cert, 5313 time, pwArg, 5314 encodedResponse, 5315 &decodedResponse, 5316 &singleResponse); 5317 if (rv == SECSuccess) { 5318 switch (singleResponse->certStatus->certStatusType) { 5319 case ocspCertStatus_good: 5320 case ocspCertStatus_revoked: 5321 validResponseWithAccurateInfo = PR_TRUE; 5322 break; 5323 default: 5324 break; 5325 } 5326 *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(singleResponse, time); 5327 } 5328 } 5329 5330 if (currentStage == stageGET) { 5331 /* only accept GET response if good or revoked */ 5332 if (validResponseWithAccurateInfo) { 5333 ocsp_CacheSingleResponse(certID, singleResponse, 5334 certIDWasConsumed); 5335 } else { 5336 retry = PR_TRUE; 5337 currentStage = stagePOST; 5338 } 5339 } else { 5340 /* cache the POST respone, regardless of status */ 5341 if (!singleResponse) { 5342 cert_RememberOCSPProcessingFailure(certID, certIDWasConsumed); 5343 } else { 5344 ocsp_CacheSingleResponse(certID, singleResponse, 5345 certIDWasConsumed); 5346 } 5347 } 5348 5349 if (encodedResponse) { 5350 SECITEM_FreeItem(encodedResponse, PR_TRUE); 5351 encodedResponse = NULL; 5352 } 5353 if (request) { 5354 CERT_DestroyOCSPRequest(request); 5355 request = NULL; 5356 } 5357 if (decodedResponse) { 5358 CERT_DestroyOCSPResponse(decodedResponse); 5359 decodedResponse = NULL; 5360 } 5361 singleResponse = NULL; 5362 5363 } while (retry); 5364 5365 PORT_Free(location); 5366 return rv; 5367 } 5368 5369 /* 5370 * FUNCTION: ocsp_GetDecodedVerifiedSingleResponseForID 5371 * This function decodes an OCSP response and checks for a valid response 5372 * concerning the given certificate. 5373 * 5374 * Note: a 'valid' response is one that parses successfully, is not an OCSP 5375 * exception (see RFC 2560 Section 2.3), is correctly signed and is current. 5376 * A 'good' response is a valid response that attests that the certificate 5377 * is not currently revoked (see RFC 2560 Section 2.2). 5378 * 5379 * INPUTS: 5380 * CERTCertDBHandle *handle 5381 * certificate DB of the cert that is being checked 5382 * CERTOCSPCertID *certID 5383 * the cert ID corresponding to |cert| 5384 * CERTCertificate *cert 5385 * the certificate being checked 5386 * PRTime time 5387 * time for which status is to be determined 5388 * void *pwArg 5389 * the opaque argument to the password prompting function. 5390 * SECItem *encodedResponse 5391 * the DER encoded bytes of the OCSP response 5392 * CERTOCSPResponse **pDecodedResponse 5393 * (output) The caller must ALWAYS check for this output parameter, 5394 * and if it's non-null, must destroy it using CERT_DestroyOCSPResponse. 5395 * CERTOCSPSingleResponse **pSingle 5396 * (output) on success, this points to the single response that corresponds 5397 * to the certID parameter. Points to the inside of pDecodedResponse. 5398 * It isn't a copy, don't free it. 5399 * RETURN: 5400 * SECSuccess iff the response is valid. 5401 */ 5402 static SECStatus 5403 ocsp_GetDecodedVerifiedSingleResponseForID(CERTCertDBHandle *handle, 5404 CERTOCSPCertID *certID, 5405 CERTCertificate *cert, 5406 PRTime time, 5407 void *pwArg, 5408 const SECItem *encodedResponse, 5409 CERTOCSPResponse **pDecodedResponse, 5410 CERTOCSPSingleResponse **pSingle) 5411 { 5412 CERTCertificate *signerCert = NULL; 5413 CERTCertificate *issuerCert = NULL; 5414 SECStatus rv = SECFailure; 5415 5416 if (!pSingle || !pDecodedResponse) { 5417 return SECFailure; 5418 } 5419 *pSingle = NULL; 5420 *pDecodedResponse = CERT_DecodeOCSPResponse(encodedResponse); 5421 if (!*pDecodedResponse) { 5422 return SECFailure; 5423 } 5424 5425 /* 5426 * Okay, we at least have a response that *looks* like a response! 5427 * Now see if the overall response status value is good or not. 5428 * If not, we set an error and give up. (It means that either the 5429 * server had a problem, or it didn't like something about our 5430 * request. Either way there is nothing to do but give up.) 5431 * Otherwise, we continue to find the actual per-cert status 5432 * in the response. 5433 */ 5434 if (CERT_GetOCSPResponseStatus(*pDecodedResponse) != SECSuccess) { 5435 goto loser; 5436 } 5437 5438 /* 5439 * If we've made it this far, we expect a response with a good signature. 5440 * So, check for that. 5441 */ 5442 issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); 5443 rv = CERT_VerifyOCSPResponseSignature(*pDecodedResponse, handle, pwArg, 5444 &signerCert, issuerCert); 5445 if (rv != SECSuccess) { 5446 goto loser; 5447 } 5448 5449 PORT_Assert(signerCert != NULL); /* internal consistency check */ 5450 /* XXX probably should set error, return failure if signerCert is null */ 5451 5452 /* 5453 * Again, we are only doing one request for one cert. 5454 * XXX When we handle cert chains, the following code will obviously 5455 * have to be modified, in coordation with the code above that will 5456 * have to determine how to make multiple requests, etc. 5457 */ 5458 rv = ocsp_GetVerifiedSingleResponseForCertID(handle, *pDecodedResponse, certID, 5459 signerCert, time, pSingle); 5460 loser: 5461 if (issuerCert != NULL) 5462 CERT_DestroyCertificate(issuerCert); 5463 if (signerCert != NULL) 5464 CERT_DestroyCertificate(signerCert); 5465 return rv; 5466 } 5467 5468 /* 5469 * FUNCTION: ocsp_CacheSingleResponse 5470 * This function requires that the caller has checked that the response 5471 * is valid and verified. 5472 * The (positive or negative) valid response will be used to update the cache. 5473 * INPUTS: 5474 * CERTOCSPCertID *certID 5475 * the cert ID corresponding to |cert| 5476 * PRBool *certIDWasConsumed 5477 * (output) on return, this is true iff |certID| was consumed by this 5478 * function. 5479 */ 5480 void 5481 ocsp_CacheSingleResponse(CERTOCSPCertID *certID, 5482 CERTOCSPSingleResponse *single, 5483 PRBool *certIDWasConsumed) 5484 { 5485 if (single != NULL) { 5486 PR_EnterMonitor(OCSP_Global.monitor); 5487 if (OCSP_Global.maxCacheEntries >= 0) { 5488 ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single, 5489 certIDWasConsumed); 5490 /* ignore cache update failures */ 5491 } 5492 PR_ExitMonitor(OCSP_Global.monitor); 5493 } 5494 } 5495 5496 SECStatus 5497 ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle, 5498 CERTOCSPResponse *response, 5499 CERTOCSPCertID *certID, 5500 CERTCertificate *signerCert, 5501 PRTime time, 5502 CERTOCSPSingleResponse 5503 **pSingleResponse) 5504 { 5505 SECStatus rv; 5506 ocspResponseData *responseData; 5507 PRTime producedAt; 5508 CERTOCSPSingleResponse *single; 5509 5510 /* 5511 * The ResponseData part is the real guts of the response. 5512 */ 5513 responseData = ocsp_GetResponseData(response, NULL); 5514 if (responseData == NULL) { 5515 rv = SECFailure; 5516 goto loser; 5517 } 5518 5519 /* 5520 * There is one producedAt time for the entire response (and a separate 5521 * thisUpdate time for each individual single response). We need to 5522 * compare them, so get the overall time to pass into the check of each 5523 * single response. 5524 */ 5525 rv = DER_GeneralizedTimeToTime(&producedAt, &responseData->producedAt); 5526 if (rv != SECSuccess) 5527 goto loser; 5528 5529 single = ocsp_GetSingleResponseForCertID(responseData->responses, 5530 handle, certID); 5531 if (single == NULL) { 5532 rv = SECFailure; 5533 goto loser; 5534 } 5535 5536 rv = ocsp_VerifySingleResponse(single, handle, signerCert, producedAt); 5537 if (rv != SECSuccess) 5538 goto loser; 5539 *pSingleResponse = single; 5540 5541 loser: 5542 return rv; 5543 } 5544 5545 SECStatus 5546 CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle, 5547 CERTOCSPResponse *response, 5548 CERTOCSPCertID *certID, 5549 CERTCertificate *signerCert, 5550 PRTime time) 5551 { 5552 /* 5553 * We do not update the cache, because: 5554 * 5555 * CERT_GetOCSPStatusForCertID is an old exported API that was introduced 5556 * before the OCSP cache got implemented. 5557 * 5558 * The implementation of helper function cert_ProcessOCSPResponse 5559 * requires the ability to transfer ownership of the the given certID to 5560 * the cache. The external API doesn't allow us to prevent the caller from 5561 * destroying the certID. We don't have the original certificate available, 5562 * therefore we are unable to produce another certID object (that could 5563 * be stored in the cache). 5564 * 5565 * Should we ever implement code to produce a deep copy of certID, 5566 * then this could be changed to allow updating the cache. 5567 * The duplication would have to be done in 5568 * cert_ProcessOCSPResponse, if the out parameter to indicate 5569 * a transfer of ownership is NULL. 5570 */ 5571 return cert_ProcessOCSPResponse(handle, response, certID, 5572 signerCert, time, 5573 NULL, NULL); 5574 } 5575 5576 /* 5577 * The first 5 parameters match the definition of CERT_GetOCSPStatusForCertID. 5578 */ 5579 SECStatus 5580 cert_ProcessOCSPResponse(CERTCertDBHandle *handle, 5581 CERTOCSPResponse *response, 5582 CERTOCSPCertID *certID, 5583 CERTCertificate *signerCert, 5584 PRTime time, 5585 PRBool *certIDWasConsumed, 5586 SECStatus *cacheUpdateStatus) 5587 { 5588 SECStatus rv; 5589 SECStatus rv_cache = SECSuccess; 5590 CERTOCSPSingleResponse *single = NULL; 5591 5592 rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, 5593 signerCert, time, &single); 5594 if (rv == SECSuccess) { 5595 /* 5596 * Check whether the status says revoked, and if so 5597 * how that compares to the time value passed into this routine. 5598 */ 5599 rv = ocsp_SingleResponseCertHasGoodStatus(single, time); 5600 } 5601 5602 if (certIDWasConsumed) { 5603 /* 5604 * We don't have copy-of-certid implemented. In order to update 5605 * the cache, the caller must supply an out variable 5606 * certIDWasConsumed, allowing us to return ownership status. 5607 */ 5608 5609 PR_EnterMonitor(OCSP_Global.monitor); 5610 if (OCSP_Global.maxCacheEntries >= 0) { 5611 /* single == NULL means: remember response failure */ 5612 rv_cache = 5613 ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, 5614 single, certIDWasConsumed); 5615 } 5616 PR_ExitMonitor(OCSP_Global.monitor); 5617 if (cacheUpdateStatus) { 5618 *cacheUpdateStatus = rv_cache; 5619 } 5620 } 5621 5622 return rv; 5623 } 5624 5625 SECStatus 5626 cert_RememberOCSPProcessingFailure(CERTOCSPCertID *certID, 5627 PRBool *certIDWasConsumed) 5628 { 5629 SECStatus rv = SECSuccess; 5630 PR_EnterMonitor(OCSP_Global.monitor); 5631 if (OCSP_Global.maxCacheEntries >= 0) { 5632 rv = ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, NULL, 5633 certIDWasConsumed); 5634 } 5635 PR_ExitMonitor(OCSP_Global.monitor); 5636 return rv; 5637 } 5638 5639 /* 5640 * Disable status checking and destroy related structures/data. 5641 */ 5642 static SECStatus 5643 ocsp_DestroyStatusChecking(CERTStatusConfig *statusConfig) 5644 { 5645 ocspCheckingContext *statusContext; 5646 5647 /* 5648 * Disable OCSP checking 5649 */ 5650 statusConfig->statusChecker = NULL; 5651 5652 statusContext = statusConfig->statusContext; 5653 PORT_Assert(statusContext != NULL); 5654 if (statusContext == NULL) 5655 return SECFailure; 5656 5657 if (statusContext->defaultResponderURI != NULL) 5658 PORT_Free(statusContext->defaultResponderURI); 5659 if (statusContext->defaultResponderNickname != NULL) 5660 PORT_Free(statusContext->defaultResponderNickname); 5661 5662 PORT_Free(statusContext); 5663 statusConfig->statusContext = NULL; 5664 5665 PORT_Free(statusConfig); 5666 5667 return SECSuccess; 5668 } 5669 5670 /* 5671 * FUNCTION: CERT_DisableOCSPChecking 5672 * Turns off OCSP checking for the given certificate database. 5673 * This routine disables OCSP checking. Though it will return 5674 * SECFailure if OCSP checking is not enabled, it is "safe" to 5675 * call it that way and just ignore the return value, if it is 5676 * easier to just call it than to "remember" whether it is enabled. 5677 * INPUTS: 5678 * CERTCertDBHandle *handle 5679 * Certificate database for which OCSP checking will be disabled. 5680 * RETURN: 5681 * Returns SECFailure if an error occurred (usually means that OCSP 5682 * checking was not enabled or status contexts were not initialized -- 5683 * error set will be SEC_ERROR_OCSP_NOT_ENABLED); SECSuccess otherwise. 5684 */ 5685 SECStatus 5686 CERT_DisableOCSPChecking(CERTCertDBHandle *handle) 5687 { 5688 CERTStatusConfig *statusConfig; 5689 ocspCheckingContext *statusContext; 5690 5691 if (handle == NULL) { 5692 PORT_SetError(SEC_ERROR_INVALID_ARGS); 5693 return SECFailure; 5694 } 5695 5696 statusConfig = CERT_GetStatusConfig(handle); 5697 statusContext = ocsp_GetCheckingContext(handle); 5698 if (statusContext == NULL) 5699 return SECFailure; 5700 5701 if (statusConfig->statusChecker != CERT_CheckOCSPStatus) { 5702 /* 5703 * Status configuration is present, but either not currently 5704 * enabled or not for OCSP. 5705 */ 5706 PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED); 5707 return SECFailure; 5708 } 5709 5710 /* cache no longer necessary */ 5711 CERT_ClearOCSPCache(); 5712 5713 /* 5714 * This is how we disable status checking. Everything else remains 5715 * in place in case we are enabled again. 5716 */ 5717 statusConfig->statusChecker = NULL; 5718 5719 return SECSuccess; 5720 } 5721 5722 /* 5723 * Allocate and initialize the informational structures for status checking. 5724 * This is done when some configuration of OCSP is being done or when OCSP 5725 * checking is being turned on, whichever comes first. 5726 */ 5727 static SECStatus 5728 ocsp_InitStatusChecking(CERTCertDBHandle *handle) 5729 { 5730 CERTStatusConfig *statusConfig = NULL; 5731 ocspCheckingContext *statusContext = NULL; 5732 5733 PORT_Assert(CERT_GetStatusConfig(handle) == NULL); 5734 if (CERT_GetStatusConfig(handle) != NULL) { 5735 /* XXX or call statusConfig->statusDestroy and continue? */ 5736 return SECFailure; 5737 } 5738 5739 statusConfig = PORT_ZNew(CERTStatusConfig); 5740 if (statusConfig == NULL) 5741 goto loser; 5742 5743 statusContext = PORT_ZNew(ocspCheckingContext); 5744 if (statusContext == NULL) 5745 goto loser; 5746 5747 statusConfig->statusDestroy = ocsp_DestroyStatusChecking; 5748 statusConfig->statusContext = statusContext; 5749 5750 CERT_SetStatusConfig(handle, statusConfig); 5751 5752 return SECSuccess; 5753 5754 loser: 5755 if (statusConfig != NULL) 5756 PORT_Free(statusConfig); 5757 return SECFailure; 5758 } 5759 5760 /* 5761 * FUNCTION: CERT_EnableOCSPChecking 5762 * Turns on OCSP checking for the given certificate database. 5763 * INPUTS: 5764 * CERTCertDBHandle *handle 5765 * Certificate database for which OCSP checking will be enabled. 5766 * RETURN: 5767 * Returns SECFailure if an error occurred (likely only problem 5768 * allocating memory); SECSuccess otherwise. 5769 */ 5770 SECStatus 5771 CERT_EnableOCSPChecking(CERTCertDBHandle *handle) 5772 { 5773 CERTStatusConfig *statusConfig; 5774 5775 SECStatus rv; 5776 5777 if (handle == NULL) { 5778 PORT_SetError(SEC_ERROR_INVALID_ARGS); 5779 return SECFailure; 5780 } 5781 5782 statusConfig = CERT_GetStatusConfig(handle); 5783 if (statusConfig == NULL) { 5784 rv = ocsp_InitStatusChecking(handle); 5785 if (rv != SECSuccess) 5786 return rv; 5787 5788 /* Get newly established value */ 5789 statusConfig = CERT_GetStatusConfig(handle); 5790 PORT_Assert(statusConfig != NULL); 5791 } 5792 5793 /* 5794 * Setting the checker function is what really enables the checking 5795 * when each cert verification is done. 5796 */ 5797 statusConfig->statusChecker = CERT_CheckOCSPStatus; 5798 5799 return SECSuccess; 5800 } 5801 5802 /* 5803 * FUNCTION: CERT_SetOCSPDefaultResponder 5804 * Specify the location and cert of the default responder. 5805 * If OCSP checking is already enabled *and* use of a default responder 5806 * is also already enabled, all OCSP checking from now on will go directly 5807 * to the specified responder. If OCSP checking is not enabled, or if 5808 * it is but use of a default responder is not enabled, the information 5809 * will be recorded and take effect whenever both are enabled. 5810 * INPUTS: 5811 * CERTCertDBHandle *handle 5812 * Cert database on which OCSP checking should use the default responder. 5813 * char *url 5814 * The location of the default responder (e.g. "http://foo.com:80/ocsp") 5815 * Note that the location will not be tested until the first attempt 5816 * to send a request there. 5817 * char *name 5818 * The nickname of the cert to trust (expected) to sign the OCSP responses. 5819 * If the corresponding cert cannot be found, SECFailure is returned. 5820 * RETURN: 5821 * Returns SECFailure if an error occurred; SECSuccess otherwise. 5822 * The most likely error is that the cert for "name" could not be found 5823 * (probably SEC_ERROR_UNKNOWN_CERT). Other errors are low-level (no memory, 5824 * bad database, etc.). 5825 */ 5826 SECStatus 5827 CERT_SetOCSPDefaultResponder(CERTCertDBHandle *handle, 5828 const char *url, const char *name) 5829 { 5830 CERTCertificate *cert; 5831 ocspCheckingContext *statusContext; 5832 char *url_copy = NULL; 5833 char *name_copy = NULL; 5834 SECStatus rv; 5835 5836 if (handle == NULL || url == NULL || name == NULL) { 5837 /* 5838 * XXX When interface is exported, probably want better errors; 5839 * perhaps different one for each parameter. 5840 */ 5841 PORT_SetError(SEC_ERROR_INVALID_ARGS); 5842 return SECFailure; 5843 } 5844 5845 /* 5846 * Find the certificate for the specified nickname. Do this first 5847 * because it seems the most likely to fail. 5848 * 5849 * XXX Shouldn't need that cast if the FindCertByNickname interface 5850 * used const to convey that it does not modify the name. Maybe someday. 5851 */ 5852 cert = CERT_FindCertByNickname(handle, (char *)name); 5853 if (cert == NULL) { 5854 /* 5855 * look for the cert on an external token. 5856 */ 5857 cert = PK11_FindCertFromNickname((char *)name, NULL); 5858 } 5859 if (cert == NULL) 5860 return SECFailure; 5861 5862 /* 5863 * Make a copy of the url and nickname. 5864 */ 5865 url_copy = PORT_Strdup(url); 5866 name_copy = PORT_Strdup(name); 5867 if (url_copy == NULL || name_copy == NULL) { 5868 rv = SECFailure; 5869 goto loser; 5870 } 5871 5872 statusContext = ocsp_GetCheckingContext(handle); 5873 5874 /* 5875 * Allocate and init the context if it doesn't already exist. 5876 */ 5877 if (statusContext == NULL) { 5878 rv = ocsp_InitStatusChecking(handle); 5879 if (rv != SECSuccess) 5880 goto loser; 5881 5882 statusContext = ocsp_GetCheckingContext(handle); 5883 PORT_Assert(statusContext != NULL); /* extreme paranoia */ 5884 } 5885 5886 /* 5887 * Note -- we do not touch the status context until after all of 5888 * the steps which could cause errors. If something goes wrong, 5889 * we want to leave things as they were. 5890 */ 5891 5892 /* 5893 * Get rid of old url and name if there. 5894 */ 5895 if (statusContext->defaultResponderNickname != NULL) 5896 PORT_Free(statusContext->defaultResponderNickname); 5897 if (statusContext->defaultResponderURI != NULL) 5898 PORT_Free(statusContext->defaultResponderURI); 5899 5900 /* 5901 * And replace them with the new ones. 5902 */ 5903 statusContext->defaultResponderURI = url_copy; 5904 statusContext->defaultResponderNickname = name_copy; 5905 5906 /* 5907 * If there was already a cert in place, get rid of it and replace it. 5908 * Otherwise, we are not currently enabled, so we don't want to save it; 5909 * it will get re-found and set whenever use of a default responder is 5910 * enabled. 5911 */ 5912 if (statusContext->defaultResponderCert != NULL) { 5913 CERT_DestroyCertificate(statusContext->defaultResponderCert); 5914 statusContext->defaultResponderCert = cert; 5915 /*OCSP enabled, switching responder: clear cache*/ 5916 CERT_ClearOCSPCache(); 5917 } else { 5918 PORT_Assert(statusContext->useDefaultResponder == PR_FALSE); 5919 CERT_DestroyCertificate(cert); 5920 /*OCSP currently not enabled, no need to clear cache*/ 5921 } 5922 5923 return SECSuccess; 5924 5925 loser: 5926 CERT_DestroyCertificate(cert); 5927 if (url_copy != NULL) 5928 PORT_Free(url_copy); 5929 if (name_copy != NULL) 5930 PORT_Free(name_copy); 5931 return rv; 5932 } 5933 5934 /* 5935 * FUNCTION: CERT_EnableOCSPDefaultResponder 5936 * Turns on use of a default responder when OCSP checking. 5937 * If OCSP checking is already enabled, this will make subsequent checks 5938 * go directly to the default responder. (The location of the responder 5939 * and the nickname of the responder cert must already be specified.) 5940 * If OCSP checking is not enabled, this will be recorded and take effect 5941 * whenever it is enabled. 5942 * INPUTS: 5943 * CERTCertDBHandle *handle 5944 * Cert database on which OCSP checking should use the default responder. 5945 * RETURN: 5946 * Returns SECFailure if an error occurred; SECSuccess otherwise. 5947 * No errors are especially likely unless the caller did not previously 5948 * perform a successful call to SetOCSPDefaultResponder (in which case 5949 * the error set will be SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER). 5950 */ 5951 SECStatus 5952 CERT_EnableOCSPDefaultResponder(CERTCertDBHandle *handle) 5953 { 5954 ocspCheckingContext *statusContext; 5955 CERTCertificate *cert; 5956 SECStatus rv; 5957 SECCertificateUsage usage; 5958 5959 if (handle == NULL) { 5960 PORT_SetError(SEC_ERROR_INVALID_ARGS); 5961 return SECFailure; 5962 } 5963 5964 statusContext = ocsp_GetCheckingContext(handle); 5965 5966 if (statusContext == NULL) { 5967 /* 5968 * Strictly speaking, the error already set is "correct", 5969 * but cover over it with one more helpful in this context. 5970 */ 5971 PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER); 5972 return SECFailure; 5973 } 5974 5975 if (statusContext->defaultResponderURI == NULL) { 5976 PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER); 5977 return SECFailure; 5978 } 5979 5980 if (statusContext->defaultResponderNickname == NULL) { 5981 PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER); 5982 return SECFailure; 5983 } 5984 5985 /* 5986 * Find the cert for the nickname. 5987 */ 5988 cert = CERT_FindCertByNickname(handle, 5989 statusContext->defaultResponderNickname); 5990 if (cert == NULL) { 5991 cert = PK11_FindCertFromNickname(statusContext->defaultResponderNickname, 5992 NULL); 5993 } 5994 /* 5995 * We should never have trouble finding the cert, because its 5996 * existence should have been proven by SetOCSPDefaultResponder. 5997 */ 5998 PORT_Assert(cert != NULL); 5999 if (cert == NULL) 6000 return SECFailure; 6001 6002 /* 6003 * Supplied cert should at least have a signing capability in order for us 6004 * to use it as a trusted responder cert. Ability to sign is guaranteed if 6005 * cert is validated to have any set of the usages below. 6006 */ 6007 rv = CERT_VerifyCertificateNow(handle, cert, PR_TRUE, 6008 certificateUsageCheckAllUsages, 6009 NULL, &usage); 6010 if (rv != SECSuccess || (usage & (certificateUsageSSLClient | certificateUsageSSLServer | certificateUsageSSLServerWithStepUp | certificateUsageEmailSigner | certificateUsageObjectSigner | certificateUsageStatusResponder | certificateUsageSSLCA)) == 0) { 6011 PORT_SetError(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID); 6012 return SECFailure; 6013 } 6014 6015 /* 6016 * And hang onto it. 6017 */ 6018 statusContext->defaultResponderCert = cert; 6019 6020 /* we don't allow a mix of cache entries from different responders */ 6021 CERT_ClearOCSPCache(); 6022 6023 /* 6024 * Finally, record the fact that we now have a default responder enabled. 6025 */ 6026 statusContext->useDefaultResponder = PR_TRUE; 6027 return SECSuccess; 6028 } 6029 6030 /* 6031 * FUNCTION: CERT_DisableOCSPDefaultResponder 6032 * Turns off use of a default responder when OCSP checking. 6033 * (Does nothing if use of a default responder is not enabled.) 6034 * INPUTS: 6035 * CERTCertDBHandle *handle 6036 * Cert database on which OCSP checking should stop using a default 6037 * responder. 6038 * RETURN: 6039 * Returns SECFailure if an error occurred; SECSuccess otherwise. 6040 * Errors very unlikely (like random memory corruption...). 6041 */ 6042 SECStatus 6043 CERT_DisableOCSPDefaultResponder(CERTCertDBHandle *handle) 6044 { 6045 CERTStatusConfig *statusConfig; 6046 ocspCheckingContext *statusContext; 6047 CERTCertificate *tmpCert; 6048 6049 if (handle == NULL) { 6050 PORT_SetError(SEC_ERROR_INVALID_ARGS); 6051 return SECFailure; 6052 } 6053 6054 statusConfig = CERT_GetStatusConfig(handle); 6055 if (statusConfig == NULL) 6056 return SECSuccess; 6057 6058 statusContext = ocsp_GetCheckingContext(handle); 6059 PORT_Assert(statusContext != NULL); 6060 if (statusContext == NULL) 6061 return SECFailure; 6062 6063 tmpCert = statusContext->defaultResponderCert; 6064 if (tmpCert) { 6065 statusContext->defaultResponderCert = NULL; 6066 CERT_DestroyCertificate(tmpCert); 6067 /* we don't allow a mix of cache entries from different responders */ 6068 CERT_ClearOCSPCache(); 6069 } 6070 6071 /* 6072 * Finally, record the fact. 6073 */ 6074 statusContext->useDefaultResponder = PR_FALSE; 6075 return SECSuccess; 6076 } 6077 6078 SECStatus 6079 CERT_ForcePostMethodForOCSP(PRBool forcePost) 6080 { 6081 if (!OCSP_Global.monitor) { 6082 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 6083 return SECFailure; 6084 } 6085 6086 PR_EnterMonitor(OCSP_Global.monitor); 6087 OCSP_Global.forcePost = forcePost; 6088 PR_ExitMonitor(OCSP_Global.monitor); 6089 6090 return SECSuccess; 6091 } 6092 6093 SECStatus 6094 CERT_GetOCSPResponseStatus(CERTOCSPResponse *response) 6095 { 6096 PORT_Assert(response); 6097 if (response->statusValue == ocspResponse_successful) 6098 return SECSuccess; 6099 6100 switch (response->statusValue) { 6101 case ocspResponse_malformedRequest: 6102 PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST); 6103 break; 6104 case ocspResponse_internalError: 6105 PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR); 6106 break; 6107 case ocspResponse_tryLater: 6108 PORT_SetError(SEC_ERROR_OCSP_TRY_SERVER_LATER); 6109 break; 6110 case ocspResponse_sigRequired: 6111 /* XXX We *should* retry with a signature, if possible. */ 6112 PORT_SetError(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG); 6113 break; 6114 case ocspResponse_unauthorized: 6115 PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST); 6116 break; 6117 case ocspResponse_unused: 6118 default: 6119 PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS); 6120 break; 6121 } 6122 return SECFailure; 6123 }