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