comparison nss/lib/certhigh/ocsp.c @ 0:1e5118fa0cb1

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