Coverage Report

Created: 2018-09-25 14:53

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