~ubuntu-branches/ubuntu/lucid/seamonkey/lucid-security

« back to all changes in this revision

Viewing changes to security/nss/lib/certhigh/ocsp.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabien Tassin
  • Date: 2008-07-29 21:29:02 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080729212902-spm9kpvchp9udwbw
Tags: 1.1.11+nobinonly-0ubuntu1
* New security upstream release: 1.1.11 (LP: #218534)
  Fixes USN-602-1, USN-619-1, USN-623-1 and USN-629-1
* Refresh diverged patch:
  - update debian/patches/80_security_build.patch
* Fix FTBFS with missing -lfontconfig
  - add debian/patches/11_fix_ftbfs_with_fontconfig.patch
  - update debian/patches/series
* Build with default gcc (hardy: 4.2, intrepid: 4.3)
  - update debian/rules
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 * the Initial Developer. All Rights Reserved.
20
20
 *
21
21
 * Contributor(s):
 
22
 *   Kai Engert (kengert@redhat.com)
22
23
 *
23
24
 * Alternatively, the contents of this file may be used under the terms of
24
25
 * either the GNU General Public License Version 2 or later (the "GPL"), or
38
39
 * Implementation of OCSP services, for both client and server.
39
40
 * (XXX, really, mostly just for client right now, but intended to do both.)
40
41
 *
41
 
 * $Id: ocsp.c,v 1.21.2.12 2007/01/06 17:08:44 wtchang%redhat.com Exp $
 
42
 * $Id: ocsp.c,v 1.21.2.16 2007/05/25 03:37:37 alexei.volkov.bugs%sun.com Exp $
42
43
 */
43
44
 
44
45
#include "prerror.h"
66
67
#include "certxutl.h"
67
68
#include "pk11func.h"   /* for PK11_HashBuf */
68
69
#include <stdarg.h>
69
 
 
 
70
#include <plhash.h>
 
71
 
 
72
#define DEFAULT_OCSP_CACHE_SIZE 1000
 
73
#define DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 1*60*60L
 
74
#define DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 24*60*60L
 
75
#define MICROSECONDS_PER_SECOND 1000000L
 
76
 
 
77
typedef struct OCSPCacheItemStr OCSPCacheItem;
 
78
typedef struct OCSPCacheDataStr OCSPCacheData;
 
79
 
 
80
struct OCSPCacheItemStr {
 
81
    /* LRU linking */
 
82
    OCSPCacheItem *moreRecent;
 
83
    OCSPCacheItem *lessRecent;
 
84
 
 
85
    /* key */
 
86
    CERTOCSPCertID *certID;
 
87
    /* CertID's arena also used to allocate "this" cache item */
 
88
 
 
89
    /* cache control information */
 
90
    PRTime nextFetchAttemptTime;
 
91
 
 
92
    /* Cached contents. Use a separate arena, because lifetime is different */
 
93
    PRArenaPool *certStatusArena; /* NULL means: no cert status cached */
 
94
    ocspCertStatus certStatus;
 
95
 
 
96
    PRPackedBool haveThisUpdate;
 
97
    PRPackedBool haveNextUpdate;
 
98
    PRTime thisUpdate;
 
99
    PRTime nextUpdate;
 
100
};
 
101
 
 
102
struct OCSPCacheDataStr {
 
103
    PLHashTable *entries;
 
104
    PRUint32 numberOfEntries;
 
105
    OCSPCacheItem *MRUitem; /* most recently used cache item */
 
106
    OCSPCacheItem *LRUitem; /* least recently used cache item */
 
107
};
70
108
 
71
109
static struct OCSPGlobalStruct {
72
 
    PRLock *lock;
 
110
    PRMonitor *monitor;
73
111
    const SEC_HttpClientFcn *defaultHttpClientFcn;
74
 
} OCSP_Global = { NULL, NULL };
 
112
    PRInt32 maxCacheEntries;
 
113
    PRUint32 minimumSecondsToNextFetchAttempt;
 
114
    PRUint32 maximumSecondsToNextFetchAttempt;
 
115
    OCSPCacheData cache;
 
116
    SEC_OcspFailureMode ocspFailureMode;
 
117
} OCSP_Global = { NULL, 
 
118
                  NULL, 
 
119
                  DEFAULT_OCSP_CACHE_SIZE, 
 
120
                  DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT,
 
121
                  DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT,
 
122
                  {NULL, 0, NULL, NULL},
 
123
                  ocspMode_FailureIsVerificationFailure
 
124
                };
 
125
 
 
126
/* Forward declarations */
 
127
static SECItem *
 
128
ocsp_GetEncodedOCSPResponseFromRequest(PRArenaPool *arena, 
 
129
                                       CERTOCSPRequest *request,
 
130
                                       char *location, int64 time,
 
131
                                       PRBool addServiceLocator,
 
132
                                       void *pwArg,
 
133
                                       CERTOCSPRequest **pRequest);
 
134
static SECStatus
 
135
ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle, 
 
136
                              CERTOCSPCertID *certID, 
 
137
                              CERTCertificate *cert, 
 
138
                              int64 time, 
 
139
                              void *pwArg,
 
140
                              PRBool *certIDWasConsumed,
 
141
                              SECStatus *rv_ocsp);
 
142
static SECStatus
 
143
ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle, 
 
144
                                        CERTOCSPResponse *response, 
 
145
                                        CERTOCSPCertID   *certID,
 
146
                                        CERTCertificate  *signerCert,
 
147
                                        int64             time,
 
148
                                        CERTOCSPSingleResponse **pSingleResponse);
 
149
 
 
150
#ifndef DEBUG
 
151
#define OCSP_TRACE(msg)
 
152
#define OCSP_TRACE_TIME(msg, time)
 
153
#define OCSP_TRACE_CERT(cert)
 
154
#else
 
155
#define OCSP_TRACE(msg) ocsp_Trace msg
 
156
#define OCSP_TRACE_TIME(msg, time) ocsp_dumpStringWithTime(msg, time)
 
157
#define OCSP_TRACE_CERT(cert) dumpCertificate(cert)
 
158
 
 
159
#if (defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS) \
 
160
     || defined(XP_MACOSX)) && !defined(_WIN32_WCE)
 
161
#define NSS_HAVE_GETENV 1
 
162
#endif
 
163
 
 
164
static PRBool wantOcspTrace()
 
165
{
 
166
    static PRBool firstTime = PR_TRUE;
 
167
    static PRBool wantTrace = PR_FALSE;
 
168
 
 
169
#ifdef NSS_HAVE_GETENV
 
170
    if (firstTime) {
 
171
        char *ev = getenv("NSS_TRACE_OCSP");
 
172
        if (ev && ev[0]) {
 
173
            wantTrace = PR_TRUE;
 
174
        }
 
175
        firstTime = PR_FALSE;
 
176
    }
 
177
#endif
 
178
    return wantTrace;
 
179
}
 
180
 
 
181
static void
 
182
ocsp_Trace(const char *format, ...)
 
183
{
 
184
    char buf[2000];
 
185
    va_list args;
 
186
  
 
187
    if (!wantOcspTrace())
 
188
        return;
 
189
    va_start(args, format);
 
190
    PR_vsnprintf(buf, sizeof(buf), format, args);
 
191
    va_end(args);
 
192
    PR_LogPrint("%s", buf);
 
193
}
 
194
 
 
195
static void
 
196
ocsp_dumpStringWithTime(const char *str, int64 time)
 
197
{
 
198
    PRExplodedTime timePrintable;
 
199
    char timestr[100];
 
200
 
 
201
    if (!wantOcspTrace())
 
202
        return;
 
203
    PR_ExplodeTime(time, PR_GMTParameters, &timePrintable);
 
204
    PR_FormatTime(timestr, 100, "%a %b %d %H:%M:%S %Y", 
 
205
                  &timePrintable);
 
206
    ocsp_Trace("OCSP %s %s\n", str, timestr);
 
207
}
 
208
 
 
209
static void
 
210
printHexString(const char *prefix, SECItem *hexval)
 
211
{
 
212
    unsigned int i;
 
213
    char *hexbuf = NULL;
 
214
 
 
215
    for (i = 0; i < hexval->len; i++) {
 
216
        if (i != hexval->len - 1) {
 
217
            PR_sprintf_append(hexbuf, "%02x:", hexval->data[i]);
 
218
        } else {
 
219
            PR_sprintf_append(hexbuf, "%02x", hexval->data[i]);
 
220
        }
 
221
    }
 
222
    if (hexbuf) {
 
223
        ocsp_Trace("%s %s\n", prefix, hexbuf);
 
224
        PR_smprintf_free(hexbuf);
 
225
    }
 
226
}
 
227
 
 
228
static void
 
229
dumpCertificate(CERTCertificate *cert)
 
230
{
 
231
    if (!wantOcspTrace())
 
232
        return;
 
233
 
 
234
    ocsp_Trace("OCSP ----------------\n");
 
235
    ocsp_Trace("OCSP ## SUBJECT:  %s\n", cert->subjectName);
 
236
    {
 
237
        int64 timeBefore, timeAfter;
 
238
        PRExplodedTime beforePrintable, afterPrintable;
 
239
        char beforestr[100], afterstr[100];
 
240
        DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore);
 
241
        DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter);
 
242
        PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable);
 
243
        PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable);
 
244
        PR_FormatTime(beforestr, 100, "%a %b %d %H:%M:%S %Y", 
 
245
                      &beforePrintable);
 
246
        PR_FormatTime(afterstr, 100, "%a %b %d %H:%M:%S %Y", 
 
247
                      &afterPrintable);
 
248
        ocsp_Trace("OCSP ## VALIDITY:  %s to %s\n", beforestr, afterstr);
 
249
    }
 
250
    ocsp_Trace("OCSP ## ISSUER:  %s\n", cert->issuerName);
 
251
    printHexString("OCSP ## SERIAL NUMBER:", &cert->serialNumber);
 
252
}
 
253
#endif
75
254
 
76
255
SECStatus
77
256
SEC_RegisterDefaultHttpClient(const SEC_HttpClientFcn *fcnTable)
78
257
{
79
 
    if (!OCSP_Global.lock) {
 
258
    if (!OCSP_Global.monitor) {
80
259
      PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
81
260
      return SECFailure;
82
261
    }
83
262
    
84
 
    PR_Lock(OCSP_Global.lock);
 
263
    PR_EnterMonitor(OCSP_Global.monitor);
85
264
    OCSP_Global.defaultHttpClientFcn = fcnTable;
86
 
    PR_Unlock(OCSP_Global.lock);
 
265
    PR_ExitMonitor(OCSP_Global.monitor);
87
266
    
88
267
    return SECSuccess;
89
268
}
90
269
 
 
270
static PLHashNumber PR_CALLBACK
 
271
ocsp_CacheKeyHashFunction(const void *key)
 
272
{
 
273
    CERTOCSPCertID *cid = (CERTOCSPCertID *)key;
 
274
    PLHashNumber hash = 0;
 
275
    unsigned int i;
 
276
    unsigned char *walk;
 
277
  
 
278
    /* a very simple hash calculation for the initial coding phase */
 
279
    walk = (unsigned char*)cid->issuerNameHash.data;
 
280
    for (i=0; i < cid->issuerNameHash.len; ++i, ++walk) {
 
281
        hash += *walk;
 
282
    }
 
283
    walk = (unsigned char*)cid->issuerKeyHash.data;
 
284
    for (i=0; i < cid->issuerKeyHash.len; ++i, ++walk) {
 
285
        hash += *walk;
 
286
    }
 
287
    walk = (unsigned char*)cid->serialNumber.data;
 
288
    for (i=0; i < cid->serialNumber.len; ++i, ++walk) {
 
289
        hash += *walk;
 
290
    }
 
291
    return hash;
 
292
}
 
293
 
 
294
static PRIntn PR_CALLBACK
 
295
ocsp_CacheKeyCompareFunction(const void *v1, const void *v2)
 
296
{
 
297
    CERTOCSPCertID *cid1 = (CERTOCSPCertID *)v1;
 
298
    CERTOCSPCertID *cid2 = (CERTOCSPCertID *)v2;
 
299
  
 
300
    return (SECEqual == SECITEM_CompareItem(&cid1->issuerNameHash, 
 
301
                                            &cid2->issuerNameHash)
 
302
            && SECEqual == SECITEM_CompareItem(&cid1->issuerKeyHash, 
 
303
                                               &cid2->issuerKeyHash)
 
304
            && SECEqual == SECITEM_CompareItem(&cid1->serialNumber, 
 
305
                                               &cid2->serialNumber));
 
306
}
 
307
 
 
308
static SECStatus
 
309
ocsp_CopyRevokedInfo(PRArenaPool *arena, ocspCertStatus *dest, 
 
310
                     ocspRevokedInfo *src)
 
311
{
 
312
    SECStatus rv = SECFailure;
 
313
    void *mark;
 
314
  
 
315
    mark = PORT_ArenaMark(arena);
 
316
  
 
317
    dest->certStatusInfo.revokedInfo = 
 
318
        (ocspRevokedInfo *) PORT_ArenaZAlloc(arena, sizeof(ocspRevokedInfo));
 
319
    if (!dest->certStatusInfo.revokedInfo) {
 
320
        goto loser;
 
321
    }
 
322
  
 
323
    rv = SECITEM_CopyItem(arena, 
 
324
                          &dest->certStatusInfo.revokedInfo->revocationTime, 
 
325
                          &src->revocationTime);
 
326
    if (rv != SECSuccess) {
 
327
        goto loser;
 
328
    }
 
329
  
 
330
    if (src->revocationReason) {
 
331
        dest->certStatusInfo.revokedInfo->revocationReason = 
 
332
            SECITEM_ArenaDupItem(arena, src->revocationReason);
 
333
        if (!dest->certStatusInfo.revokedInfo->revocationReason) {
 
334
            goto loser;
 
335
        }
 
336
    }  else {
 
337
        dest->certStatusInfo.revokedInfo->revocationReason = NULL;
 
338
    }
 
339
  
 
340
    PORT_ArenaUnmark(arena, mark);
 
341
    return SECSuccess;
 
342
 
 
343
loser:
 
344
    PORT_ArenaRelease(arena, mark);
 
345
    return SECFailure;
 
346
}
 
347
 
 
348
static SECStatus
 
349
ocsp_CopyCertStatus(PRArenaPool *arena, ocspCertStatus *dest, 
 
350
                    ocspCertStatus*src)
 
351
{
 
352
    SECStatus rv = SECFailure;
 
353
    dest->certStatusType = src->certStatusType;
 
354
  
 
355
    switch (src->certStatusType) {
 
356
    case ocspCertStatus_good:
 
357
        dest->certStatusInfo.goodInfo = 
 
358
            SECITEM_ArenaDupItem(arena, src->certStatusInfo.goodInfo);
 
359
        if (dest->certStatusInfo.goodInfo != NULL) {
 
360
            rv = SECSuccess;
 
361
        }
 
362
        break;
 
363
    case ocspCertStatus_revoked:
 
364
        rv = ocsp_CopyRevokedInfo(arena, dest, 
 
365
                                  src->certStatusInfo.revokedInfo);
 
366
        break;
 
367
    case ocspCertStatus_unknown:
 
368
        dest->certStatusInfo.unknownInfo = 
 
369
            SECITEM_ArenaDupItem(arena, src->certStatusInfo.unknownInfo);
 
370
        if (dest->certStatusInfo.unknownInfo != NULL) {
 
371
            rv = SECSuccess;
 
372
        }
 
373
        break;
 
374
    case ocspCertStatus_other:
 
375
    default:
 
376
        PORT_Assert(src->certStatusType == ocspCertStatus_other);
 
377
        dest->certStatusInfo.otherInfo = 
 
378
            SECITEM_ArenaDupItem(arena, src->certStatusInfo.otherInfo);
 
379
        if (dest->certStatusInfo.otherInfo != NULL) {
 
380
            rv = SECSuccess;
 
381
        }
 
382
        break;
 
383
    }
 
384
    return rv;
 
385
}
 
386
 
 
387
static void
 
388
ocsp_AddCacheItemToLinkedList(OCSPCacheData *cache, OCSPCacheItem *new_most_recent)
 
389
{
 
390
    PR_EnterMonitor(OCSP_Global.monitor);
 
391
 
 
392
    if (!cache->LRUitem) {
 
393
        cache->LRUitem = new_most_recent;
 
394
    }
 
395
    new_most_recent->lessRecent = cache->MRUitem;
 
396
    new_most_recent->moreRecent = NULL;
 
397
 
 
398
    if (cache->MRUitem) {
 
399
        cache->MRUitem->moreRecent = new_most_recent;
 
400
    }
 
401
    cache->MRUitem = new_most_recent;
 
402
 
 
403
    PR_ExitMonitor(OCSP_Global.monitor);
 
404
}
 
405
 
 
406
static void
 
407
ocsp_RemoveCacheItemFromLinkedList(OCSPCacheData *cache, OCSPCacheItem *item)
 
408
{
 
409
    PR_EnterMonitor(OCSP_Global.monitor);
 
410
 
 
411
    if (!item->lessRecent && !item->moreRecent) {
 
412
        /*
 
413
         * Fail gracefully on attempts to remove an item from the list,
 
414
         * which is currently not part of the list.
 
415
         * But check for the edge case it is the single entry in the list.
 
416
         */
 
417
        if (item == cache->LRUitem &&
 
418
            item == cache->MRUitem) {
 
419
            /* remove the single entry */
 
420
            PORT_Assert(cache->numberOfEntries == 1);
 
421
            PORT_Assert(item->moreRecent == NULL);
 
422
            cache->MRUitem = NULL;
 
423
            cache->LRUitem = NULL;
 
424
        }
 
425
        PR_ExitMonitor(OCSP_Global.monitor);
 
426
        return;
 
427
    }
 
428
 
 
429
    PORT_Assert(cache->numberOfEntries > 1);
 
430
  
 
431
    if (item == cache->LRUitem) {
 
432
        PORT_Assert(item != cache->MRUitem);
 
433
        PORT_Assert(item->lessRecent == NULL);
 
434
        PORT_Assert(item->moreRecent != NULL);
 
435
        PORT_Assert(item->moreRecent->lessRecent == item);
 
436
        cache->LRUitem = item->moreRecent;
 
437
        cache->LRUitem->lessRecent = NULL;
 
438
    }
 
439
    else if (item == cache->MRUitem) {
 
440
        PORT_Assert(item->moreRecent == NULL);
 
441
        PORT_Assert(item->lessRecent != NULL);
 
442
        PORT_Assert(item->lessRecent->moreRecent == item);
 
443
        cache->MRUitem = item->lessRecent;
 
444
        cache->MRUitem->moreRecent = NULL;
 
445
    } else {
 
446
        /* remove an entry in the middle of the list */
 
447
        PORT_Assert(item->moreRecent != NULL);
 
448
        PORT_Assert(item->lessRecent != NULL);
 
449
        PORT_Assert(item->lessRecent->moreRecent == item);
 
450
        PORT_Assert(item->moreRecent->lessRecent == item);
 
451
        item->moreRecent->lessRecent = item->lessRecent;
 
452
        item->lessRecent->moreRecent = item->moreRecent;
 
453
    }
 
454
 
 
455
    item->lessRecent = NULL;
 
456
    item->moreRecent = NULL;
 
457
 
 
458
    PR_ExitMonitor(OCSP_Global.monitor);
 
459
}
 
460
 
 
461
static void
 
462
ocsp_MakeCacheEntryMostRecent(OCSPCacheData *cache, OCSPCacheItem *new_most_recent)
 
463
{
 
464
    OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent THREADID %p\n", 
 
465
                PR_GetCurrentThread()));
 
466
    PR_EnterMonitor(OCSP_Global.monitor);
 
467
    if (cache->MRUitem == new_most_recent) {
 
468
        OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent ALREADY MOST\n"));
 
469
        PR_ExitMonitor(OCSP_Global.monitor);
 
470
        return;
 
471
    }
 
472
    OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent NEW entry\n"));
 
473
    ocsp_RemoveCacheItemFromLinkedList(cache, new_most_recent);
 
474
    ocsp_AddCacheItemToLinkedList(cache, new_most_recent);
 
475
    PR_ExitMonitor(OCSP_Global.monitor);
 
476
}
 
477
 
 
478
static PRBool
 
479
ocsp_IsCacheDisabled()
 
480
{
 
481
    /* 
 
482
     * maxCacheEntries == 0 means unlimited cache entries
 
483
     * maxCacheEntries  < 0 means cache is disabled
 
484
     */
 
485
    PRBool retval;
 
486
    PR_EnterMonitor(OCSP_Global.monitor);
 
487
    retval = (OCSP_Global.maxCacheEntries < 0);
 
488
    PR_ExitMonitor(OCSP_Global.monitor);
 
489
    return retval;
 
490
}
 
491
 
 
492
static OCSPCacheItem *
 
493
ocsp_FindCacheEntry(OCSPCacheData *cache, CERTOCSPCertID *certID)
 
494
{
 
495
    OCSPCacheItem *found_ocsp_item = NULL;
 
496
    OCSP_TRACE(("OCSP ocsp_FindCacheEntry\n"));
 
497
    PR_EnterMonitor(OCSP_Global.monitor);
 
498
    if (ocsp_IsCacheDisabled())
 
499
        goto loser;
 
500
  
 
501
    found_ocsp_item = (OCSPCacheItem *)PL_HashTableLookup(
 
502
                          cache->entries, certID);
 
503
    if (!found_ocsp_item)
 
504
        goto loser;
 
505
  
 
506
    OCSP_TRACE(("OCSP ocsp_FindCacheEntry FOUND!\n"));
 
507
    ocsp_MakeCacheEntryMostRecent(cache, found_ocsp_item);
 
508
 
 
509
loser:
 
510
    PR_ExitMonitor(OCSP_Global.monitor);
 
511
    return found_ocsp_item;
 
512
}
 
513
 
 
514
static void
 
515
ocsp_FreeCacheItem(OCSPCacheItem *item)
 
516
{
 
517
    OCSP_TRACE(("OCSP ocsp_FreeCacheItem\n"));
 
518
    if (item->certStatusArena) {
 
519
        PORT_FreeArena(item->certStatusArena, PR_FALSE);
 
520
    }
 
521
    if (item->certID->poolp) {
 
522
        /* freeing this poolp arena will also free item */
 
523
        PORT_FreeArena(item->certID->poolp, PR_FALSE);
 
524
    }
 
525
}
 
526
 
 
527
static void
 
528
ocsp_RemoveCacheItem(OCSPCacheData *cache, OCSPCacheItem *item)
 
529
{
 
530
    /* The item we're removing could be either the least recently used item,
 
531
     * or it could be an item that couldn't get updated with newer status info
 
532
     * because of an allocation failure, or it could get removed because we're 
 
533
     * cleaning up.
 
534
     */
 
535
    PRBool couldRemoveFromHashTable;
 
536
    OCSP_TRACE(("OCSP ocsp_RemoveCacheItem, THREADID %p\n", PR_GetCurrentThread()));
 
537
    PR_EnterMonitor(OCSP_Global.monitor);
 
538
 
 
539
    ocsp_RemoveCacheItemFromLinkedList(cache, item);
 
540
    couldRemoveFromHashTable = PL_HashTableRemove(cache->entries, 
 
541
                                                  item->certID);
 
542
    PORT_Assert(couldRemoveFromHashTable);
 
543
    --cache->numberOfEntries;
 
544
    ocsp_FreeCacheItem(item);
 
545
    PR_ExitMonitor(OCSP_Global.monitor);
 
546
}
 
547
 
 
548
static void
 
549
ocsp_CheckCacheSize(OCSPCacheData *cache)
 
550
{
 
551
    OCSP_TRACE(("OCSP ocsp_CheckCacheSize\n"));
 
552
    PR_EnterMonitor(OCSP_Global.monitor);
 
553
    if (OCSP_Global.maxCacheEntries <= 0) /* disabled or unlimited */
 
554
        return;
 
555
    while (cache->numberOfEntries > OCSP_Global.maxCacheEntries) {
 
556
        ocsp_RemoveCacheItem(cache, cache->LRUitem);
 
557
    }
 
558
    PR_ExitMonitor(OCSP_Global.monitor);
 
559
}
 
560
 
 
561
SECStatus
 
562
CERT_ClearOCSPCache()
 
563
{
 
564
    OCSP_TRACE(("OCSP CERT_ClearOCSPCache\n"));
 
565
    PR_EnterMonitor(OCSP_Global.monitor);
 
566
    while (OCSP_Global.cache.numberOfEntries > 0) {
 
567
        ocsp_RemoveCacheItem(&OCSP_Global.cache, 
 
568
                             OCSP_Global.cache.LRUitem);
 
569
    }
 
570
    PR_ExitMonitor(OCSP_Global.monitor);
 
571
    return SECSuccess;
 
572
}
 
573
 
 
574
static SECStatus
 
575
ocsp_CreateCacheItemAndConsumeCertID(OCSPCacheData *cache,
 
576
                                     CERTOCSPCertID *certID, 
 
577
                                     OCSPCacheItem **pCacheItem)
 
578
{
 
579
    PRArenaPool *arena;
 
580
    void *mark;
 
581
    PLHashEntry *new_hash_entry;
 
582
    OCSPCacheItem *item;
 
583
  
 
584
    PORT_Assert(pCacheItem != NULL);
 
585
    *pCacheItem = NULL;
 
586
 
 
587
    PR_EnterMonitor(OCSP_Global.monitor);
 
588
    arena = certID->poolp;
 
589
    mark = PORT_ArenaMark(arena);
 
590
  
 
591
    /* ZAlloc will init all Bools to False and all Pointers to NULL */
 
592
    item = (OCSPCacheItem *)PORT_ArenaZAlloc(certID->poolp, 
 
593
                                             sizeof(OCSPCacheItem));
 
594
    if (!item) {
 
595
        goto loser; 
 
596
    }
 
597
    item->certID = certID;
 
598
    new_hash_entry = PL_HashTableAdd(cache->entries, item->certID, 
 
599
                                     item);
 
600
    if (!new_hash_entry) {
 
601
        goto loser;
 
602
    }
 
603
    ++cache->numberOfEntries;
 
604
    PORT_ArenaUnmark(arena, mark);
 
605
    ocsp_AddCacheItemToLinkedList(cache, item);
 
606
    *pCacheItem = item;
 
607
 
 
608
    PR_ExitMonitor(OCSP_Global.monitor);
 
609
    return SECSuccess;
 
610
  
 
611
loser:
 
612
    PORT_ArenaRelease(arena, mark);
 
613
    PR_ExitMonitor(OCSP_Global.monitor);
 
614
    return SECFailure;
 
615
}
 
616
 
 
617
static SECStatus
 
618
ocsp_SetCacheItemResponse(OCSPCacheItem *item,
 
619
                          const CERTOCSPSingleResponse *response)
 
620
{
 
621
    if (item->certStatusArena) {
 
622
        PORT_FreeArena(item->certStatusArena, PR_FALSE);
 
623
        item->certStatusArena = NULL;
 
624
    }
 
625
    item->haveThisUpdate = item->haveNextUpdate = PR_FALSE;
 
626
    if (response) {
 
627
        SECStatus rv;
 
628
        item->certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
629
        if (item->certStatusArena == NULL) {
 
630
            return SECFailure;
 
631
        }
 
632
        rv = ocsp_CopyCertStatus(item->certStatusArena, &item->certStatus, 
 
633
                                 response->certStatus);
 
634
        if (rv != SECSuccess) {
 
635
            PORT_FreeArena(item->certStatusArena, PR_FALSE);
 
636
            item->certStatusArena = NULL;
 
637
            return rv;
 
638
        }
 
639
        rv = DER_GeneralizedTimeToTime(&item->thisUpdate, 
 
640
                                       &response->thisUpdate);
 
641
        item->haveThisUpdate = (rv == SECSuccess);
 
642
        if (response->nextUpdate) {
 
643
            rv = DER_GeneralizedTimeToTime(&item->nextUpdate, 
 
644
                                           response->nextUpdate);
 
645
            item->haveNextUpdate = (rv == SECSuccess);
 
646
        } else {
 
647
            item->haveNextUpdate = PR_FALSE;
 
648
        }
 
649
    }
 
650
    return SECSuccess;
 
651
}
 
652
 
 
653
static void
 
654
ocsp_FreshenCacheItemNextFetchAttemptTime(OCSPCacheItem *cacheItem)
 
655
{
 
656
    PRTime now;
 
657
    PRTime earliestAllowedNextFetchAttemptTime;
 
658
    PRTime latestTimeWhenResponseIsConsideredFresh;
 
659
  
 
660
    OCSP_TRACE(("OCSP ocsp_FreshenCacheItemNextFetchAttemptTime\n"));
 
661
 
 
662
    PR_EnterMonitor(OCSP_Global.monitor);
 
663
  
 
664
    now = PR_Now();
 
665
    OCSP_TRACE_TIME("now:", now);
 
666
  
 
667
    if (cacheItem->haveThisUpdate) {
 
668
        OCSP_TRACE_TIME("thisUpdate:", cacheItem->thisUpdate);
 
669
        latestTimeWhenResponseIsConsideredFresh = cacheItem->thisUpdate +
 
670
            OCSP_Global.maximumSecondsToNextFetchAttempt * 
 
671
                MICROSECONDS_PER_SECOND;
 
672
        OCSP_TRACE_TIME("latestTimeWhenResponseIsConsideredFresh:", 
 
673
                        latestTimeWhenResponseIsConsideredFresh);
 
674
    } else {
 
675
        latestTimeWhenResponseIsConsideredFresh = now +
 
676
            OCSP_Global.minimumSecondsToNextFetchAttempt *
 
677
                MICROSECONDS_PER_SECOND;
 
678
        OCSP_TRACE_TIME("no thisUpdate, "
 
679
                        "latestTimeWhenResponseIsConsideredFresh:", 
 
680
                        latestTimeWhenResponseIsConsideredFresh);
 
681
    }
 
682
  
 
683
    if (cacheItem->haveNextUpdate) {
 
684
        OCSP_TRACE_TIME("have nextUpdate:", cacheItem->thisUpdate);
 
685
    }
 
686
  
 
687
    if (cacheItem->haveNextUpdate &&
 
688
        cacheItem->nextUpdate < latestTimeWhenResponseIsConsideredFresh) {
 
689
        latestTimeWhenResponseIsConsideredFresh = cacheItem->nextUpdate;
 
690
        OCSP_TRACE_TIME("nextUpdate is smaller than latestFresh, setting "
 
691
                        "latestTimeWhenResponseIsConsideredFresh:", 
 
692
                        latestTimeWhenResponseIsConsideredFresh);
 
693
    }
 
694
  
 
695
    earliestAllowedNextFetchAttemptTime = now +
 
696
        OCSP_Global.minimumSecondsToNextFetchAttempt * 
 
697
            MICROSECONDS_PER_SECOND;
 
698
    OCSP_TRACE_TIME("earliestAllowedNextFetchAttemptTime:", 
 
699
                    earliestAllowedNextFetchAttemptTime);
 
700
  
 
701
    if (latestTimeWhenResponseIsConsideredFresh < 
 
702
        earliestAllowedNextFetchAttemptTime) {
 
703
        latestTimeWhenResponseIsConsideredFresh = 
 
704
            earliestAllowedNextFetchAttemptTime;
 
705
        OCSP_TRACE_TIME("latest < earliest, setting latest to:", 
 
706
                        latestTimeWhenResponseIsConsideredFresh);
 
707
    }
 
708
  
 
709
    cacheItem->nextFetchAttemptTime = 
 
710
        latestTimeWhenResponseIsConsideredFresh;
 
711
    OCSP_TRACE_TIME("nextFetchAttemptTime", 
 
712
        latestTimeWhenResponseIsConsideredFresh);
 
713
 
 
714
    PR_ExitMonitor(OCSP_Global.monitor);
 
715
}
 
716
 
 
717
static PRBool
 
718
ocsp_IsCacheItemFresh(OCSPCacheItem *cacheItem)
 
719
{
 
720
    PRTime now;
 
721
    PRBool retval;
 
722
 
 
723
    PR_EnterMonitor(OCSP_Global.monitor);
 
724
    now = PR_Now();
 
725
    retval = (cacheItem->nextFetchAttemptTime > now);
 
726
    OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", retval));
 
727
    PR_ExitMonitor(OCSP_Global.monitor);
 
728
    return retval;
 
729
}
 
730
 
 
731
/*
 
732
 * Status in *certIDWasConsumed will always be correct, regardless of 
 
733
 * return value.
 
734
 */
 
735
static SECStatus
 
736
ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache, 
 
737
                              CERTOCSPCertID *certID,
 
738
                              CERTOCSPSingleResponse *single,
 
739
                              PRBool *certIDWasConsumed)
 
740
{
 
741
    SECStatus rv;
 
742
    OCSPCacheItem *cacheItem;
 
743
    OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n"));
 
744
  
 
745
    if (!certIDWasConsumed) {
 
746
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
747
        return SECFailure;
 
748
    }
 
749
    *certIDWasConsumed = PR_FALSE;
 
750
  
 
751
    PR_EnterMonitor(OCSP_Global.monitor);
 
752
    PORT_Assert(OCSP_Global.maxCacheEntries >= 0);
 
753
  
 
754
    cacheItem = ocsp_FindCacheEntry(cache, certID);
 
755
    if (!cacheItem) {
 
756
        rv = ocsp_CreateCacheItemAndConsumeCertID(cache, certID, 
 
757
                                                  &cacheItem);
 
758
        if (rv != SECSuccess) {
 
759
            PR_ExitMonitor(OCSP_Global.monitor);
 
760
            return rv;
 
761
        }
 
762
        *certIDWasConsumed = PR_TRUE;
 
763
    }
 
764
    if (single) {
 
765
        rv = ocsp_SetCacheItemResponse(cacheItem, single);
 
766
        if (rv != SECSuccess) {
 
767
            ocsp_RemoveCacheItem(cache, cacheItem);
 
768
            PR_ExitMonitor(OCSP_Global.monitor);
 
769
            return rv;
 
770
        }
 
771
    }
 
772
    ocsp_FreshenCacheItemNextFetchAttemptTime(cacheItem);
 
773
    ocsp_CheckCacheSize(cache);
 
774
 
 
775
    PR_ExitMonitor(OCSP_Global.monitor);
 
776
    return SECSuccess;
 
777
}
 
778
 
 
779
extern SECStatus
 
780
CERT_SetOCSPFailureMode(SEC_OcspFailureMode ocspFailureMode)
 
781
{
 
782
    switch (ocspFailureMode) {
 
783
    case ocspMode_FailureIsVerificationFailure:
 
784
    case ocspMode_FailureIsNotAVerificationFailure:
 
785
        break;
 
786
    default:
 
787
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
788
        return SECFailure;
 
789
    }
 
790
 
 
791
    PR_EnterMonitor(OCSP_Global.monitor);
 
792
    OCSP_Global.ocspFailureMode = ocspFailureMode;
 
793
    PR_ExitMonitor(OCSP_Global.monitor);
 
794
    return SECSuccess;
 
795
}
 
796
 
 
797
SECStatus
 
798
CERT_OCSPCacheSettings(PRInt32 maxCacheEntries,
 
799
                       PRUint32 minimumSecondsToNextFetchAttempt,
 
800
                       PRUint32 maximumSecondsToNextFetchAttempt)
 
801
{
 
802
    if (minimumSecondsToNextFetchAttempt > maximumSecondsToNextFetchAttempt
 
803
        || maxCacheEntries < -1) {
 
804
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
805
        return SECFailure;
 
806
    }
 
807
  
 
808
    PR_EnterMonitor(OCSP_Global.monitor);
 
809
  
 
810
    if (maxCacheEntries < 0) {
 
811
        OCSP_Global.maxCacheEntries = -1; /* disable cache */
 
812
    } else if (maxCacheEntries == 0) {
 
813
        OCSP_Global.maxCacheEntries = 0; /* unlimited cache entries */
 
814
    } else {
 
815
        OCSP_Global.maxCacheEntries = maxCacheEntries;
 
816
    }
 
817
  
 
818
    if (minimumSecondsToNextFetchAttempt < 
 
819
            OCSP_Global.minimumSecondsToNextFetchAttempt
 
820
        || maximumSecondsToNextFetchAttempt < 
 
821
            OCSP_Global.maximumSecondsToNextFetchAttempt) {
 
822
        /*
 
823
         * Ensure our existing cache entries are not used longer than the 
 
824
         * new settings allow, we're lazy and just clear the cache
 
825
         */
 
826
        CERT_ClearOCSPCache();
 
827
    }
 
828
  
 
829
    OCSP_Global.minimumSecondsToNextFetchAttempt = 
 
830
        minimumSecondsToNextFetchAttempt;
 
831
    OCSP_Global.maximumSecondsToNextFetchAttempt = 
 
832
        maximumSecondsToNextFetchAttempt;
 
833
    ocsp_CheckCacheSize(&OCSP_Global.cache);
 
834
  
 
835
    PR_ExitMonitor(OCSP_Global.monitor);
 
836
    return SECSuccess;
 
837
}
 
838
 
91
839
/* this function is called at NSS initialization time */
92
 
SECStatus InitOCSPGlobal(void)
93
 
{
94
 
  if (OCSP_Global.lock != NULL) {
95
 
    /* already initialized */
 
840
SECStatus OCSP_InitGlobal(void)
 
841
{
 
842
    SECStatus rv = SECFailure;
 
843
 
 
844
    if (OCSP_Global.monitor == NULL) {
 
845
        OCSP_Global.monitor = PR_NewMonitor();
 
846
    }
 
847
    if (!OCSP_Global.monitor)
 
848
        return SECFailure;
 
849
 
 
850
    PR_EnterMonitor(OCSP_Global.monitor);
 
851
    if (!OCSP_Global.cache.entries) {
 
852
        OCSP_Global.cache.entries = 
 
853
            PL_NewHashTable(0, 
 
854
                            ocsp_CacheKeyHashFunction, 
 
855
                            ocsp_CacheKeyCompareFunction, 
 
856
                            PL_CompareValues, 
 
857
                            NULL, 
 
858
                            NULL);
 
859
        OCSP_Global.ocspFailureMode = ocspMode_FailureIsVerificationFailure;
 
860
        OCSP_Global.cache.numberOfEntries = 0;
 
861
        OCSP_Global.cache.MRUitem = NULL;
 
862
        OCSP_Global.cache.LRUitem = NULL;
 
863
    } else {
 
864
        /*
 
865
         * NSS might call this function twice while attempting to init.
 
866
         * But it's not allowed to call this again after any activity.
 
867
         */
 
868
        PORT_Assert(OCSP_Global.cache.numberOfEntries == 0);
 
869
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
870
    }
 
871
    if (OCSP_Global.cache.entries)
 
872
        rv = SECSuccess;
 
873
    PR_ExitMonitor(OCSP_Global.monitor);
 
874
    return rv;
 
875
}
 
876
 
 
877
SECStatus OCSP_ShutdownCache(void)
 
878
{
 
879
    if (!OCSP_Global.monitor)
 
880
        return SECSuccess;
 
881
 
 
882
    PR_EnterMonitor(OCSP_Global.monitor);
 
883
    if (OCSP_Global.cache.entries) {
 
884
        CERT_ClearOCSPCache();
 
885
        PL_HashTableDestroy(OCSP_Global.cache.entries);
 
886
        OCSP_Global.cache.entries = NULL;
 
887
    }
 
888
    PORT_Assert(OCSP_Global.cache.numberOfEntries == 0);
 
889
    OCSP_Global.cache.MRUitem = NULL;
 
890
    OCSP_Global.cache.LRUitem = NULL;
 
891
    PR_ExitMonitor(OCSP_Global.monitor);
96
892
    return SECSuccess;
97
 
  }
98
 
  
99
 
  OCSP_Global.lock = PR_NewLock();
100
 
  
101
 
  return (OCSP_Global.lock) ? SECSuccess : SECFailure;
102
893
}
103
894
 
104
895
/*
109
900
{
110
901
    const SEC_HttpClientFcn *retval;
111
902
 
112
 
    if (!OCSP_Global.lock) {
 
903
    if (!OCSP_Global.monitor) {
113
904
      PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
114
905
      return NULL;
115
906
    }
116
907
 
117
 
    PR_Lock(OCSP_Global.lock);
 
908
    PR_EnterMonitor(OCSP_Global.monitor);
118
909
    retval = OCSP_Global.defaultHttpClientFcn;
119
 
    PR_Unlock(OCSP_Global.lock);
 
910
    PR_ExitMonitor(OCSP_Global.monitor);
120
911
    
121
912
    return retval;
122
913
}
353
1144
static const SEC_ASN1Template ocsp_BasicOCSPResponseTemplate[] = {
354
1145
    { SEC_ASN1_SEQUENCE,
355
1146
        0, NULL, sizeof(ocspBasicOCSPResponse) },
 
1147
    { SEC_ASN1_ANY | SEC_ASN1_SAVE,
 
1148
        offsetof(ocspBasicOCSPResponse, tbsResponseDataDER) },
356
1149
    { SEC_ASN1_POINTER,
357
1150
        offsetof(ocspBasicOCSPResponse, tbsResponseData),
358
1151
        ocsp_ResponseDataTemplate },
431
1224
        offsetof(ocspResponderID, responderIDValue.other) }
432
1225
};
433
1226
 
 
1227
/* Decode choice container, but leave x509 name object encoded */
 
1228
static const SEC_ASN1Template ocsp_ResponderIDDerNameTemplate[] = {
 
1229
    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
 
1230
        0, SEC_AnyTemplate }
 
1231
};
 
1232
 
434
1233
/*
435
1234
 * SingleResponse       ::=     SEQUENCE {
436
1235
 *      certID                  CertID,
669
1468
    return SECFailure;
670
1469
}
671
1470
 
 
1471
/*
 
1472
 * Digest data using the specified algorithm.
 
1473
 * The necessary storage for the digest data is allocated.  If "fill" is
 
1474
 * non-null, the data is put there, otherwise a SECItem is allocated.
 
1475
 * Allocation from "arena" if it is non-null, heap otherwise.  Any problem
 
1476
 * results in a NULL being returned (and an appropriate error set).
 
1477
 */
 
1478
 
 
1479
static SECItem *
 
1480
ocsp_DigestValue(PRArenaPool *arena, SECOidTag digestAlg, 
 
1481
                 SECItem *fill, const SECItem *src)
 
1482
{
 
1483
    const SECHashObject *digestObject;
 
1484
    SECItem *result = NULL;
 
1485
    void *mark = NULL;
 
1486
    void *digestBuff = NULL;
 
1487
 
 
1488
    if ( arena != NULL ) {
 
1489
        mark = PORT_ArenaMark(arena);
 
1490
    }
 
1491
 
 
1492
    digestObject = HASH_GetHashObjectByOidTag(digestAlg);
 
1493
    if ( digestObject == NULL ) {
 
1494
        goto loser;
 
1495
    }
 
1496
 
 
1497
    if (fill == NULL || fill->data == NULL) {
 
1498
        result = SECITEM_AllocItem(arena, fill, digestObject->length);
 
1499
        if ( result == NULL ) {
 
1500
           goto loser;
 
1501
        }
 
1502
        digestBuff = result->data;
 
1503
    } else {
 
1504
        if (fill->len < digestObject->length) {
 
1505
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
1506
            goto loser;
 
1507
        }
 
1508
        digestBuff = fill->data;
 
1509
    }
 
1510
 
 
1511
    if (PK11_HashBuf(digestAlg, digestBuff,
 
1512
                     src->data, src->len) != SECSuccess) {
 
1513
        goto loser;
 
1514
    }
 
1515
 
 
1516
    if ( arena != NULL ) {
 
1517
        PORT_ArenaUnmark(arena, mark);
 
1518
    }
 
1519
 
 
1520
    if (result == NULL) {
 
1521
        result = fill;
 
1522
    }
 
1523
    return result;
 
1524
 
 
1525
loser:
 
1526
    if (arena != NULL) {
 
1527
        PORT_ArenaRelease(arena, mark);
 
1528
    } else {
 
1529
        if (result != NULL) {
 
1530
            SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE);
 
1531
        }
 
1532
    }
 
1533
    return(NULL);
 
1534
}
 
1535
 
 
1536
/*
 
1537
 * Digest the cert's subject public key using the specified algorithm.
 
1538
 * The necessary storage for the digest data is allocated.  If "fill" is
 
1539
 * non-null, the data is put there, otherwise a SECItem is allocated.
 
1540
 * Allocation from "arena" if it is non-null, heap otherwise.  Any problem
 
1541
 * results in a NULL being returned (and an appropriate error set).
 
1542
 */
 
1543
SECItem *
 
1544
cert_GetSPKIDigest(PRArenaPool *arena, const CERTCertificate *cert,
 
1545
                           SECOidTag digestAlg, SECItem *fill)
 
1546
{
 
1547
    SECItem spk;
 
1548
 
 
1549
    /*
 
1550
     * Copy just the length and data pointer (nothing needs to be freed)
 
1551
     * of the subject public key so we can convert the length from bits
 
1552
     * to bytes, which is what the digest function expects.
 
1553
     */
 
1554
    spk = cert->subjectPublicKeyInfo.subjectPublicKey;
 
1555
    DER_ConvertBitString(&spk);
 
1556
 
 
1557
    return ocsp_DigestValue(arena, digestAlg, fill, &spk);
 
1558
}
 
1559
 
 
1560
/*
 
1561
 * Digest the cert's subject name using the specified algorithm.
 
1562
 */
 
1563
static SECItem *
 
1564
cert_GetSubjectNameDigest(PRArenaPool *arena, const CERTCertificate *cert,
 
1565
                           SECOidTag digestAlg, SECItem *fill)
 
1566
{
 
1567
    SECItem name;
 
1568
 
 
1569
    /*
 
1570
     * Copy just the length and data pointer (nothing needs to be freed)
 
1571
     * of the subject name
 
1572
     */
 
1573
    name = cert->derSubject;
 
1574
 
 
1575
    return ocsp_DigestValue(arena, digestAlg, fill, &name);
 
1576
}
672
1577
 
673
1578
/*
674
1579
 * Create and fill-in a CertID.  This function fills in the hash values
707
1612
        goto loser;
708
1613
    }
709
1614
 
710
 
    tempItem = SEC_ASN1EncodeItem(NULL, NULL, &issuerCert->subject,
711
 
                                  CERT_NameTemplate);
712
 
    if (tempItem == NULL) {
713
 
        goto loser;
714
 
    }
715
 
 
716
 
    if (SECITEM_AllocItem(arena, &(certID->issuerNameHash),
717
 
                          SHA1_LENGTH) == NULL) {
718
 
        goto loser;
719
 
    }
720
 
    rv = PK11_HashBuf(SEC_OID_SHA1, certID->issuerNameHash.data,
721
 
                      tempItem->data, tempItem->len);
722
 
    if (rv != SECSuccess) {
723
 
        goto loser; 
 
1615
    if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_SHA1,
 
1616
                                  &(certID->issuerNameHash)) == NULL) {
 
1617
        goto loser;
724
1618
    }
725
1619
    certID->issuerSHA1NameHash.data = certID->issuerNameHash.data;
726
1620
    certID->issuerSHA1NameHash.len = certID->issuerNameHash.len;
727
 
    /* cache the other two hash algorithms as well */
728
 
    if (SECITEM_AllocItem(arena, &(certID->issuerMD5NameHash),
729
 
                          MD5_LENGTH) == NULL) {
730
 
        goto loser;
731
 
    }
732
 
    rv = PK11_HashBuf(SEC_OID_MD5, certID->issuerMD5NameHash.data,
733
 
                      tempItem->data, tempItem->len);
734
 
    if (rv != SECSuccess) {
735
 
        goto loser; 
736
 
    }
737
 
    if (SECITEM_AllocItem(arena, &(certID->issuerMD2NameHash),
738
 
                          MD2_LENGTH) == NULL) {
739
 
        goto loser;
740
 
    }
741
 
    rv = PK11_HashBuf(SEC_OID_MD2, certID->issuerMD2NameHash.data,
742
 
                      tempItem->data, tempItem->len);
743
 
    if (rv != SECSuccess) {
744
 
        goto loser; 
745
 
    }
746
 
 
747
 
    SECITEM_FreeItem(tempItem, PR_TRUE);
748
 
    tempItem = NULL;
749
 
 
750
 
    if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_SHA1,
 
1621
 
 
1622
    if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD5,
 
1623
                                  &(certID->issuerMD5NameHash)) == NULL) {
 
1624
        goto loser;
 
1625
    }
 
1626
 
 
1627
    if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD2,
 
1628
                                  &(certID->issuerMD2NameHash)) == NULL) {
 
1629
        goto loser;
 
1630
    }
 
1631
 
 
1632
    if (cert_GetSPKIDigest(arena, issuerCert, SEC_OID_SHA1,
751
1633
                                   &(certID->issuerKeyHash)) == NULL) {
752
1634
        goto loser;
753
1635
    }
754
1636
    certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data;
755
1637
    certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len;
756
1638
    /* cache the other two hash algorithms as well */
757
 
    if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_MD5,
 
1639
    if (cert_GetSPKIDigest(arena, issuerCert, SEC_OID_MD5,
758
1640
                                   &(certID->issuerMD5KeyHash)) == NULL) {
759
1641
        goto loser;
760
1642
    }
761
 
    if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_MD2,
 
1643
    if (cert_GetSPKIDigest(arena, issuerCert, SEC_OID_MD2,
762
1644
                                   &(certID->issuerMD2KeyHash)) == NULL) {
763
1645
        goto loser;
764
1646
    }
898
1780
 * it deserves to be mentioned.
899
1781
 *
900
1782
 * Any problem causes a null return and error set:
901
 
 *      SEC_ERROR_UNKNOWN_ISSUER
 
1783
 *      SEC_ERROR_UNKNOWN_ISSUER
902
1784
 * Other errors are low-level problems (no memory, bad database, etc.).
903
1785
 */
904
1786
static ocspSingleRequest **
905
1787
ocsp_CreateSingleRequestList(PRArenaPool *arena, CERTCertList *certList,
906
 
                             int64 time, PRBool includeLocator)
 
1788
                             int64 time, PRBool includeLocator)
907
1789
{
908
1790
    ocspSingleRequest **requestList = NULL;
909
 
    CERTCertListNode *node;
 
1791
    CERTCertListNode *node = NULL;
910
1792
    int i, count;
911
1793
    void *mark = PORT_ArenaMark(arena);
912
1794
 
913
1795
    node = CERT_LIST_HEAD(certList);
914
1796
    for (count = 0; !CERT_LIST_END(node, certList); count++) {
915
 
        node = CERT_LIST_NEXT(node);
 
1797
        node = CERT_LIST_NEXT(node);
916
1798
    }
917
1799
 
918
1800
    if (count == 0)
925
1807
    node = CERT_LIST_HEAD(certList);
926
1808
    for (i = 0; !CERT_LIST_END(node, certList); i++) {
927
1809
        requestList[i] = PORT_ArenaZNew(arena, ocspSingleRequest);
928
 
        if (requestList[i] == NULL)
929
 
            goto loser;
930
 
 
931
 
        requestList[i]->arena = arena;
932
 
        requestList[i]->reqCert = ocsp_CreateCertID(arena, node->cert, time);
933
 
        if (requestList[i]->reqCert == NULL)
934
 
            goto loser;
935
 
 
936
 
        if (includeLocator == PR_TRUE) {
937
 
            SECStatus rv;
938
 
 
939
 
            rv = ocsp_AddServiceLocatorExtension(requestList[i], node->cert);
940
 
            if (rv != SECSuccess)
941
 
                goto loser;
942
 
        }
943
 
 
944
 
        node = CERT_LIST_NEXT(node);
 
1810
        if (requestList[i] == NULL)
 
1811
            goto loser;
 
1812
 
 
1813
        requestList[i]->arena = arena;
 
1814
        requestList[i]->reqCert = ocsp_CreateCertID(arena, node->cert, time);
 
1815
        if (requestList[i]->reqCert == NULL)
 
1816
            goto loser;
 
1817
 
 
1818
        if (includeLocator == PR_TRUE) {
 
1819
            SECStatus rv;
 
1820
 
 
1821
            rv = ocsp_AddServiceLocatorExtension(requestList[i], node->cert);
 
1822
            if (rv != SECSuccess)
 
1823
                goto loser;
 
1824
        }
 
1825
 
 
1826
        node = CERT_LIST_NEXT(node);
945
1827
    }
946
1828
 
947
1829
    PORT_Assert(i == count);
955
1837
    return NULL;
956
1838
}
957
1839
 
 
1840
static ocspSingleRequest **
 
1841
ocsp_CreateRequestFromCert(PRArenaPool *arena, 
 
1842
                           CERTOCSPCertID *certID, 
 
1843
                           CERTCertificate *singleCert,
 
1844
                           int64 time, 
 
1845
                           PRBool includeLocator)
 
1846
{
 
1847
    ocspSingleRequest **requestList = NULL;
 
1848
    void *mark = PORT_ArenaMark(arena);
 
1849
    PORT_Assert(certID != NULL && singleCert != NULL);
 
1850
 
 
1851
    /* meaning of value 2: one entry + one end marker */
 
1852
    requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, 2);
 
1853
    if (requestList == NULL)
 
1854
        goto loser;
 
1855
    requestList[0] = PORT_ArenaZNew(arena, ocspSingleRequest);
 
1856
    if (requestList[0] == NULL)
 
1857
        goto loser;
 
1858
    requestList[0]->arena = arena;
 
1859
    /* certID will live longer than the request */
 
1860
    requestList[0]->reqCert = certID; 
 
1861
 
 
1862
    if (includeLocator == PR_TRUE) {
 
1863
        SECStatus rv;
 
1864
        rv = ocsp_AddServiceLocatorExtension(requestList[0], singleCert);
 
1865
        if (rv != SECSuccess)
 
1866
            goto loser;
 
1867
    }
 
1868
 
 
1869
    PORT_ArenaUnmark(arena, mark);
 
1870
    requestList[1] = NULL;
 
1871
    return requestList;
 
1872
 
 
1873
loser:
 
1874
    PORT_ArenaRelease(arena, mark);
 
1875
    return NULL;
 
1876
}
 
1877
 
 
1878
static CERTOCSPRequest *
 
1879
ocsp_prepareEmptyOCSPRequest()
 
1880
{
 
1881
    PRArenaPool *arena = NULL;
 
1882
    CERTOCSPRequest *request = NULL;
 
1883
    ocspTBSRequest *tbsRequest = NULL;
 
1884
 
 
1885
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
1886
    if (arena == NULL) {
 
1887
        goto loser;
 
1888
    }
 
1889
    request = PORT_ArenaZNew(arena, CERTOCSPRequest);
 
1890
    if (request == NULL) {
 
1891
        goto loser;
 
1892
    }
 
1893
    request->arena = arena;
 
1894
 
 
1895
    tbsRequest = PORT_ArenaZNew(arena, ocspTBSRequest);
 
1896
    if (tbsRequest == NULL) {
 
1897
        goto loser;
 
1898
    }
 
1899
    request->tbsRequest = tbsRequest;
 
1900
    /* version 1 is the default, so we need not fill in a version number */
 
1901
    return request;
 
1902
 
 
1903
loser:
 
1904
    if (arena != NULL) {
 
1905
        PORT_FreeArena(arena, PR_FALSE);
 
1906
    }
 
1907
    return NULL;
 
1908
}
 
1909
 
 
1910
static CERTOCSPRequest *
 
1911
cert_CreateSingleCertOCSPRequest(CERTOCSPCertID *certID, 
 
1912
                                 CERTCertificate *singleCert, 
 
1913
                                 int64 time, 
 
1914
                                 PRBool addServiceLocator)
 
1915
{
 
1916
    CERTOCSPRequest *request;
 
1917
    request = ocsp_prepareEmptyOCSPRequest();
 
1918
    if (!request)
 
1919
        return NULL;
 
1920
    /*
 
1921
     * Version 1 is the default, so we need not fill in a version number.
 
1922
     * Now create the list of single requests, one for each cert.
 
1923
     */
 
1924
    request->tbsRequest->requestList = 
 
1925
        ocsp_CreateRequestFromCert(request->arena, 
 
1926
                                   certID,
 
1927
                                   singleCert,
 
1928
                                   time,
 
1929
                                   addServiceLocator);
 
1930
    if (request->tbsRequest->requestList == NULL) {
 
1931
        PORT_FreeArena(request->arena, PR_FALSE);
 
1932
        return NULL;
 
1933
    }
 
1934
    return request;
 
1935
}
958
1936
 
959
1937
/*
960
1938
 * FUNCTION: CERT_CreateOCSPRequest
992
1970
                       PRBool addServiceLocator,
993
1971
                       CERTCertificate *signerCert)
994
1972
{
995
 
    PRArenaPool *arena = NULL;
996
1973
    CERTOCSPRequest *request = NULL;
997
 
    ocspTBSRequest *tbsRequest = NULL;
998
1974
 
 
1975
    if (!certList) {
 
1976
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
1977
        return NULL;
 
1978
    }
999
1979
    /*
1000
1980
     * XXX This should set an error, but since it is only temporary and
1001
1981
     * since PSM will not initially provide a way to turn on signing of
1008
1988
     * field of the tbsRequest.
1009
1989
     */
1010
1990
    if (signerCert != NULL) {
1011
 
        return NULL;
1012
 
    }
1013
 
 
1014
 
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1015
 
    if (arena == NULL) {
1016
 
        goto loser;
1017
 
    }
1018
 
 
1019
 
    request = PORT_ArenaZNew(arena, CERTOCSPRequest);
1020
 
    if (request == NULL) {
1021
 
        goto loser;
1022
 
    }
1023
 
    request->arena = arena;
1024
 
 
1025
 
    tbsRequest = PORT_ArenaZNew(arena, ocspTBSRequest);
1026
 
    if (tbsRequest == NULL) {
1027
 
        goto loser;
1028
 
    }
1029
 
    request->tbsRequest = tbsRequest;
1030
 
 
1031
 
    /* version 1 is the default, so we need not fill in a version number */
1032
 
 
 
1991
        return NULL;
 
1992
    }
 
1993
    request = ocsp_prepareEmptyOCSPRequest();
 
1994
    if (!request)
 
1995
        return NULL;
1033
1996
    /*
1034
1997
     * Now create the list of single requests, one for each cert.
1035
1998
     */
1036
 
    tbsRequest->requestList = ocsp_CreateSingleRequestList(arena, certList,
1037
 
                                                           time,
1038
 
                                                           addServiceLocator);
1039
 
    if (tbsRequest->requestList == NULL) {
1040
 
        goto loser;
 
1999
    request->tbsRequest->requestList = 
 
2000
        ocsp_CreateSingleRequestList(request->arena, 
 
2001
                                     certList,
 
2002
                                     time,
 
2003
                                     addServiceLocator);
 
2004
    if (request->tbsRequest->requestList == NULL) {
 
2005
        PORT_FreeArena(request->arena, PR_FALSE);
 
2006
        return NULL;
1041
2007
    }
1042
2008
    return request;
1043
 
 
1044
 
loser:
1045
 
    if (arena != NULL) {
1046
 
        PORT_FreeArena(arena, PR_FALSE);
1047
 
    }
1048
 
    return NULL;
1049
2009
}
1050
2010
 
1051
 
 
1052
2011
/*
1053
2012
 * FUNCTION: CERT_AddOCSPAcceptableResponses
1054
2013
 *   Add the AcceptableResponses extension to an OCSP Request.
1571
2530
 * is only used internally.  When this interface is officially exported,
1572
2531
 * each assertion below will need to be followed-up with setting an error
1573
2532
 * and returning (null).
 
2533
 *
 
2534
 * FUNCTION: ocsp_GetResponseData
 
2535
 *   Returns ocspResponseData structure and a pointer to tbs response
 
2536
 *   data DER from a valid ocsp response. 
 
2537
 * INPUTS:
 
2538
 *   CERTOCSPResponse *response
 
2539
 *     structure of a valid ocsp response
 
2540
 * RETURN:
 
2541
 *   decoded OCSP response data and a pointer(tbsResponseDataDER) to its
 
2542
 *   undecoded data DER.
1574
2543
 */
1575
2544
static ocspResponseData *
1576
 
ocsp_GetResponseData(CERTOCSPResponse *response)
 
2545
ocsp_GetResponseData(CERTOCSPResponse *response, SECItem **tbsResponseDataDER)
1577
2546
{
1578
2547
    ocspBasicOCSPResponse *basic;
1579
2548
    ocspResponseData *responseData;
1591
2560
    responseData = basic->tbsResponseData;
1592
2561
    PORT_Assert(responseData != NULL);
1593
2562
 
 
2563
    if (tbsResponseDataDER) {
 
2564
        *tbsResponseDataDER = &basic->tbsResponseDataDER;
 
2565
 
 
2566
        PORT_Assert((*tbsResponseDataDER)->data != NULL);
 
2567
        PORT_Assert((*tbsResponseDataDER)->len != 0);
 
2568
    }
 
2569
 
1594
2570
    return responseData;
1595
2571
}
1596
2572
 
2345
3321
                            CERTCertificate *signerCert, void *pwArg,
2346
3322
                            CERTOCSPRequest **pRequest)
2347
3323
{
2348
 
    CERTOCSPRequest *request = NULL;
 
3324
    CERTOCSPRequest *request;
 
3325
    request = CERT_CreateOCSPRequest(certList, time, addServiceLocator,
 
3326
                                     signerCert);
 
3327
    if (!request)
 
3328
        return NULL;
 
3329
    return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, 
 
3330
                                                  time, addServiceLocator, 
 
3331
                                                  pwArg, pRequest);
 
3332
}
 
3333
 
 
3334
static SECItem *
 
3335
ocsp_GetEncodedOCSPResponseFromRequest(PRArenaPool *arena, 
 
3336
                                       CERTOCSPRequest *request,
 
3337
                                       char *location, int64 time,
 
3338
                                       PRBool addServiceLocator,
 
3339
                                       void *pwArg,
 
3340
                                       CERTOCSPRequest **pRequest)
 
3341
{
2349
3342
    SECItem *encodedRequest = NULL;
2350
3343
    SECItem *encodedResponse = NULL;
2351
3344
    PRFileDesc *sock = NULL;
2352
3345
    SECStatus rv;
2353
3346
    const SEC_HttpClientFcn *registeredHttpClient = NULL;
2354
3347
 
2355
 
    request = CERT_CreateOCSPRequest(certList, time, addServiceLocator,
2356
 
                                     signerCert);
2357
 
    if (request == NULL)
2358
 
        goto loser;
2359
 
 
2360
3348
    rv = CERT_AddOCSPAcceptableResponses(request,
2361
3349
                                         SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
2362
3350
    if (rv != SECSuccess)
2403
3391
    return encodedResponse;
2404
3392
}
2405
3393
 
 
3394
static SECItem *
 
3395
ocsp_GetEncodedOCSPResponseForSingleCert(PRArenaPool *arena, 
 
3396
                                         CERTOCSPCertID *certID, 
 
3397
                                         CERTCertificate *singleCert, 
 
3398
                                         char *location, int64 time,
 
3399
                                         PRBool addServiceLocator,
 
3400
                                         void *pwArg,
 
3401
                                         CERTOCSPRequest **pRequest)
 
3402
{
 
3403
    CERTOCSPRequest *request;
 
3404
    request = cert_CreateSingleCertOCSPRequest(certID, singleCert, time, 
 
3405
                                               addServiceLocator);
 
3406
    if (!request)
 
3407
        return NULL;
 
3408
    return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, 
 
3409
                                                  time, addServiceLocator, 
 
3410
                                                  pwArg, pRequest);
 
3411
}
2406
3412
 
2407
3413
/* Checks a certificate for the key usage extension of OCSP signer. */
2408
3414
static PRBool
2409
 
ocsp_CertIsOCSPSigner(CERTCertificate *cert)
 
3415
ocsp_CertIsOCSPDesignatedResponder(CERTCertificate *cert)
2410
3416
{
2411
3417
    SECStatus rv;
2412
3418
    SECItem extItem;
2491
3497
    item.data = buf;
2492
3498
    item.len = SHA1_LENGTH;
2493
3499
 
2494
 
    if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_SHA1, &item) == NULL) {
2495
 
        return PR_FALSE;
2496
 
    }
2497
 
    if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
2498
 
        return PR_TRUE;
2499
 
    }
2500
 
    if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_MD5, &item) == NULL) {
2501
 
        return PR_FALSE;
2502
 
    }
2503
 
    if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
2504
 
        return PR_TRUE;
2505
 
    }
2506
 
    if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_MD2, &item) == NULL) {
 
3500
    if (cert_GetSPKIDigest(NULL,testCert,SEC_OID_SHA1, &item) == NULL) {
 
3501
        return PR_FALSE;
 
3502
    }
 
3503
    if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
 
3504
        return PR_TRUE;
 
3505
    }
 
3506
    if (cert_GetSPKIDigest(NULL,testCert,SEC_OID_MD5, &item) == NULL) {
 
3507
        return PR_FALSE;
 
3508
    }
 
3509
    if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
 
3510
        return PR_TRUE;
 
3511
    }
 
3512
    if (cert_GetSPKIDigest(NULL,testCert,SEC_OID_MD2, &item) == NULL) {
2507
3513
        return PR_FALSE;
2508
3514
    }
2509
3515
    if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
2513
3519
    return PR_FALSE;
2514
3520
}
2515
3521
 
 
3522
static PRBool
 
3523
ocsp_CertIsOCSPDefaultResponder(CERTCertDBHandle *handle, CERTCertificate *cert);
 
3524
 
2516
3525
static CERTCertificate *
2517
3526
ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle,CERTOCSPCertID *certID);
2518
3527
 
2519
3528
/*
2520
 
 * Check the signature on some OCSP data.  This is a helper function that
2521
 
 * can be used to check either a request or a response.  The result is
2522
 
 * saved in the signature structure itself for future reference (to avoid
2523
 
 * repeating the expensive verification operation), as well as returned.
2524
 
 * In addition to checking the signature, the certificate (and its chain)
2525
 
 * are also checked for validity (at the specified time) and usage.
2526
 
 *
2527
 
 * The type of cert lookup to be performed is specified by "lookupByName":
2528
 
 * if true, then "certIndex" is actually a CERTName; otherwise it is a
2529
 
 * SECItem which contains a key hash.
2530
 
 *
2531
 
 * If the signature verifies okay, and the argument "pSignerCert" is not
2532
 
 * null, that parameter will be filled-in with a pointer to the signer's
2533
 
 * certificate.  The caller is then responsible for destroying the cert.
2534
 
 *
2535
 
 * A return of SECSuccess means the verification succeeded.  If not,
2536
 
 * an error will be set with the reason.  Most likely are:
 
3529
 * FUNCTION: CERT_VerifyOCSPResponseSignature
 
3530
 *   Check the signature on an OCSP Response.  Will also perform a
 
3531
 *   verification of the signer's certificate.  Note, however, that a
 
3532
 *   successful verification does not make any statement about the
 
3533
 *   signer's *authority* to provide status for the certificate(s),
 
3534
 *   that must be checked individually for each certificate.
 
3535
 * INPUTS:
 
3536
 *   CERTOCSPResponse *response
 
3537
 *     Pointer to response structure with signature to be checked.
 
3538
 *   CERTCertDBHandle *handle
 
3539
 *     Pointer to CERTCertDBHandle for certificate DB to use for verification.
 
3540
 *   void *pwArg
 
3541
 *     Pointer to argument for password prompting, if needed.
 
3542
 * OUTPUTS:
 
3543
 *   CERTCertificate **pSignerCert
 
3544
 *     Pointer in which to store signer's certificate; only filled-in if
 
3545
 *     non-null.
 
3546
 * RETURN:
 
3547
 *   Returns SECSuccess when signature is valid, anything else means invalid.
 
3548
 *   Possible errors set:
 
3549
 *      SEC_ERROR_OCSP_MALFORMED_RESPONSE - unknown type of ResponderID
 
3550
 *      SEC_ERROR_INVALID_TIME - bad format of "ProducedAt" time
2537
3551
 *      SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found
2538
3552
 *      SEC_ERROR_BAD_SIGNATURE - the signature did not verify
2539
 
 * Other errors are any of the many possible failures in cert verification
2540
 
 * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
2541
 
 * verifying the signer's cert, or low-level problems (no memory, etc.)
 
3553
 *   Other errors are any of the many possible failures in cert verification
 
3554
 *   (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
 
3555
 *   verifying the signer's cert, or low-level problems (no memory, etc.)
2542
3556
 */
2543
 
static SECStatus
2544
 
ocsp_CheckSignature(ocspSignature *signature, void *tbs,
2545
 
                    const SEC_ASN1Template *encodeTemplate,
2546
 
                    CERTCertDBHandle *handle, SECCertUsage certUsage,
2547
 
                    int64 checkTime, PRBool lookupByName, void *certIndex,
2548
 
                    void *pwArg, CERTCertificate **pSignerCert,
2549
 
                    CERTCertificate *issuer)
 
3557
SECStatus
 
3558
CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response,    
 
3559
                                 CERTCertDBHandle *handle, void *pwArg,
 
3560
                                 CERTCertificate **pSignerCert,
 
3561
                                 CERTCertificate *issuer)
2550
3562
{
2551
3563
    SECItem rawSignature;
2552
 
    SECItem *encodedTBS = NULL;
 
3564
    SECItem *tbsResponseDataDER;
2553
3565
    CERTCertificate *responder = NULL;
2554
3566
    CERTCertificate *signerCert = NULL;
2555
3567
    SECKEYPublicKey *signerKey = NULL;
2556
3568
    CERTCertificate **certs = NULL;
2557
3569
    SECStatus rv = SECFailure;
2558
 
    int certCount;
2559
 
    int i;
 
3570
    int certCount = 0;
 
3571
    PRBool lookupByName;
 
3572
    void *certIndex;
 
3573
    int64 producedAt;
 
3574
 
 
3575
    /* ocsp_DecodeBasicOCSPResponse will fail if asn1 decoder is unable
 
3576
     * to properly decode tbsData (see the function and
 
3577
     * ocsp_BasicOCSPResponseTemplate). Thus, tbsData can not be
 
3578
     * equal to null */
 
3579
    ocspResponseData *tbsData = ocsp_GetResponseData(response,
 
3580
                                                     &tbsResponseDataDER);
 
3581
    ocspSignature *signature = ocsp_GetResponseSignature(response);
 
3582
 
 
3583
    if (!signature) {
 
3584
        PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE);
 
3585
        return SECFailure;
 
3586
    }
2560
3587
 
2561
3588
    /*
2562
3589
     * If this signature has already gone through verification, just
2572
3599
        return signature->status;
2573
3600
    }
2574
3601
 
 
3602
    PORT_Assert(tbsData->responderID != NULL);
 
3603
    switch (tbsData->responderID->responderIDType) {
 
3604
    case ocspResponderID_byName:
 
3605
        lookupByName = PR_TRUE;
 
3606
        certIndex = &tbsData->derResponderID;
 
3607
        break;
 
3608
    case ocspResponderID_byKey:
 
3609
        lookupByName = PR_FALSE;
 
3610
        certIndex = &tbsData->responderID->responderIDValue.keyHash;
 
3611
        break;
 
3612
    case ocspResponderID_other:
 
3613
    default:
 
3614
        PORT_Assert(0);
 
3615
        PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
 
3616
        return SECFailure;
 
3617
    }
 
3618
 
2575
3619
    /*
2576
3620
     * If the signature contains some certificates as well, temporarily
2577
3621
     * import them in case they are needed for verification.
2579
3623
     * Note that the result of this is that each cert in "certs" needs
2580
3624
     * to be destroyed.
2581
3625
     */
2582
 
    certCount = 0;
2583
3626
    if (signature->derCerts != NULL) {
2584
3627
        for (; signature->derCerts[certCount] != NULL; certCount++) {
2585
3628
            /* just counting */
2586
 
            /*IMPORT CERT TO SPKI TABLE */
2587
3629
        }
 
3630
        rv = CERT_ImportCerts(handle, certUsageStatusResponder, certCount,
 
3631
                              signature->derCerts, &certs,
 
3632
                              PR_FALSE, PR_FALSE, NULL);
 
3633
        if (rv != SECSuccess)
 
3634
             goto finish;
2588
3635
    }
2589
 
    rv = CERT_ImportCerts(handle, certUsage, certCount,
2590
 
                          signature->derCerts, &certs,
2591
 
                          PR_FALSE, PR_FALSE, NULL);
2592
 
    if (rv != SECSuccess)
2593
 
        goto finish;
2594
3636
 
2595
3637
    /*
2596
3638
     * Now look up the certificate that did the signing.
2597
3639
     * The signer can be specified either by name or by key hash.
2598
3640
     */
2599
3641
    if (lookupByName) {
2600
 
        SECItem *encodedName;
2601
 
 
2602
 
        encodedName = SEC_ASN1EncodeItem(NULL, NULL, certIndex,
2603
 
                                         CERT_NameTemplate);
2604
 
        if (encodedName == NULL)
2605
 
            goto finish;
2606
 
 
2607
 
        signerCert = CERT_FindCertByName(handle, encodedName);
2608
 
        SECITEM_FreeItem(encodedName, PR_TRUE);
 
3642
        SECItem *crIndex = (SECItem*)certIndex;
 
3643
        SECItem encodedName;
 
3644
        PLArenaPool *arena;
 
3645
 
 
3646
        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
3647
        if (arena != NULL) {
 
3648
 
 
3649
            rv = SEC_QuickDERDecodeItem(arena, &encodedName,
 
3650
                                        ocsp_ResponderIDDerNameTemplate,
 
3651
                                        crIndex);
 
3652
            if (rv != SECSuccess) {
 
3653
                if (PORT_GetError() == SEC_ERROR_BAD_DER)
 
3654
                    PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
 
3655
            } else {
 
3656
                    signerCert = CERT_FindCertByName(handle, &encodedName);
 
3657
            }
 
3658
            PORT_FreeArena(arena, PR_FALSE);
 
3659
        }
2609
3660
    } else {
2610
3661
        /*
2611
3662
         * The signer is either 1) a known issuer CA we passed in,
2612
3663
         * 2) the default OCSP responder, or 3) an intermediate CA
2613
3664
         * passed in the cert list to use. Figure out which it is.
2614
3665
         */
 
3666
        int i;
2615
3667
        responder = ocsp_CertGetDefaultResponder(handle,NULL);
2616
3668
        if (responder && ocsp_matchcert(certIndex,responder)) {
2617
3669
            signerCert = CERT_DupCertificate(responder);
2643
3695
    signature->wasChecked = PR_TRUE;
2644
3696
 
2645
3697
    /*
 
3698
     * The function will also verify the signer certificate; we
 
3699
     * need to tell it *when* that certificate must be valid -- for our
 
3700
     * purposes we expect it to be valid when the response was signed.
 
3701
     * The value of "producedAt" is the signing time.
 
3702
     */
 
3703
    rv = DER_GeneralizedTimeToTime(&producedAt, &tbsData->producedAt);
 
3704
    if (rv != SECSuccess)
 
3705
        goto finish;
 
3706
 
 
3707
    /*
2646
3708
     * Just because we have a cert does not mean it is any good; check
2647
3709
     * it for validity, trust and usage.
2648
3710
     */
2649
 
    rv = CERT_VerifyCert(handle, signerCert, PR_TRUE, certUsage, checkTime,
2650
 
                         pwArg, NULL);
2651
 
    if (rv != SECSuccess) {
2652
 
        PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
2653
 
        goto finish;
 
3711
    if (ocsp_CertIsOCSPDefaultResponder(handle, signerCert)) {
 
3712
        rv = SECSuccess;
 
3713
    } else {
 
3714
        if (CERT_IsCACert(signerCert, NULL)) {
 
3715
            rv = CERT_VerifyCert(handle, signerCert, PR_TRUE,
 
3716
                                 certUsageVerifyCA,
 
3717
                                 producedAt, pwArg, NULL);
 
3718
        } else {
 
3719
            rv = CERT_VerifyCert(handle, signerCert, PR_TRUE,
 
3720
                                 certUsageStatusResponder,
 
3721
                                 producedAt, pwArg, NULL);
 
3722
        }
 
3723
        if (rv != SECSuccess) {
 
3724
            PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
 
3725
            goto finish;
 
3726
        }
2654
3727
    }
2655
3728
 
2656
3729
    /*
2660
3733
    signerKey = CERT_ExtractPublicKey(signerCert);
2661
3734
    if (signerKey == NULL)
2662
3735
        goto finish;
2663
 
 
2664
 
    /*
2665
 
     * Prepare the data to be verified; it needs to be DER encoded first.
2666
 
     */
2667
 
    encodedTBS = SEC_ASN1EncodeItem(NULL, NULL, tbs, encodeTemplate);
2668
 
    if (encodedTBS == NULL)
2669
 
        goto finish;
2670
 
 
2671
3736
    /*
2672
3737
     * We copy the signature data *pointer* and length, so that we can
2673
3738
     * modify the length without damaging the original copy.  This is a
2680
3745
     */
2681
3746
    DER_ConvertBitString(&rawSignature);
2682
3747
 
2683
 
    rv = VFY_VerifyDataWithAlgorithmID(encodedTBS->data, encodedTBS->len, 
2684
 
                        signerKey, &rawSignature,
2685
 
                        &signature->signatureAlgorithm, NULL, pwArg);
 
3748
    rv = VFY_VerifyDataWithAlgorithmID(tbsResponseDataDER->data,
 
3749
                                       tbsResponseDataDER->len,
 
3750
                                       signerKey, &rawSignature,
 
3751
                                       &signature->signatureAlgorithm,
 
3752
                                       NULL, pwArg);
 
3753
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_BAD_SIGNATURE) {
 
3754
        PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE);
 
3755
    }
2686
3756
 
2687
3757
finish:
2688
3758
    if (signature->wasChecked)
2706
3776
        }
2707
3777
    }
2708
3778
 
2709
 
    if (encodedTBS != NULL)
2710
 
        SECITEM_FreeItem(encodedTBS, PR_TRUE);
2711
 
 
2712
3779
    if (signerKey != NULL)
2713
3780
        SECKEY_DestroyPublicKey(signerKey);
2714
3781
 
2719
3786
    return rv;
2720
3787
}
2721
3788
 
2722
 
 
2723
 
/*
2724
 
 * FUNCTION: CERT_VerifyOCSPResponseSignature
2725
 
 *   Check the signature on an OCSP Response.  Will also perform a
2726
 
 *   verification of the signer's certificate.  Note, however, that a
2727
 
 *   successful verification does not make any statement about the
2728
 
 *   signer's *authority* to provide status for the certificate(s),
2729
 
 *   that must be checked individually for each certificate.
2730
 
 * INPUTS:
2731
 
 *   CERTOCSPResponse *response
2732
 
 *     Pointer to response structure with signature to be checked.
2733
 
 *   CERTCertDBHandle *handle
2734
 
 *     Pointer to CERTCertDBHandle for certificate DB to use for verification.
2735
 
 *   void *pwArg
2736
 
 *     Pointer to argument for password prompting, if needed.
2737
 
 * OUTPUTS:
2738
 
 *   CERTCertificate **pSignerCert
2739
 
 *     Pointer in which to store signer's certificate; only filled-in if
2740
 
 *     non-null.
2741
 
 * RETURN:
2742
 
 *   Returns SECSuccess when signature is valid, anything else means invalid.
2743
 
 *   Possible errors set:
2744
 
 *      SEC_ERROR_OCSP_MALFORMED_RESPONSE - unknown type of ResponderID
2745
 
 *      SEC_ERROR_INVALID_TIME - bad format of "ProducedAt" time
2746
 
 *      SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found
2747
 
 *      SEC_ERROR_BAD_SIGNATURE - the signature did not verify
2748
 
 *   Other errors are any of the many possible failures in cert verification
2749
 
 *   (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
2750
 
 *   verifying the signer's cert, or low-level problems (no memory, etc.)
2751
 
 */
2752
 
SECStatus
2753
 
CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response,    
2754
 
                                 CERTCertDBHandle *handle, void *pwArg,
2755
 
                                 CERTCertificate **pSignerCert,
2756
 
                                 CERTCertificate *issuer)
2757
 
{
2758
 
    ocspResponseData *tbsData;          /* this is what is signed */
2759
 
    PRBool byName;
2760
 
    void *certIndex;
2761
 
    int64 producedAt;
2762
 
    SECStatus rv;
2763
 
 
2764
 
    tbsData = ocsp_GetResponseData(response);
2765
 
 
2766
 
    PORT_Assert(tbsData->responderID != NULL);
2767
 
    switch (tbsData->responderID->responderIDType) {
2768
 
      case ocspResponderID_byName:
2769
 
        byName = PR_TRUE;
2770
 
        certIndex = &tbsData->responderID->responderIDValue.name;
2771
 
        break;
2772
 
      case ocspResponderID_byKey:
2773
 
        byName = PR_FALSE;
2774
 
        certIndex = &tbsData->responderID->responderIDValue.keyHash;
2775
 
        break;
2776
 
      case ocspResponderID_other:
2777
 
      default:
2778
 
        PORT_Assert(0);
2779
 
        PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
2780
 
        return SECFailure;
2781
 
    }
2782
 
 
2783
 
    /*
2784
 
     * ocsp_CheckSignature will also verify the signer certificate; we
2785
 
     * need to tell it *when* that certificate must be valid -- for our
2786
 
     * purposes we expect it to be valid when the response was signed.
2787
 
     * The value of "producedAt" is the signing time.
2788
 
     */
2789
 
    rv = DER_GeneralizedTimeToTime(&producedAt, &tbsData->producedAt);
2790
 
    if (rv != SECSuccess)
2791
 
        return rv;
2792
 
 
2793
 
    return ocsp_CheckSignature(ocsp_GetResponseSignature(response),
2794
 
                               tbsData, ocsp_ResponseDataTemplate,
2795
 
                               handle, certUsageStatusResponder, producedAt,
2796
 
                               byName, certIndex, pwArg, pSignerCert, issuer);
2797
 
}
2798
 
 
2799
3789
/*
2800
3790
 * See if the request's certID and the single response's certID match.
2801
3791
 * This can be easy or difficult, depending on whether the same hash
2858
3848
        keyHash = &requestCertID->issuerMD2KeyHash;
2859
3849
        nameHash = &requestCertID->issuerMD2NameHash;
2860
3850
        break;
 
3851
    default:
 
3852
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
 
3853
        return SECFailure;
2861
3854
    }
2862
3855
 
2863
3856
    if ((keyHash != NULL)
2891
3884
 
2892
3885
    for (i = 0; responses[i] != NULL; i++) {
2893
3886
        single = responses[i];
2894
 
        if (ocsp_CertIDsMatch(handle, certID, single->certID) == PR_TRUE) {
 
3887
        if (ocsp_CertIDsMatch(handle, certID, single->certID)) {
2895
3888
            return single;
2896
3889
        }
2897
3890
    }
2932
3925
 
2933
3926
    return ocspcx;
2934
3927
}
 
3928
 
2935
3929
/*
2936
 
 * Return true if the given signerCert is the default responder for
2937
 
 * the given certID.  If not, or if any error, return false.
 
3930
 * Return cert reference if the given signerCert is the default responder for
 
3931
 * the given certID.  If not, or if any error, return NULL.
2938
3932
 */
2939
3933
static CERTCertificate *
2940
 
ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle,CERTOCSPCertID *certID)
 
3934
ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle, CERTOCSPCertID *certID)
2941
3935
{
2942
3936
    ocspCheckingContext *ocspcx;
2943
3937
 
2963
3957
}
2964
3958
 
2965
3959
/*
2966
 
 * Return true if the given signerCert is the default responder for
2967
 
 * the given certID.  If not, or if any error, return false.
 
3960
 * Return true if the cert is one of the default responders configured for
 
3961
 * ocsp context. If not, or if any error, return false.
2968
3962
 */
2969
3963
static PRBool
2970
 
ocsp_CertIsDefaultResponderForCertID(CERTCertDBHandle *handle,
2971
 
                                     CERTCertificate *signerCert,
2972
 
                                     CERTOCSPCertID *certID)
 
3964
ocsp_CertIsOCSPDefaultResponder(CERTCertDBHandle *handle, CERTCertificate *cert)
2973
3965
{
2974
 
    CERTCertificate *defaultResponderCert;
2975
 
 
2976
 
    defaultResponderCert = ocsp_CertGetDefaultResponder(handle, certID);
2977
 
    return (PRBool) (defaultResponderCert == signerCert);
 
3966
    ocspCheckingContext *ocspcx;
 
3967
 
 
3968
    ocspcx = ocsp_GetCheckingContext(handle);
 
3969
    if (ocspcx == NULL)
 
3970
        return PR_FALSE;
 
3971
 
 
3972
   /*
 
3973
    * Right now we have only one default responder.  It applies to
 
3974
    * all certs when it is used, so the check is simple and certID
 
3975
    * has no bearing on the answer.  Someday in the future we may
 
3976
    * allow configuration of different responders for different
 
3977
    * issuers, and then we would have to use the issuer specified
 
3978
    * in certID to determine if signerCert is the right one.
 
3979
    */
 
3980
    if (ocspcx->useDefaultResponder &&
 
3981
        CERT_CompareCerts(ocspcx->defaultResponderCert, cert)) {
 
3982
        return PR_TRUE;
 
3983
    }
 
3984
 
 
3985
    return PR_FALSE;
2978
3986
}
2979
3987
 
2980
3988
/*
3000
4008
                                  CERTOCSPCertID *certID,
3001
4009
                                  int64 thisUpdate)
3002
4010
{
3003
 
    CERTCertificate *issuerCert = NULL;
3004
 
    SECItem *issuerKeyHash = NULL;
 
4011
    CERTCertificate *issuerCert = NULL, *defRespCert;
 
4012
    SECItem *keyHash = NULL;
 
4013
    SECItem *nameHash = NULL;
3005
4014
    SECOidTag hashAlg;
3006
 
    PRBool okay = PR_FALSE;
 
4015
    PRBool keyHashEQ = PR_FALSE, nameHashEQ = PR_FALSE;
3007
4016
 
3008
4017
    /*
3009
4018
     * Check first for a trusted responder, which overrides everything else.
3010
4019
     */
3011
 
    if (ocsp_CertIsDefaultResponderForCertID(handle, signerCert, certID))
3012
 
        return PR_TRUE;
 
4020
    if ((defRespCert = ocsp_CertGetDefaultResponder(handle, certID)) &&
 
4021
        CERT_CompareCerts(defRespCert, signerCert)) {
 
4022
        return PR_TRUE;
 
4023
    }
3013
4024
 
3014
4025
    /*
3015
4026
     * In the other two cases, we need to do an issuer comparison.
3016
4027
     * How we do it depends on whether the signer certificate has the
3017
4028
     * special extension (for a designated responder) or not.
 
4029
     *
 
4030
     * First, lets check if signer of the response is the actual issuer
 
4031
     * of the cert. For that we will use signer cert key hash and cert subj
 
4032
     * name hash and will compare them with already calculated issuer key
 
4033
     * hash and issuer name hash. The hash algorithm is picked from response
 
4034
     * certID hash to avoid second hash calculation.
3018
4035
     */
3019
4036
 
3020
 
    if (ocsp_CertIsOCSPSigner(signerCert)) {
3021
 
        /*
3022
 
         * The signer is a designated responder.  Its issuer must match
3023
 
         * the issuer of the cert being checked.
3024
 
         */
3025
 
        issuerCert = CERT_FindCertIssuer(signerCert, thisUpdate,
3026
 
                                         certUsageAnyCA);
3027
 
        if (issuerCert == NULL) {
3028
 
            /*
3029
 
             * We could leave the SEC_ERROR_UNKNOWN_ISSUER error alone,
3030
 
             * but the following will give slightly more information.
3031
 
             * Once we have an error stack, things will be much better.
3032
 
             */
3033
 
            PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
3034
 
            goto loser;
3035
 
        }
3036
 
    } else {
3037
 
        /*
3038
 
         * The signer must *be* the issuer of the cert being checked.
3039
 
         */
3040
 
        issuerCert = signerCert;
3041
 
    }
3042
 
 
3043
4037
    hashAlg = SECOID_FindOIDTag(&certID->hashAlgorithm.algorithm);
3044
 
    issuerKeyHash = CERT_SPKDigestValueForCert(NULL, issuerCert, hashAlg, NULL);
3045
 
    if (issuerKeyHash == NULL)
3046
 
        goto loser;
3047
 
 
3048
 
    if (SECITEM_CompareItem(issuerKeyHash,
3049
 
                            &certID->issuerKeyHash) != SECEqual) {
3050
 
        PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
3051
 
        goto loser;
3052
 
    }
3053
 
 
3054
 
    okay = PR_TRUE;
3055
 
 
3056
 
loser:
3057
 
    if (issuerKeyHash != NULL)
3058
 
        SECITEM_FreeItem(issuerKeyHash, PR_TRUE);
3059
 
 
3060
 
    if (issuerCert != NULL && issuerCert != signerCert)
3061
 
        CERT_DestroyCertificate(issuerCert);
3062
 
 
3063
 
    return okay;
 
4038
 
 
4039
    keyHash = cert_GetSPKIDigest(NULL, signerCert, hashAlg, NULL);
 
4040
    if (keyHash != NULL) {
 
4041
 
 
4042
        keyHashEQ =
 
4043
            (SECITEM_CompareItem(keyHash,
 
4044
                                 &certID->issuerKeyHash) == SECEqual);
 
4045
        SECITEM_FreeItem(keyHash, PR_TRUE);
 
4046
    }
 
4047
    if (keyHashEQ &&
 
4048
        (nameHash = cert_GetSubjectNameDigest(NULL, signerCert,
 
4049
                                              hashAlg, NULL))) {
 
4050
        nameHashEQ =
 
4051
            (SECITEM_CompareItem(nameHash,
 
4052
                                 &certID->issuerNameHash) == SECEqual);
 
4053
            
 
4054
        SECITEM_FreeItem(nameHash, PR_TRUE);
 
4055
        if (nameHashEQ) {
 
4056
            /* The issuer of the cert is the the signer of the response */
 
4057
            return PR_TRUE;
 
4058
        }
 
4059
    }
 
4060
 
 
4061
 
 
4062
    keyHashEQ = PR_FALSE;
 
4063
    nameHashEQ = PR_FALSE;
 
4064
 
 
4065
    if (!ocsp_CertIsOCSPDesignatedResponder(signerCert)) {
 
4066
        PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
 
4067
        return PR_FALSE;
 
4068
    }
 
4069
 
 
4070
    /*
 
4071
     * The signer is a designated responder.  Its issuer must match
 
4072
     * the issuer of the cert being checked.
 
4073
     */
 
4074
    issuerCert = CERT_FindCertIssuer(signerCert, thisUpdate,
 
4075
                                     certUsageAnyCA);
 
4076
    if (issuerCert == NULL) {
 
4077
        /*
 
4078
         * We could leave the SEC_ERROR_UNKNOWN_ISSUER error alone,
 
4079
         * but the following will give slightly more information.
 
4080
         * Once we have an error stack, things will be much better.
 
4081
         */
 
4082
        PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
 
4083
        return PR_FALSE;
 
4084
    }
 
4085
 
 
4086
    keyHash = cert_GetSPKIDigest(NULL, issuerCert, hashAlg, NULL);
 
4087
    nameHash = cert_GetSubjectNameDigest(NULL, issuerCert, hashAlg, NULL);
 
4088
 
 
4089
    CERT_DestroyCertificate(issuerCert);
 
4090
 
 
4091
    if (keyHash != NULL && nameHash != NULL) {
 
4092
        keyHashEQ = 
 
4093
            (SECITEM_CompareItem(keyHash,
 
4094
                                 &certID->issuerKeyHash) == SECEqual);
 
4095
 
 
4096
        nameHashEQ =
 
4097
            (SECITEM_CompareItem(nameHash,
 
4098
                                 &certID->issuerNameHash) == SECEqual);
 
4099
    }
 
4100
 
 
4101
    if (keyHash) {
 
4102
        SECITEM_FreeItem(keyHash, PR_TRUE);
 
4103
    }
 
4104
    if (nameHash) {
 
4105
        SECITEM_FreeItem(nameHash, PR_TRUE);
 
4106
    }
 
4107
 
 
4108
    if (keyHashEQ && nameHashEQ) {
 
4109
        return PR_TRUE;
 
4110
    }
 
4111
 
 
4112
    PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
 
4113
    return PR_FALSE;
3064
4114
}
3065
4115
 
3066
4116
/*
3132
4182
    int64 now, thisUpdate, nextUpdate, tmstamp, tmp;
3133
4183
    SECStatus rv;
3134
4184
 
 
4185
    OCSP_TRACE(("OCSP ocsp_VerifySingleResponse, nextUpdate: %d\n", 
 
4186
               ((single->nextUpdate) != 0)));
3135
4187
    /*
3136
4188
     * If all the responder said was that the given cert was unknown to it,
3137
4189
     * that is a valid response.  Not very interesting to us, of course,
3378
4430
 * at the specified time.
3379
4431
 */
3380
4432
static SECStatus
3381
 
ocsp_CertHasGoodStatus(CERTOCSPSingleResponse *single, int64 time)
 
4433
ocsp_CertHasGoodStatus(ocspCertStatus *status, int64 time)
3382
4434
{
3383
 
    ocspCertStatus *status;
3384
4435
    SECStatus rv;
3385
 
 
3386
 
    status = single->certStatus;
3387
 
 
3388
4436
    switch (status->certStatusType) {
3389
 
      case ocspCertStatus_good:
3390
 
        rv = SECSuccess;
3391
 
        break;
3392
 
      case ocspCertStatus_revoked:
3393
 
        rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
3394
 
        break;
3395
 
      case ocspCertStatus_unknown:
3396
 
        PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
3397
 
        rv = SECFailure;
3398
 
        break;
3399
 
      case ocspCertStatus_other:
3400
 
      default:
3401
 
        PORT_Assert(0);
3402
 
        PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
3403
 
        rv = SECFailure;
3404
 
        break;
3405
 
    }
3406
 
 
3407
 
    return rv;
3408
 
}
3409
 
 
 
4437
    case ocspCertStatus_good:
 
4438
        rv = SECSuccess;
 
4439
        break;
 
4440
    case ocspCertStatus_revoked:
 
4441
        rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
 
4442
        break;
 
4443
    case ocspCertStatus_unknown:
 
4444
        PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
 
4445
        rv = SECFailure;
 
4446
        break;
 
4447
    case ocspCertStatus_other:
 
4448
    default:
 
4449
        PORT_Assert(0);
 
4450
        PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
 
4451
        rv = SECFailure;
 
4452
        break;
 
4453
    }
 
4454
    return rv;
 
4455
}
 
4456
 
 
4457
static SECStatus
 
4458
ocsp_SingleResponseCertHasGoodStatus(CERTOCSPSingleResponse *single, int64 time)
 
4459
{
 
4460
    return ocsp_CertHasGoodStatus(single->certStatus, time);
 
4461
}
 
4462
 
 
4463
/* return value SECFailure means: not found or not fresh */
 
4464
static SECStatus
 
4465
ocsp_GetCachedOCSPResponseStatusIfFresh(CERTOCSPCertID *certID, 
 
4466
                                        int64 time, 
 
4467
                                        SECStatus *rv_ocsp)
 
4468
{
 
4469
    OCSPCacheItem *cacheItem = NULL;
 
4470
    SECStatus rv = SECFailure;
 
4471
  
 
4472
    if (!certID || !rv_ocsp) {
 
4473
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
4474
        return SECFailure;
 
4475
    }
 
4476
    *rv_ocsp = SECFailure;
 
4477
  
 
4478
    PR_EnterMonitor(OCSP_Global.monitor);
 
4479
    cacheItem = ocsp_FindCacheEntry(&OCSP_Global.cache, certID);
 
4480
    if (cacheItem && ocsp_IsCacheItemFresh(cacheItem)) {
 
4481
        /* having an arena means, we have a cached certStatus */
 
4482
        if (cacheItem->certStatusArena) {
 
4483
            *rv_ocsp = ocsp_CertHasGoodStatus(&cacheItem->certStatus, time);
 
4484
            rv = SECSuccess;
 
4485
        } else {
 
4486
            /*
 
4487
             * No status cached, the previous attempt failed.
 
4488
             * If OCSP is required, we never decide based on a failed attempt 
 
4489
             * However, if OCSP is optional, a recent OCSP failure is
 
4490
             * an allowed good state.
 
4491
             */
 
4492
            if (OCSP_Global.ocspFailureMode == 
 
4493
                    ocspMode_FailureIsNotAVerificationFailure) {
 
4494
                rv = SECSuccess;
 
4495
                *rv_ocsp = SECSuccess;
 
4496
            }
 
4497
        }
 
4498
    }
 
4499
    PR_ExitMonitor(OCSP_Global.monitor);
 
4500
    return rv;
 
4501
}
3410
4502
 
3411
4503
/*
3412
4504
 * FUNCTION: CERT_CheckOCSPStatus
3462
4554
CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
3463
4555
                     int64 time, void *pwArg)
3464
4556
{
 
4557
    CERTOCSPCertID *certID;
 
4558
    PRBool certIDWasConsumed = PR_FALSE;
 
4559
    SECStatus rv = SECFailure;
 
4560
    SECStatus rv_ocsp;
 
4561
  
 
4562
    OCSP_TRACE_CERT(cert);
 
4563
    OCSP_TRACE_TIME("## requested validity time:", time);
 
4564
  
 
4565
    certID = CERT_CreateOCSPCertID(cert, time);
 
4566
    if (!certID)
 
4567
        return SECFailure;
 
4568
    rv = ocsp_GetCachedOCSPResponseStatusIfFresh(certID, time, &rv_ocsp);
 
4569
    if (rv == SECSuccess) {
 
4570
        CERT_DestroyOCSPCertID(certID);
 
4571
        return rv_ocsp;
 
4572
    }
 
4573
    rv = ocsp_GetOCSPStatusFromNetwork(handle, certID, cert, time, pwArg, 
 
4574
                                       &certIDWasConsumed, &rv_ocsp);
 
4575
    if (rv != SECSuccess) {
 
4576
        /* we were unable to obtain ocsp status */
 
4577
        PR_EnterMonitor(OCSP_Global.monitor);
 
4578
        if (OCSP_Global.ocspFailureMode ==
 
4579
                ocspMode_FailureIsVerificationFailure) {
 
4580
            rv_ocsp = SECFailure;
 
4581
        } else {
 
4582
            rv_ocsp = SECSuccess;
 
4583
        }
 
4584
        PR_ExitMonitor(OCSP_Global.monitor);
 
4585
    }
 
4586
    if (!certIDWasConsumed) {
 
4587
        CERT_DestroyOCSPCertID(certID);
 
4588
    }
 
4589
    return rv_ocsp;
 
4590
}
 
4591
 
 
4592
/*
 
4593
 * Status in *certIDWasConsumed will always be correct, regardless of 
 
4594
 * return value.
 
4595
 */
 
4596
static SECStatus
 
4597
ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle, 
 
4598
                              CERTOCSPCertID *certID, 
 
4599
                              CERTCertificate *cert, 
 
4600
                              int64 time, 
 
4601
                              void *pwArg,
 
4602
                              PRBool *certIDWasConsumed,
 
4603
                              SECStatus *rv_ocsp)
 
4604
{
3465
4605
    char *location = NULL;
3466
4606
    PRBool locationIsDefault;
3467
 
    CERTCertList *certList = NULL;
3468
4607
    SECItem *encodedResponse = NULL;
3469
4608
    CERTOCSPRequest *request = NULL;
3470
4609
    CERTOCSPResponse *response = NULL;
3471
4610
    CERTCertificate *signerCert = NULL;
3472
4611
    CERTCertificate *issuerCert = NULL;
3473
 
    CERTOCSPCertID *certID;
3474
4612
    SECStatus rv = SECFailure;
 
4613
    CERTOCSPSingleResponse *single = NULL;
3475
4614
 
 
4615
    if (!certIDWasConsumed || !rv_ocsp) {
 
4616
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
4617
        return SECFailure;
 
4618
    }
 
4619
    *certIDWasConsumed = PR_FALSE;
 
4620
    *rv_ocsp = SECFailure;
3476
4621
 
3477
4622
    /*
3478
4623
     * The first thing we need to do is find the location of the responder.
3487
4632
     */
3488
4633
    location = ocsp_GetResponderLocation(handle, cert, &locationIsDefault);
3489
4634
    if (location == NULL) {
3490
 
        int err = PORT_GetError();
3491
 
        if (err == SEC_ERROR_EXTENSION_NOT_FOUND ||
3492
 
            err == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) {
3493
 
            PORT_SetError(0);
3494
 
            return SECSuccess;
3495
 
        }
3496
 
        return SECFailure;
 
4635
       int err = PORT_GetError();
 
4636
       if (err == SEC_ERROR_EXTENSION_NOT_FOUND ||
 
4637
           err == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) {
 
4638
           PORT_SetError(0);
 
4639
           *rv_ocsp = SECSuccess;
 
4640
           return SECSuccess;
 
4641
       }
 
4642
       return SECFailure;
3497
4643
    }
3498
4644
 
3499
4645
    /*
3500
 
     * For now, create a cert-list of one.
3501
4646
     * XXX In the fullness of time, we will want/need to handle a
3502
4647
     * certificate chain.  This will be done either when a new parameter
3503
4648
     * tells us to, or some configuration variable tells us to.  In any
3512
4657
     * if you do not understand this.)
3513
4658
     */
3514
4659
 
3515
 
    certList = CERT_NewCertList();
3516
 
    if (certList == NULL)
3517
 
        goto loser;
3518
 
 
3519
 
    /* dup it because freeing the list will destroy the cert, too */
3520
 
    cert = CERT_DupCertificate(cert);
3521
 
    if (cert == NULL)
3522
 
        goto loser;
3523
 
 
3524
 
    if (CERT_AddCertToListTail(certList, cert) != SECSuccess) {
3525
 
        CERT_DestroyCertificate(cert);
3526
 
        goto loser;
3527
 
    }
3528
 
 
3529
4660
    /*
3530
4661
     * XXX If/when signing of requests is supported, that second NULL
3531
4662
     * should be changed to be the signer certificate.  Not sure if that
3532
4663
     * should be passed into this function or retrieved via some operation
3533
4664
     * on the handle/context.
3534
4665
     */
3535
 
    encodedResponse = CERT_GetEncodedOCSPResponse(NULL, certList, location,
3536
 
                                                  time, locationIsDefault,
3537
 
                                                  NULL, pwArg, &request);
 
4666
    encodedResponse = 
 
4667
        ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert, location,
 
4668
                                                 time, locationIsDefault,
 
4669
                                                 pwArg, &request);
3538
4670
    if (encodedResponse == NULL) {
3539
 
        goto loser;
 
4671
        goto loser;
3540
4672
    }
3541
4673
 
3542
4674
    response = CERT_DecodeOCSPResponse(encodedResponse);
3575
4707
     * Again, we are only doing one request for one cert.
3576
4708
     * XXX When we handle cert chains, the following code will obviously
3577
4709
     * have to be modified, in coordation with the code above that will
3578
 
     * have to determine how to make multiple requests, etc.  It will need
3579
 
     * to loop, and for each certID in the request, find the matching
3580
 
     * single response and check the status specified by it.
3581
 
     *
3582
 
     * We are helped here in that we know that the requests are made with
3583
 
     * the request list in the same order as the order of the certs we hand
3584
 
     * to it.  This is why I can directly access the first member of the
3585
 
     * single request array for the one cert I care about.
 
4710
     * have to determine how to make multiple requests, etc. 
3586
4711
     */
3587
4712
 
3588
 
    certID = request->tbsRequest->requestList[0]->reqCert;
3589
 
    rv = CERT_GetOCSPStatusForCertID(handle, response, certID, 
3590
 
                                     signerCert, time);
 
4713
    rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, 
 
4714
                                                 signerCert, time, &single);
 
4715
    if (rv != SECSuccess)
 
4716
        goto loser;
 
4717
 
 
4718
    *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(single, time);
 
4719
 
3591
4720
loser:
 
4721
    PR_EnterMonitor(OCSP_Global.monitor);
 
4722
    if (OCSP_Global.maxCacheEntries >= 0) {
 
4723
        /* single == NULL means: remember response failure */
 
4724
        ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single, 
 
4725
                                      certIDWasConsumed);
 
4726
        /* ignore cache update failures */
 
4727
    }
 
4728
    PR_ExitMonitor(OCSP_Global.monitor);
 
4729
 
3592
4730
    if (issuerCert != NULL)
3593
4731
        CERT_DestroyCertificate(issuerCert);
3594
4732
    if (signerCert != NULL)
3599
4737
        CERT_DestroyOCSPRequest(request);
3600
4738
    if (encodedResponse != NULL)
3601
4739
        SECITEM_FreeItem(encodedResponse, PR_TRUE);
3602
 
    if (certList != NULL)
3603
 
        CERT_DestroyCertList(certList);
3604
4740
    if (location != NULL)
3605
4741
        PORT_Free(location);
3606
4742
    return rv;
3607
4743
}
3608
4744
 
3609
 
SECStatus
3610
 
CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle, 
3611
 
                            CERTOCSPResponse *response, 
3612
 
                            CERTOCSPCertID   *certID,
3613
 
                            CERTCertificate  *signerCert,
3614
 
                            int64             time)
 
4745
static SECStatus
 
4746
ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle, 
 
4747
                                        CERTOCSPResponse *response, 
 
4748
                                        CERTOCSPCertID   *certID,
 
4749
                                        CERTCertificate  *signerCert,
 
4750
                                        int64             time,
 
4751
                                        CERTOCSPSingleResponse 
 
4752
                                            **pSingleResponse)
3615
4753
{
3616
4754
    SECStatus rv;
3617
4755
    ocspResponseData *responseData;
3621
4759
    /*
3622
4760
     * The ResponseData part is the real guts of the response.
3623
4761
     */
3624
 
    responseData = ocsp_GetResponseData(response);
 
4762
    responseData = ocsp_GetResponseData(response, NULL);
3625
4763
    if (responseData == NULL) {
3626
 
        rv = SECFailure;
3627
 
        goto loser;
 
4764
        rv = SECFailure;
 
4765
        goto loser;
3628
4766
    }
3629
4767
 
3630
4768
    /*
3635
4773
     */
3636
4774
    rv = DER_GeneralizedTimeToTime(&producedAt, &responseData->producedAt);
3637
4775
    if (rv != SECSuccess)
3638
 
        goto loser;
 
4776
        goto loser;
3639
4777
 
3640
4778
    single = ocsp_GetSingleResponseForCertID(responseData->responses,
3641
 
                                             handle, certID);
 
4779
                                             handle, certID);
3642
4780
    if (single == NULL) {
3643
 
        rv = SECFailure;
3644
 
        goto loser;
 
4781
        rv = SECFailure;
 
4782
        goto loser;
3645
4783
    }
3646
4784
 
3647
4785
    rv = ocsp_VerifySingleResponse(single, handle, signerCert, producedAt);
3648
4786
    if (rv != SECSuccess)
3649
 
        goto loser;
3650
 
 
 
4787
        goto loser;
 
4788
    *pSingleResponse = single;
 
4789
 
 
4790
loser:
 
4791
    return rv;
 
4792
}
 
4793
 
 
4794
SECStatus
 
4795
CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle, 
 
4796
                            CERTOCSPResponse *response, 
 
4797
                            CERTOCSPCertID   *certID,
 
4798
                            CERTCertificate  *signerCert,
 
4799
                            int64             time)
 
4800
{
 
4801
    SECStatus rv;
 
4802
    CERTOCSPSingleResponse *single;
 
4803
 
 
4804
    rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, 
 
4805
                                                 signerCert, time, &single);
 
4806
    if (rv != SECSuccess)
 
4807
        return rv;
3651
4808
    /*
3652
4809
     * Okay, the last step is to check whether the status says revoked,
3653
4810
     * and if so how that compares to the time value passed into this routine.
3654
4811
     */
3655
 
 
3656
 
    rv = ocsp_CertHasGoodStatus(single, time);
3657
 
loser:
 
4812
    rv = ocsp_SingleResponseCertHasGoodStatus(single, time);
3658
4813
    return rv;
3659
4814
}
3660
4815
 
3661
 
 
3662
4816
/*
3663
4817
 * Disable status checking and destroy related structures/data.
3664
4818
 */
3731
4885
        return SECFailure;
3732
4886
    }
3733
4887
 
 
4888
    /* cache no longer necessary */
 
4889
    CERT_ClearOCSPCache();
 
4890
 
3734
4891
    /*
3735
4892
     * This is how we disable status checking.  Everything else remains
3736
4893
     * in place in case we are enabled again.
3935
5092
    if (statusContext->defaultResponderCert != NULL) {
3936
5093
        CERT_DestroyCertificate(statusContext->defaultResponderCert);
3937
5094
        statusContext->defaultResponderCert = cert;
 
5095
        /*OCSP enabled, switching responder: clear cache*/
 
5096
        CERT_ClearOCSPCache();
3938
5097
    } else {
3939
5098
        PORT_Assert(statusContext->useDefaultResponder == PR_FALSE);
3940
5099
        CERT_DestroyCertificate(cert);
 
5100
        /*OCSP currently not enabled, no need to clear cache*/
3941
5101
    }
3942
5102
 
3943
5103
    return SECSuccess;
3974
5134
{
3975
5135
    ocspCheckingContext *statusContext;
3976
5136
    CERTCertificate *cert;
 
5137
    SECStatus rv;
 
5138
    SECCertificateUsage usage;
3977
5139
 
3978
5140
    if (handle == NULL) {
3979
5141
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
4018
5180
    if (cert == NULL)
4019
5181
        return SECFailure;
4020
5182
 
 
5183
   /*
 
5184
    * Supplied cert should at least have  a signing capability in order for us
 
5185
    * to use it as a trusted responder cert. Ability to sign is guarantied  if
 
5186
    * cert is validated to have any set of the usages below.
 
5187
    */
 
5188
    rv = CERT_VerifyCertificateNow(handle, cert, PR_TRUE,
 
5189
                                   certificateUsageCheckAllUsages,
 
5190
                                   NULL, &usage);
 
5191
    if (rv != SECSuccess || (usage & (certificateUsageSSLClient |
 
5192
                                      certificateUsageSSLServer |
 
5193
                                      certificateUsageSSLServerWithStepUp |
 
5194
                                      certificateUsageEmailSigner |
 
5195
                                      certificateUsageObjectSigner |
 
5196
                                      certificateUsageStatusResponder |
 
5197
                                      certificateUsageSSLCA)) == 0) {
 
5198
        PORT_SetError(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID);
 
5199
        return SECFailure;
 
5200
    }
 
5201
 
4021
5202
    /*
4022
5203
     * And hang onto it.
4023
5204
     */
4024
5205
    statusContext->defaultResponderCert = cert;
4025
5206
 
 
5207
    /* we don't allow a mix of cache entries from different responders */
 
5208
    CERT_ClearOCSPCache();
 
5209
 
4026
5210
    /*
4027
5211
     * Finally, record the fact that we now have a default responder enabled.
4028
5212
     */
4048
5232
{
4049
5233
    CERTStatusConfig *statusConfig;
4050
5234
    ocspCheckingContext *statusContext;
 
5235
    CERTCertificate *tmpCert;
4051
5236
 
4052
5237
    if (handle == NULL) {
4053
5238
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
4063
5248
    if (statusContext == NULL)
4064
5249
        return SECFailure;
4065
5250
 
4066
 
    if (statusContext->defaultResponderCert != NULL) {
4067
 
        CERT_DestroyCertificate(statusContext->defaultResponderCert);
 
5251
    tmpCert = statusContext->defaultResponderCert;
 
5252
    if (tmpCert) {
4068
5253
        statusContext->defaultResponderCert = NULL;
 
5254
        CERT_DestroyCertificate(tmpCert);
 
5255
        /* we don't allow a mix of cache entries from different responders */
 
5256
        CERT_ClearOCSPCache();
4069
5257
    }
4070
5258
 
4071
5259
    /*
4075
5263
    return SECSuccess;
4076
5264
}
4077
5265
 
4078
 
/*
4079
 
 * Digest the cert's subject public key using the specified algorithm.
4080
 
 * The necessary storage for the digest data is allocated.  If "fill" is
4081
 
 * non-null, the data is put there, otherwise a SECItem is allocated.
4082
 
 * Allocation from "arena" if it is non-null, heap otherwise.  Any problem
4083
 
 * results in a NULL being returned (and an appropriate error set).
4084
 
 */
4085
 
SECItem *
4086
 
CERT_SPKDigestValueForCert(PRArenaPool *arena, CERTCertificate *cert,
4087
 
                           SECOidTag digestAlg, SECItem *fill)
4088
 
{
4089
 
    const SECHashObject *digestObject;
4090
 
    void *digestContext;
4091
 
    SECItem *result = NULL;
4092
 
    void *mark = NULL;
4093
 
    SECItem spk;
4094
 
 
4095
 
    if ( arena != NULL ) {
4096
 
        mark = PORT_ArenaMark(arena);
4097
 
    }
4098
 
 
4099
 
    digestObject = HASH_GetHashObjectByOidTag(digestAlg);
4100
 
    if ( digestObject == NULL ) {
4101
 
        goto loser;
4102
 
    }
4103
 
 
4104
 
    if ((fill == NULL) || (fill->data == NULL)) {
4105
 
        result = SECITEM_AllocItem(arena, fill, digestObject->length);
4106
 
        if ( result == NULL ) {
4107
 
           goto loser;
4108
 
        }
4109
 
        fill = result;
4110
 
    }
4111
 
 
4112
 
    /*
4113
 
     * Copy just the length and data pointer (nothing needs to be freed)
4114
 
     * of the subject public key so we can convert the length from bits
4115
 
     * to bytes, which is what the digest function expects.
4116
 
     */
4117
 
    spk = cert->subjectPublicKeyInfo.subjectPublicKey;
4118
 
    DER_ConvertBitString(&spk);
4119
 
 
4120
 
    /*
4121
 
     * Now digest the value, using the specified algorithm.
4122
 
     */
4123
 
    digestContext = digestObject->create();
4124
 
    if ( digestContext == NULL ) {
4125
 
        goto loser;
4126
 
    }
4127
 
    digestObject->begin(digestContext);
4128
 
    digestObject->update(digestContext, spk.data, spk.len);
4129
 
    digestObject->end(digestContext, fill->data, &(fill->len), fill->len);
4130
 
    digestObject->destroy(digestContext, PR_TRUE);
4131
 
 
4132
 
    if ( arena != NULL ) {
4133
 
        PORT_ArenaUnmark(arena, mark);
4134
 
    }
4135
 
    return(fill);
4136
 
 
4137
 
loser:
4138
 
    if ( arena != NULL ) {
4139
 
        PORT_ArenaRelease(arena, mark);
4140
 
    } else {
4141
 
        if ( result != NULL ) {
4142
 
            SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE);
4143
 
        }
4144
 
    }
4145
 
    return(NULL);
4146
 
}
4147
5266
 
4148
5267
SECStatus
4149
5268
CERT_GetOCSPResponseStatus(CERTOCSPResponse *response)