security/nss/lib/certhigh/ocsp.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial