Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: mozilla/security/nss/lib/certhigh/ocsp.c

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

Powered by Google App Engine
This is Rietveld 408576698