/security/nss/lib/certhigh/ocsp.c

http://github.com/zpao/v8monkey · C · 5734 lines · 3549 code · 656 blank · 1529 comment · 913 complexity · 0c459ade7a54e7874d3c23421dab4cb9 MD5 · raw file

Large files are truncated click here to view the full file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Kai Engert (kengert@redhat.com)
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either the GNU General Public License Version 2 or later (the "GPL"), or
  26. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /*
  38. * Implementation of OCSP services, for both client and server.
  39. * (XXX, really, mostly just for client right now, but intended to do both.)
  40. *
  41. * $Id: ocsp.c,v 1.67 2011/08/10 12:31:52 kaie%kuix.de Exp $
  42. */
  43. #include "prerror.h"
  44. #include "prprf.h"
  45. #include "plarena.h"
  46. #include "prnetdb.h"
  47. #include "seccomon.h"
  48. #include "secitem.h"
  49. #include "secoidt.h"
  50. #include "secasn1.h"
  51. #include "secder.h"
  52. #include "cert.h"
  53. #include "xconst.h"
  54. #include "secerr.h"
  55. #include "secoid.h"
  56. #include "hasht.h"
  57. #include "sechash.h"
  58. #include "secasn1.h"
  59. #include "keyhi.h"
  60. #include "cryptohi.h"
  61. #include "ocsp.h"
  62. #include "ocspti.h"
  63. #include "ocspi.h"
  64. #include "genname.h"
  65. #include "certxutl.h"
  66. #include "pk11func.h" /* for PK11_HashBuf */
  67. #include <stdarg.h>
  68. #include <plhash.h>
  69. #define DEFAULT_OCSP_CACHE_SIZE 1000
  70. #define DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 1*60*60L
  71. #define DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 24*60*60L
  72. #define DEFAULT_OSCP_TIMEOUT_SECONDS 60
  73. #define MICROSECONDS_PER_SECOND 1000000L
  74. typedef struct OCSPCacheItemStr OCSPCacheItem;
  75. typedef struct OCSPCacheDataStr OCSPCacheData;
  76. struct OCSPCacheItemStr {
  77. /* LRU linking */
  78. OCSPCacheItem *moreRecent;
  79. OCSPCacheItem *lessRecent;
  80. /* key */
  81. CERTOCSPCertID *certID;
  82. /* CertID's arena also used to allocate "this" cache item */
  83. /* cache control information */
  84. PRTime nextFetchAttemptTime;
  85. /* Cached contents. Use a separate arena, because lifetime is different */
  86. PRArenaPool *certStatusArena; /* NULL means: no cert status cached */
  87. ocspCertStatus certStatus;
  88. /* This may contain an error code when no OCSP response is available. */
  89. SECErrorCodes missingResponseError;
  90. PRPackedBool haveThisUpdate;
  91. PRPackedBool haveNextUpdate;
  92. PRTime thisUpdate;
  93. PRTime nextUpdate;
  94. };
  95. struct OCSPCacheDataStr {
  96. PLHashTable *entries;
  97. PRUint32 numberOfEntries;
  98. OCSPCacheItem *MRUitem; /* most recently used cache item */
  99. OCSPCacheItem *LRUitem; /* least recently used cache item */
  100. };
  101. static struct OCSPGlobalStruct {
  102. PRMonitor *monitor;
  103. const SEC_HttpClientFcn *defaultHttpClientFcn;
  104. PRInt32 maxCacheEntries;
  105. PRUint32 minimumSecondsToNextFetchAttempt;
  106. PRUint32 maximumSecondsToNextFetchAttempt;
  107. PRUint32 timeoutSeconds;
  108. OCSPCacheData cache;
  109. SEC_OcspFailureMode ocspFailureMode;
  110. CERT_StringFromCertFcn alternateOCSPAIAFcn;
  111. } OCSP_Global = { NULL,
  112. NULL,
  113. DEFAULT_OCSP_CACHE_SIZE,
  114. DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT,
  115. DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT,
  116. DEFAULT_OSCP_TIMEOUT_SECONDS,
  117. {NULL, 0, NULL, NULL},
  118. ocspMode_FailureIsVerificationFailure,
  119. NULL
  120. };
  121. /* Forward declarations */
  122. static SECItem *
  123. ocsp_GetEncodedOCSPResponseFromRequest(PRArenaPool *arena,
  124. CERTOCSPRequest *request,
  125. char *location, int64 time,
  126. PRBool addServiceLocator,
  127. void *pwArg,
  128. CERTOCSPRequest **pRequest);
  129. static SECStatus
  130. ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle,
  131. CERTOCSPCertID *certID,
  132. CERTCertificate *cert,
  133. int64 time,
  134. void *pwArg,
  135. PRBool *certIDWasConsumed,
  136. SECStatus *rv_ocsp);
  137. static SECStatus
  138. ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle,
  139. CERTOCSPCertID *certID,
  140. CERTCertificate *cert,
  141. int64 time,
  142. void *pwArg,
  143. SECItem *encodedResponse,
  144. PRBool *certIDWasConsumed,
  145. PRBool cacheNegative,
  146. SECStatus *rv_ocsp);
  147. static SECStatus
  148. ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle,
  149. CERTOCSPResponse *response,
  150. CERTOCSPCertID *certID,
  151. CERTCertificate *signerCert,
  152. int64 time,
  153. CERTOCSPSingleResponse **pSingleResponse);
  154. static SECStatus
  155. ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, int64 time);
  156. #ifndef DEBUG
  157. #define OCSP_TRACE(msg)
  158. #define OCSP_TRACE_TIME(msg, time)
  159. #define OCSP_TRACE_CERT(cert)
  160. #define OCSP_TRACE_CERTID(certid)
  161. #else
  162. #define OCSP_TRACE(msg) ocsp_Trace msg
  163. #define OCSP_TRACE_TIME(msg, time) ocsp_dumpStringWithTime(msg, time)
  164. #define OCSP_TRACE_CERT(cert) dumpCertificate(cert)
  165. #define OCSP_TRACE_CERTID(certid) dumpCertID(certid)
  166. #if (defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS) \
  167. || defined(XP_MACOSX)) && !defined(_WIN32_WCE)
  168. #define NSS_HAVE_GETENV 1
  169. #endif
  170. static PRBool wantOcspTrace()
  171. {
  172. static PRBool firstTime = PR_TRUE;
  173. static PRBool wantTrace = PR_FALSE;
  174. #ifdef NSS_HAVE_GETENV
  175. if (firstTime) {
  176. char *ev = getenv("NSS_TRACE_OCSP");
  177. if (ev && ev[0]) {
  178. wantTrace = PR_TRUE;
  179. }
  180. firstTime = PR_FALSE;
  181. }
  182. #endif
  183. return wantTrace;
  184. }
  185. static void
  186. ocsp_Trace(const char *format, ...)
  187. {
  188. char buf[2000];
  189. va_list args;
  190. if (!wantOcspTrace())
  191. return;
  192. va_start(args, format);
  193. PR_vsnprintf(buf, sizeof(buf), format, args);
  194. va_end(args);
  195. PR_LogPrint("%s", buf);
  196. }
  197. static void
  198. ocsp_dumpStringWithTime(const char *str, int64 time)
  199. {
  200. PRExplodedTime timePrintable;
  201. char timestr[256];
  202. if (!wantOcspTrace())
  203. return;
  204. PR_ExplodeTime(time, PR_GMTParameters, &timePrintable);
  205. if (PR_FormatTime(timestr, 256, "%a %b %d %H:%M:%S %Y", &timePrintable)) {
  206. ocsp_Trace("OCSP %s %s\n", str, timestr);
  207. }
  208. }
  209. static void
  210. printHexString(const char *prefix, SECItem *hexval)
  211. {
  212. unsigned int i;
  213. char *hexbuf = NULL;
  214. for (i = 0; i < hexval->len; i++) {
  215. if (i != hexval->len - 1) {
  216. hexbuf = PR_sprintf_append(hexbuf, "%02x:", hexval->data[i]);
  217. } else {
  218. hexbuf = PR_sprintf_append(hexbuf, "%02x", hexval->data[i]);
  219. }
  220. }
  221. if (hexbuf) {
  222. ocsp_Trace("%s %s\n", prefix, hexbuf);
  223. PR_smprintf_free(hexbuf);
  224. }
  225. }
  226. static void
  227. dumpCertificate(CERTCertificate *cert)
  228. {
  229. if (!wantOcspTrace())
  230. return;
  231. ocsp_Trace("OCSP ----------------\n");
  232. ocsp_Trace("OCSP ## SUBJECT: %s\n", cert->subjectName);
  233. {
  234. int64 timeBefore, timeAfter;
  235. PRExplodedTime beforePrintable, afterPrintable;
  236. char beforestr[256], afterstr[256];
  237. PRStatus rv1, rv2;
  238. DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore);
  239. DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter);
  240. PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable);
  241. PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable);
  242. rv1 = PR_FormatTime(beforestr, 256, "%a %b %d %H:%M:%S %Y",
  243. &beforePrintable);
  244. rv2 = PR_FormatTime(afterstr, 256, "%a %b %d %H:%M:%S %Y",
  245. &afterPrintable);
  246. ocsp_Trace("OCSP ## VALIDITY: %s to %s\n", rv1 ? beforestr : "",
  247. rv2 ? afterstr : "");
  248. }
  249. ocsp_Trace("OCSP ## ISSUER: %s\n", cert->issuerName);
  250. printHexString("OCSP ## SERIAL NUMBER:", &cert->serialNumber);
  251. }
  252. static void
  253. dumpCertID(CERTOCSPCertID *certID)
  254. {
  255. if (!wantOcspTrace())
  256. return;
  257. printHexString("OCSP certID issuer", &certID->issuerNameHash);
  258. printHexString("OCSP certID serial", &certID->serialNumber);
  259. }
  260. #endif
  261. SECStatus
  262. SEC_RegisterDefaultHttpClient(const SEC_HttpClientFcn *fcnTable)
  263. {
  264. if (!OCSP_Global.monitor) {
  265. PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
  266. return SECFailure;
  267. }
  268. PR_EnterMonitor(OCSP_Global.monitor);
  269. OCSP_Global.defaultHttpClientFcn = fcnTable;
  270. PR_ExitMonitor(OCSP_Global.monitor);
  271. return SECSuccess;
  272. }
  273. SECStatus
  274. CERT_RegisterAlternateOCSPAIAInfoCallBack(
  275. CERT_StringFromCertFcn newCallback,
  276. CERT_StringFromCertFcn * oldCallback)
  277. {
  278. CERT_StringFromCertFcn old;
  279. if (!OCSP_Global.monitor) {
  280. PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
  281. return SECFailure;
  282. }
  283. PR_EnterMonitor(OCSP_Global.monitor);
  284. old = OCSP_Global.alternateOCSPAIAFcn;
  285. OCSP_Global.alternateOCSPAIAFcn = newCallback;
  286. PR_ExitMonitor(OCSP_Global.monitor);
  287. if (oldCallback)
  288. *oldCallback = old;
  289. return SECSuccess;
  290. }
  291. static PLHashNumber PR_CALLBACK
  292. ocsp_CacheKeyHashFunction(const void *key)
  293. {
  294. CERTOCSPCertID *cid = (CERTOCSPCertID *)key;
  295. PLHashNumber hash = 0;
  296. unsigned int i;
  297. unsigned char *walk;
  298. /* a very simple hash calculation for the initial coding phase */
  299. walk = (unsigned char*)cid->issuerNameHash.data;
  300. for (i=0; i < cid->issuerNameHash.len; ++i, ++walk) {
  301. hash += *walk;
  302. }
  303. walk = (unsigned char*)cid->issuerKeyHash.data;
  304. for (i=0; i < cid->issuerKeyHash.len; ++i, ++walk) {
  305. hash += *walk;
  306. }
  307. walk = (unsigned char*)cid->serialNumber.data;
  308. for (i=0; i < cid->serialNumber.len; ++i, ++walk) {
  309. hash += *walk;
  310. }
  311. return hash;
  312. }
  313. static PRIntn PR_CALLBACK
  314. ocsp_CacheKeyCompareFunction(const void *v1, const void *v2)
  315. {
  316. CERTOCSPCertID *cid1 = (CERTOCSPCertID *)v1;
  317. CERTOCSPCertID *cid2 = (CERTOCSPCertID *)v2;
  318. return (SECEqual == SECITEM_CompareItem(&cid1->issuerNameHash,
  319. &cid2->issuerNameHash)
  320. && SECEqual == SECITEM_CompareItem(&cid1->issuerKeyHash,
  321. &cid2->issuerKeyHash)
  322. && SECEqual == SECITEM_CompareItem(&cid1->serialNumber,
  323. &cid2->serialNumber));
  324. }
  325. static SECStatus
  326. ocsp_CopyRevokedInfo(PRArenaPool *arena, ocspCertStatus *dest,
  327. ocspRevokedInfo *src)
  328. {
  329. SECStatus rv = SECFailure;
  330. void *mark;
  331. mark = PORT_ArenaMark(arena);
  332. dest->certStatusInfo.revokedInfo =
  333. (ocspRevokedInfo *) PORT_ArenaZAlloc(arena, sizeof(ocspRevokedInfo));
  334. if (!dest->certStatusInfo.revokedInfo) {
  335. goto loser;
  336. }
  337. rv = SECITEM_CopyItem(arena,
  338. &dest->certStatusInfo.revokedInfo->revocationTime,
  339. &src->revocationTime);
  340. if (rv != SECSuccess) {
  341. goto loser;
  342. }
  343. if (src->revocationReason) {
  344. dest->certStatusInfo.revokedInfo->revocationReason =
  345. SECITEM_ArenaDupItem(arena, src->revocationReason);
  346. if (!dest->certStatusInfo.revokedInfo->revocationReason) {
  347. goto loser;
  348. }
  349. } else {
  350. dest->certStatusInfo.revokedInfo->revocationReason = NULL;
  351. }
  352. PORT_ArenaUnmark(arena, mark);
  353. return SECSuccess;
  354. loser:
  355. PORT_ArenaRelease(arena, mark);
  356. return SECFailure;
  357. }
  358. static SECStatus
  359. ocsp_CopyCertStatus(PRArenaPool *arena, ocspCertStatus *dest,
  360. ocspCertStatus*src)
  361. {
  362. SECStatus rv = SECFailure;
  363. dest->certStatusType = src->certStatusType;
  364. switch (src->certStatusType) {
  365. case ocspCertStatus_good:
  366. dest->certStatusInfo.goodInfo =
  367. SECITEM_ArenaDupItem(arena, src->certStatusInfo.goodInfo);
  368. if (dest->certStatusInfo.goodInfo != NULL) {
  369. rv = SECSuccess;
  370. }
  371. break;
  372. case ocspCertStatus_revoked:
  373. rv = ocsp_CopyRevokedInfo(arena, dest,
  374. src->certStatusInfo.revokedInfo);
  375. break;
  376. case ocspCertStatus_unknown:
  377. dest->certStatusInfo.unknownInfo =
  378. SECITEM_ArenaDupItem(arena, src->certStatusInfo.unknownInfo);
  379. if (dest->certStatusInfo.unknownInfo != NULL) {
  380. rv = SECSuccess;
  381. }
  382. break;
  383. case ocspCertStatus_other:
  384. default:
  385. PORT_Assert(src->certStatusType == ocspCertStatus_other);
  386. dest->certStatusInfo.otherInfo =
  387. SECITEM_ArenaDupItem(arena, src->certStatusInfo.otherInfo);
  388. if (dest->certStatusInfo.otherInfo != NULL) {
  389. rv = SECSuccess;
  390. }
  391. break;
  392. }
  393. return rv;
  394. }
  395. static void
  396. ocsp_AddCacheItemToLinkedList(OCSPCacheData *cache, OCSPCacheItem *new_most_recent)
  397. {
  398. PR_EnterMonitor(OCSP_Global.monitor);
  399. if (!cache->LRUitem) {
  400. cache->LRUitem = new_most_recent;
  401. }
  402. new_most_recent->lessRecent = cache->MRUitem;
  403. new_most_recent->moreRecent = NULL;
  404. if (cache->MRUitem) {
  405. cache->MRUitem->moreRecent = new_most_recent;
  406. }
  407. cache->MRUitem = new_most_recent;
  408. PR_ExitMonitor(OCSP_Global.monitor);
  409. }
  410. static void
  411. ocsp_RemoveCacheItemFromLinkedList(OCSPCacheData *cache, OCSPCacheItem *item)
  412. {
  413. PR_EnterMonitor(OCSP_Global.monitor);
  414. if (!item->lessRecent && !item->moreRecent) {
  415. /*
  416. * Fail gracefully on attempts to remove an item from the list,
  417. * which is currently not part of the list.
  418. * But check for the edge case it is the single entry in the list.
  419. */
  420. if (item == cache->LRUitem &&
  421. item == cache->MRUitem) {
  422. /* remove the single entry */
  423. PORT_Assert(cache->numberOfEntries == 1);
  424. PORT_Assert(item->moreRecent == NULL);
  425. cache->MRUitem = NULL;
  426. cache->LRUitem = NULL;
  427. }
  428. PR_ExitMonitor(OCSP_Global.monitor);
  429. return;
  430. }
  431. PORT_Assert(cache->numberOfEntries > 1);
  432. if (item == cache->LRUitem) {
  433. PORT_Assert(item != cache->MRUitem);
  434. PORT_Assert(item->lessRecent == NULL);
  435. PORT_Assert(item->moreRecent != NULL);
  436. PORT_Assert(item->moreRecent->lessRecent == item);
  437. cache->LRUitem = item->moreRecent;
  438. cache->LRUitem->lessRecent = NULL;
  439. }
  440. else if (item == cache->MRUitem) {
  441. PORT_Assert(item->moreRecent == NULL);
  442. PORT_Assert(item->lessRecent != NULL);
  443. PORT_Assert(item->lessRecent->moreRecent == item);
  444. cache->MRUitem = item->lessRecent;
  445. cache->MRUitem->moreRecent = NULL;
  446. } else {
  447. /* remove an entry in the middle of the list */
  448. PORT_Assert(item->moreRecent != NULL);
  449. PORT_Assert(item->lessRecent != NULL);
  450. PORT_Assert(item->lessRecent->moreRecent == item);
  451. PORT_Assert(item->moreRecent->lessRecent == item);
  452. item->moreRecent->lessRecent = item->lessRecent;
  453. item->lessRecent->moreRecent = item->moreRecent;
  454. }
  455. item->lessRecent = NULL;
  456. item->moreRecent = NULL;
  457. PR_ExitMonitor(OCSP_Global.monitor);
  458. }
  459. static void
  460. ocsp_MakeCacheEntryMostRecent(OCSPCacheData *cache, OCSPCacheItem *new_most_recent)
  461. {
  462. OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent THREADID %p\n",
  463. PR_GetCurrentThread()));
  464. PR_EnterMonitor(OCSP_Global.monitor);
  465. if (cache->MRUitem == new_most_recent) {
  466. OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent ALREADY MOST\n"));
  467. PR_ExitMonitor(OCSP_Global.monitor);
  468. return;
  469. }
  470. OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent NEW entry\n"));
  471. ocsp_RemoveCacheItemFromLinkedList(cache, new_most_recent);
  472. ocsp_AddCacheItemToLinkedList(cache, new_most_recent);
  473. PR_ExitMonitor(OCSP_Global.monitor);
  474. }
  475. static PRBool
  476. ocsp_IsCacheDisabled()
  477. {
  478. /*
  479. * maxCacheEntries == 0 means unlimited cache entries
  480. * maxCacheEntries < 0 means cache is disabled
  481. */
  482. PRBool retval;
  483. PR_EnterMonitor(OCSP_Global.monitor);
  484. retval = (OCSP_Global.maxCacheEntries < 0);
  485. PR_ExitMonitor(OCSP_Global.monitor);
  486. return retval;
  487. }
  488. static OCSPCacheItem *
  489. ocsp_FindCacheEntry(OCSPCacheData *cache, CERTOCSPCertID *certID)
  490. {
  491. OCSPCacheItem *found_ocsp_item = NULL;
  492. OCSP_TRACE(("OCSP ocsp_FindCacheEntry\n"));
  493. OCSP_TRACE_CERTID(certID);
  494. PR_EnterMonitor(OCSP_Global.monitor);
  495. if (ocsp_IsCacheDisabled())
  496. goto loser;
  497. found_ocsp_item = (OCSPCacheItem *)PL_HashTableLookup(
  498. cache->entries, certID);
  499. if (!found_ocsp_item)
  500. goto loser;
  501. OCSP_TRACE(("OCSP ocsp_FindCacheEntry FOUND!\n"));
  502. ocsp_MakeCacheEntryMostRecent(cache, found_ocsp_item);
  503. loser:
  504. PR_ExitMonitor(OCSP_Global.monitor);
  505. return found_ocsp_item;
  506. }
  507. static void
  508. ocsp_FreeCacheItem(OCSPCacheItem *item)
  509. {
  510. OCSP_TRACE(("OCSP ocsp_FreeCacheItem\n"));
  511. if (item->certStatusArena) {
  512. PORT_FreeArena(item->certStatusArena, PR_FALSE);
  513. }
  514. if (item->certID->poolp) {
  515. /* freeing this poolp arena will also free item */
  516. PORT_FreeArena(item->certID->poolp, PR_FALSE);
  517. }
  518. }
  519. static void
  520. ocsp_RemoveCacheItem(OCSPCacheData *cache, OCSPCacheItem *item)
  521. {
  522. /* The item we're removing could be either the least recently used item,
  523. * or it could be an item that couldn't get updated with newer status info
  524. * because of an allocation failure, or it could get removed because we're
  525. * cleaning up.
  526. */
  527. PRBool couldRemoveFromHashTable;
  528. OCSP_TRACE(("OCSP ocsp_RemoveCacheItem, THREADID %p\n", PR_GetCurrentThread()));
  529. PR_EnterMonitor(OCSP_Global.monitor);
  530. ocsp_RemoveCacheItemFromLinkedList(cache, item);
  531. couldRemoveFromHashTable = PL_HashTableRemove(cache->entries,
  532. item->certID);
  533. PORT_Assert(couldRemoveFromHashTable);
  534. --cache->numberOfEntries;
  535. ocsp_FreeCacheItem(item);
  536. PR_ExitMonitor(OCSP_Global.monitor);
  537. }
  538. static void
  539. ocsp_CheckCacheSize(OCSPCacheData *cache)
  540. {
  541. OCSP_TRACE(("OCSP ocsp_CheckCacheSize\n"));
  542. PR_EnterMonitor(OCSP_Global.monitor);
  543. if (OCSP_Global.maxCacheEntries > 0) {
  544. /* Cache is not disabled. Number of cache entries is limited.
  545. * The monitor ensures that maxCacheEntries remains positive.
  546. */
  547. while (cache->numberOfEntries >
  548. (PRUint32)OCSP_Global.maxCacheEntries) {
  549. ocsp_RemoveCacheItem(cache, cache->LRUitem);
  550. }
  551. }
  552. PR_ExitMonitor(OCSP_Global.monitor);
  553. }
  554. SECStatus
  555. CERT_ClearOCSPCache()
  556. {
  557. OCSP_TRACE(("OCSP CERT_ClearOCSPCache\n"));
  558. PR_EnterMonitor(OCSP_Global.monitor);
  559. while (OCSP_Global.cache.numberOfEntries > 0) {
  560. ocsp_RemoveCacheItem(&OCSP_Global.cache,
  561. OCSP_Global.cache.LRUitem);
  562. }
  563. PR_ExitMonitor(OCSP_Global.monitor);
  564. return SECSuccess;
  565. }
  566. static SECStatus
  567. ocsp_CreateCacheItemAndConsumeCertID(OCSPCacheData *cache,
  568. CERTOCSPCertID *certID,
  569. OCSPCacheItem **pCacheItem)
  570. {
  571. PRArenaPool *arena;
  572. void *mark;
  573. PLHashEntry *new_hash_entry;
  574. OCSPCacheItem *item;
  575. PORT_Assert(pCacheItem != NULL);
  576. *pCacheItem = NULL;
  577. PR_EnterMonitor(OCSP_Global.monitor);
  578. arena = certID->poolp;
  579. mark = PORT_ArenaMark(arena);
  580. /* ZAlloc will init all Bools to False and all Pointers to NULL
  581. and all error codes to zero/good. */
  582. item = (OCSPCacheItem *)PORT_ArenaZAlloc(certID->poolp,
  583. sizeof(OCSPCacheItem));
  584. if (!item) {
  585. goto loser;
  586. }
  587. item->certID = certID;
  588. new_hash_entry = PL_HashTableAdd(cache->entries, item->certID,
  589. item);
  590. if (!new_hash_entry) {
  591. goto loser;
  592. }
  593. ++cache->numberOfEntries;
  594. PORT_ArenaUnmark(arena, mark);
  595. ocsp_AddCacheItemToLinkedList(cache, item);
  596. *pCacheItem = item;
  597. PR_ExitMonitor(OCSP_Global.monitor);
  598. return SECSuccess;
  599. loser:
  600. PORT_ArenaRelease(arena, mark);
  601. PR_ExitMonitor(OCSP_Global.monitor);
  602. return SECFailure;
  603. }
  604. static SECStatus
  605. ocsp_SetCacheItemResponse(OCSPCacheItem *item,
  606. const CERTOCSPSingleResponse *response)
  607. {
  608. if (item->certStatusArena) {
  609. PORT_FreeArena(item->certStatusArena, PR_FALSE);
  610. item->certStatusArena = NULL;
  611. }
  612. item->haveThisUpdate = item->haveNextUpdate = PR_FALSE;
  613. if (response) {
  614. SECStatus rv;
  615. item->certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  616. if (item->certStatusArena == NULL) {
  617. return SECFailure;
  618. }
  619. rv = ocsp_CopyCertStatus(item->certStatusArena, &item->certStatus,
  620. response->certStatus);
  621. if (rv != SECSuccess) {
  622. PORT_FreeArena(item->certStatusArena, PR_FALSE);
  623. item->certStatusArena = NULL;
  624. return rv;
  625. }
  626. item->missingResponseError = 0;
  627. rv = DER_GeneralizedTimeToTime(&item->thisUpdate,
  628. &response->thisUpdate);
  629. item->haveThisUpdate = (rv == SECSuccess);
  630. if (response->nextUpdate) {
  631. rv = DER_GeneralizedTimeToTime(&item->nextUpdate,
  632. response->nextUpdate);
  633. item->haveNextUpdate = (rv == SECSuccess);
  634. } else {
  635. item->haveNextUpdate = PR_FALSE;
  636. }
  637. }
  638. return SECSuccess;
  639. }
  640. static void
  641. ocsp_FreshenCacheItemNextFetchAttemptTime(OCSPCacheItem *cacheItem)
  642. {
  643. PRTime now;
  644. PRTime earliestAllowedNextFetchAttemptTime;
  645. PRTime latestTimeWhenResponseIsConsideredFresh;
  646. OCSP_TRACE(("OCSP ocsp_FreshenCacheItemNextFetchAttemptTime\n"));
  647. PR_EnterMonitor(OCSP_Global.monitor);
  648. now = PR_Now();
  649. OCSP_TRACE_TIME("now:", now);
  650. if (cacheItem->haveThisUpdate) {
  651. OCSP_TRACE_TIME("thisUpdate:", cacheItem->thisUpdate);
  652. latestTimeWhenResponseIsConsideredFresh = cacheItem->thisUpdate +
  653. OCSP_Global.maximumSecondsToNextFetchAttempt *
  654. MICROSECONDS_PER_SECOND;
  655. OCSP_TRACE_TIME("latestTimeWhenResponseIsConsideredFresh:",
  656. latestTimeWhenResponseIsConsideredFresh);
  657. } else {
  658. latestTimeWhenResponseIsConsideredFresh = now +
  659. OCSP_Global.minimumSecondsToNextFetchAttempt *
  660. MICROSECONDS_PER_SECOND;
  661. OCSP_TRACE_TIME("no thisUpdate, "
  662. "latestTimeWhenResponseIsConsideredFresh:",
  663. latestTimeWhenResponseIsConsideredFresh);
  664. }
  665. if (cacheItem->haveNextUpdate) {
  666. OCSP_TRACE_TIME("have nextUpdate:", cacheItem->nextUpdate);
  667. }
  668. if (cacheItem->haveNextUpdate &&
  669. cacheItem->nextUpdate < latestTimeWhenResponseIsConsideredFresh) {
  670. latestTimeWhenResponseIsConsideredFresh = cacheItem->nextUpdate;
  671. OCSP_TRACE_TIME("nextUpdate is smaller than latestFresh, setting "
  672. "latestTimeWhenResponseIsConsideredFresh:",
  673. latestTimeWhenResponseIsConsideredFresh);
  674. }
  675. earliestAllowedNextFetchAttemptTime = now +
  676. OCSP_Global.minimumSecondsToNextFetchAttempt *
  677. MICROSECONDS_PER_SECOND;
  678. OCSP_TRACE_TIME("earliestAllowedNextFetchAttemptTime:",
  679. earliestAllowedNextFetchAttemptTime);
  680. if (latestTimeWhenResponseIsConsideredFresh <
  681. earliestAllowedNextFetchAttemptTime) {
  682. latestTimeWhenResponseIsConsideredFresh =
  683. earliestAllowedNextFetchAttemptTime;
  684. OCSP_TRACE_TIME("latest < earliest, setting latest to:",
  685. latestTimeWhenResponseIsConsideredFresh);
  686. }
  687. cacheItem->nextFetchAttemptTime =
  688. latestTimeWhenResponseIsConsideredFresh;
  689. OCSP_TRACE_TIME("nextFetchAttemptTime",
  690. latestTimeWhenResponseIsConsideredFresh);
  691. PR_ExitMonitor(OCSP_Global.monitor);
  692. }
  693. static PRBool
  694. ocsp_IsCacheItemFresh(OCSPCacheItem *cacheItem)
  695. {
  696. PRTime now;
  697. PRBool retval;
  698. PR_EnterMonitor(OCSP_Global.monitor);
  699. now = PR_Now();
  700. retval = (cacheItem->nextFetchAttemptTime > now);
  701. OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", retval));
  702. PR_ExitMonitor(OCSP_Global.monitor);
  703. return retval;
  704. }
  705. /*
  706. * Status in *certIDWasConsumed will always be correct, regardless of
  707. * return value.
  708. */
  709. static SECStatus
  710. ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache,
  711. CERTOCSPCertID *certID,
  712. CERTOCSPSingleResponse *single,
  713. PRBool *certIDWasConsumed)
  714. {
  715. SECStatus rv;
  716. OCSPCacheItem *cacheItem;
  717. OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n"));
  718. if (!certIDWasConsumed) {
  719. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  720. return SECFailure;
  721. }
  722. *certIDWasConsumed = PR_FALSE;
  723. PR_EnterMonitor(OCSP_Global.monitor);
  724. PORT_Assert(OCSP_Global.maxCacheEntries >= 0);
  725. cacheItem = ocsp_FindCacheEntry(cache, certID);
  726. if (!cacheItem) {
  727. rv = ocsp_CreateCacheItemAndConsumeCertID(cache, certID,
  728. &cacheItem);
  729. if (rv != SECSuccess) {
  730. PR_ExitMonitor(OCSP_Global.monitor);
  731. return rv;
  732. }
  733. *certIDWasConsumed = PR_TRUE;
  734. }
  735. if (single) {
  736. rv = ocsp_SetCacheItemResponse(cacheItem, single);
  737. if (rv != SECSuccess) {
  738. ocsp_RemoveCacheItem(cache, cacheItem);
  739. PR_ExitMonitor(OCSP_Global.monitor);
  740. return rv;
  741. }
  742. } else {
  743. cacheItem->missingResponseError = PORT_GetError();
  744. }
  745. ocsp_FreshenCacheItemNextFetchAttemptTime(cacheItem);
  746. ocsp_CheckCacheSize(cache);
  747. PR_ExitMonitor(OCSP_Global.monitor);
  748. return SECSuccess;
  749. }
  750. extern SECStatus
  751. CERT_SetOCSPFailureMode(SEC_OcspFailureMode ocspFailureMode)
  752. {
  753. switch (ocspFailureMode) {
  754. case ocspMode_FailureIsVerificationFailure:
  755. case ocspMode_FailureIsNotAVerificationFailure:
  756. break;
  757. default:
  758. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  759. return SECFailure;
  760. }
  761. PR_EnterMonitor(OCSP_Global.monitor);
  762. OCSP_Global.ocspFailureMode = ocspFailureMode;
  763. PR_ExitMonitor(OCSP_Global.monitor);
  764. return SECSuccess;
  765. }
  766. SECStatus
  767. CERT_OCSPCacheSettings(PRInt32 maxCacheEntries,
  768. PRUint32 minimumSecondsToNextFetchAttempt,
  769. PRUint32 maximumSecondsToNextFetchAttempt)
  770. {
  771. if (minimumSecondsToNextFetchAttempt > maximumSecondsToNextFetchAttempt
  772. || maxCacheEntries < -1) {
  773. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  774. return SECFailure;
  775. }
  776. PR_EnterMonitor(OCSP_Global.monitor);
  777. if (maxCacheEntries < 0) {
  778. OCSP_Global.maxCacheEntries = -1; /* disable cache */
  779. } else if (maxCacheEntries == 0) {
  780. OCSP_Global.maxCacheEntries = 0; /* unlimited cache entries */
  781. } else {
  782. OCSP_Global.maxCacheEntries = maxCacheEntries;
  783. }
  784. if (minimumSecondsToNextFetchAttempt <
  785. OCSP_Global.minimumSecondsToNextFetchAttempt
  786. || maximumSecondsToNextFetchAttempt <
  787. OCSP_Global.maximumSecondsToNextFetchAttempt) {
  788. /*
  789. * Ensure our existing cache entries are not used longer than the
  790. * new settings allow, we're lazy and just clear the cache
  791. */
  792. CERT_ClearOCSPCache();
  793. }
  794. OCSP_Global.minimumSecondsToNextFetchAttempt =
  795. minimumSecondsToNextFetchAttempt;
  796. OCSP_Global.maximumSecondsToNextFetchAttempt =
  797. maximumSecondsToNextFetchAttempt;
  798. ocsp_CheckCacheSize(&OCSP_Global.cache);
  799. PR_ExitMonitor(OCSP_Global.monitor);
  800. return SECSuccess;
  801. }
  802. SECStatus
  803. CERT_SetOCSPTimeout(PRUint32 seconds)
  804. {
  805. /* no locking, see bug 406120 */
  806. OCSP_Global.timeoutSeconds = seconds;
  807. return SECSuccess;
  808. }
  809. /* this function is called at NSS initialization time */
  810. SECStatus OCSP_InitGlobal(void)
  811. {
  812. SECStatus rv = SECFailure;
  813. if (OCSP_Global.monitor == NULL) {
  814. OCSP_Global.monitor = PR_NewMonitor();
  815. }
  816. if (!OCSP_Global.monitor)
  817. return SECFailure;
  818. PR_EnterMonitor(OCSP_Global.monitor);
  819. if (!OCSP_Global.cache.entries) {
  820. OCSP_Global.cache.entries =
  821. PL_NewHashTable(0,
  822. ocsp_CacheKeyHashFunction,
  823. ocsp_CacheKeyCompareFunction,
  824. PL_CompareValues,
  825. NULL,
  826. NULL);
  827. OCSP_Global.ocspFailureMode = ocspMode_FailureIsVerificationFailure;
  828. OCSP_Global.cache.numberOfEntries = 0;
  829. OCSP_Global.cache.MRUitem = NULL;
  830. OCSP_Global.cache.LRUitem = NULL;
  831. } else {
  832. /*
  833. * NSS might call this function twice while attempting to init.
  834. * But it's not allowed to call this again after any activity.
  835. */
  836. PORT_Assert(OCSP_Global.cache.numberOfEntries == 0);
  837. PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
  838. }
  839. if (OCSP_Global.cache.entries)
  840. rv = SECSuccess;
  841. PR_ExitMonitor(OCSP_Global.monitor);
  842. return rv;
  843. }
  844. SECStatus OCSP_ShutdownGlobal(void)
  845. {
  846. if (!OCSP_Global.monitor)
  847. return SECSuccess;
  848. PR_EnterMonitor(OCSP_Global.monitor);
  849. if (OCSP_Global.cache.entries) {
  850. CERT_ClearOCSPCache();
  851. PL_HashTableDestroy(OCSP_Global.cache.entries);
  852. OCSP_Global.cache.entries = NULL;
  853. }
  854. PORT_Assert(OCSP_Global.cache.numberOfEntries == 0);
  855. OCSP_Global.cache.MRUitem = NULL;
  856. OCSP_Global.cache.LRUitem = NULL;
  857. OCSP_Global.defaultHttpClientFcn = NULL;
  858. OCSP_Global.maxCacheEntries = DEFAULT_OCSP_CACHE_SIZE;
  859. OCSP_Global.minimumSecondsToNextFetchAttempt =
  860. DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT;
  861. OCSP_Global.maximumSecondsToNextFetchAttempt =
  862. DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT;
  863. OCSP_Global.ocspFailureMode =
  864. ocspMode_FailureIsVerificationFailure;
  865. PR_ExitMonitor(OCSP_Global.monitor);
  866. PR_DestroyMonitor(OCSP_Global.monitor);
  867. OCSP_Global.monitor = NULL;
  868. return SECSuccess;
  869. }
  870. /*
  871. * A return value of NULL means:
  872. * The application did not register it's own HTTP client.
  873. */
  874. const SEC_HttpClientFcn *SEC_GetRegisteredHttpClient()
  875. {
  876. const SEC_HttpClientFcn *retval;
  877. if (!OCSP_Global.monitor) {
  878. PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
  879. return NULL;
  880. }
  881. PR_EnterMonitor(OCSP_Global.monitor);
  882. retval = OCSP_Global.defaultHttpClientFcn;
  883. PR_ExitMonitor(OCSP_Global.monitor);
  884. return retval;
  885. }
  886. /*
  887. * The following structure is only used internally. It is allocated when
  888. * someone turns on OCSP checking, and hangs off of the status-configuration
  889. * structure in the certdb structure. We use it to keep configuration
  890. * information specific to OCSP checking.
  891. */
  892. typedef struct ocspCheckingContextStr {
  893. PRBool useDefaultResponder;
  894. char *defaultResponderURI;
  895. char *defaultResponderNickname;
  896. CERTCertificate *defaultResponderCert;
  897. } ocspCheckingContext;
  898. SEC_ASN1_MKSUB(SEC_AnyTemplate)
  899. SEC_ASN1_MKSUB(SEC_IntegerTemplate)
  900. SEC_ASN1_MKSUB(SEC_NullTemplate)
  901. SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
  902. SEC_ASN1_MKSUB(SEC_PointerToAnyTemplate)
  903. SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
  904. SEC_ASN1_MKSUB(SEC_SequenceOfAnyTemplate)
  905. SEC_ASN1_MKSUB(SEC_PointerToGeneralizedTimeTemplate)
  906. SEC_ASN1_MKSUB(SEC_PointerToEnumeratedTemplate)
  907. /*
  908. * Forward declarations of sub-types, so I can lay out the types in the
  909. * same order as the ASN.1 is laid out in the OCSP spec itself.
  910. *
  911. * These are in alphabetical order (case-insensitive); please keep it that way!
  912. */
  913. extern const SEC_ASN1Template ocsp_CertIDTemplate[];
  914. extern const SEC_ASN1Template ocsp_PointerToSignatureTemplate[];
  915. extern const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[];
  916. extern const SEC_ASN1Template ocsp_ResponseDataTemplate[];
  917. extern const SEC_ASN1Template ocsp_RevokedInfoTemplate[];
  918. extern const SEC_ASN1Template ocsp_SingleRequestTemplate[];
  919. extern const SEC_ASN1Template ocsp_SingleResponseTemplate[];
  920. extern const SEC_ASN1Template ocsp_TBSRequestTemplate[];
  921. /*
  922. * Request-related templates...
  923. */
  924. /*
  925. * OCSPRequest ::= SEQUENCE {
  926. * tbsRequest TBSRequest,
  927. * optionalSignature [0] EXPLICIT Signature OPTIONAL }
  928. */
  929. static const SEC_ASN1Template ocsp_OCSPRequestTemplate[] = {
  930. { SEC_ASN1_SEQUENCE,
  931. 0, NULL, sizeof(CERTOCSPRequest) },
  932. { SEC_ASN1_POINTER,
  933. offsetof(CERTOCSPRequest, tbsRequest),
  934. ocsp_TBSRequestTemplate },
  935. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  936. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  937. offsetof(CERTOCSPRequest, optionalSignature),
  938. ocsp_PointerToSignatureTemplate },
  939. { 0 }
  940. };
  941. /*
  942. * TBSRequest ::= SEQUENCE {
  943. * version [0] EXPLICIT Version DEFAULT v1,
  944. * requestorName [1] EXPLICIT GeneralName OPTIONAL,
  945. * requestList SEQUENCE OF Request,
  946. * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
  947. *
  948. * Version ::= INTEGER { v1(0) }
  949. *
  950. * Note: this should be static but the AIX compiler doesn't like it (because it
  951. * was forward-declared above); it is not meant to be exported, but this
  952. * is the only way it will compile.
  953. */
  954. const SEC_ASN1Template ocsp_TBSRequestTemplate[] = {
  955. { SEC_ASN1_SEQUENCE,
  956. 0, NULL, sizeof(ocspTBSRequest) },
  957. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */
  958. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
  959. offsetof(ocspTBSRequest, version),
  960. SEC_ASN1_SUB(SEC_IntegerTemplate) },
  961. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  962. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
  963. offsetof(ocspTBSRequest, derRequestorName),
  964. SEC_ASN1_SUB(SEC_PointerToAnyTemplate) },
  965. { SEC_ASN1_SEQUENCE_OF,
  966. offsetof(ocspTBSRequest, requestList),
  967. ocsp_SingleRequestTemplate },
  968. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  969. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2,
  970. offsetof(ocspTBSRequest, requestExtensions),
  971. CERT_SequenceOfCertExtensionTemplate },
  972. { 0 }
  973. };
  974. /*
  975. * Signature ::= SEQUENCE {
  976. * signatureAlgorithm AlgorithmIdentifier,
  977. * signature BIT STRING,
  978. * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
  979. */
  980. static const SEC_ASN1Template ocsp_SignatureTemplate[] = {
  981. { SEC_ASN1_SEQUENCE,
  982. 0, NULL, sizeof(ocspSignature) },
  983. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  984. offsetof(ocspSignature, signatureAlgorithm),
  985. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  986. { SEC_ASN1_BIT_STRING,
  987. offsetof(ocspSignature, signature) },
  988. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  989. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
  990. offsetof(ocspSignature, derCerts),
  991. SEC_ASN1_SUB(SEC_SequenceOfAnyTemplate) },
  992. { 0 }
  993. };
  994. /*
  995. * This template is just an extra level to use in an explicitly-tagged
  996. * reference to a Signature.
  997. *
  998. * Note: this should be static but the AIX compiler doesn't like it (because it
  999. * was forward-declared above); it is not meant to be exported, but this
  1000. * is the only way it will compile.
  1001. */
  1002. const SEC_ASN1Template ocsp_PointerToSignatureTemplate[] = {
  1003. { SEC_ASN1_POINTER, 0, ocsp_SignatureTemplate }
  1004. };
  1005. /*
  1006. * Request ::= SEQUENCE {
  1007. * reqCert CertID,
  1008. * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
  1009. *
  1010. * Note: this should be static but the AIX compiler doesn't like it (because it
  1011. * was forward-declared above); it is not meant to be exported, but this
  1012. * is the only way it will compile.
  1013. */
  1014. const SEC_ASN1Template ocsp_SingleRequestTemplate[] = {
  1015. { SEC_ASN1_SEQUENCE,
  1016. 0, NULL, sizeof(ocspSingleRequest) },
  1017. { SEC_ASN1_POINTER,
  1018. offsetof(ocspSingleRequest, reqCert),
  1019. ocsp_CertIDTemplate },
  1020. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  1021. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  1022. offsetof(ocspSingleRequest, singleRequestExtensions),
  1023. CERT_SequenceOfCertExtensionTemplate },
  1024. { 0 }
  1025. };
  1026. /*
  1027. * This data structure and template (CertID) is used by both OCSP
  1028. * requests and responses. It is the only one that is shared.
  1029. *
  1030. * CertID ::= SEQUENCE {
  1031. * hashAlgorithm AlgorithmIdentifier,
  1032. * issuerNameHash OCTET STRING, -- Hash of Issuer DN
  1033. * issuerKeyHash OCTET STRING, -- Hash of Issuer public key
  1034. * serialNumber CertificateSerialNumber }
  1035. *
  1036. * CertificateSerialNumber ::= INTEGER
  1037. *
  1038. * Note: this should be static but the AIX compiler doesn't like it (because it
  1039. * was forward-declared above); it is not meant to be exported, but this
  1040. * is the only way it will compile.
  1041. */
  1042. const SEC_ASN1Template ocsp_CertIDTemplate[] = {
  1043. { SEC_ASN1_SEQUENCE,
  1044. 0, NULL, sizeof(CERTOCSPCertID) },
  1045. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  1046. offsetof(CERTOCSPCertID, hashAlgorithm),
  1047. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1048. { SEC_ASN1_OCTET_STRING,
  1049. offsetof(CERTOCSPCertID, issuerNameHash) },
  1050. { SEC_ASN1_OCTET_STRING,
  1051. offsetof(CERTOCSPCertID, issuerKeyHash) },
  1052. { SEC_ASN1_INTEGER,
  1053. offsetof(CERTOCSPCertID, serialNumber) },
  1054. { 0 }
  1055. };
  1056. /*
  1057. * Response-related templates...
  1058. */
  1059. /*
  1060. * OCSPResponse ::= SEQUENCE {
  1061. * responseStatus OCSPResponseStatus,
  1062. * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
  1063. */
  1064. static const SEC_ASN1Template ocsp_OCSPResponseTemplate[] = {
  1065. { SEC_ASN1_SEQUENCE,
  1066. 0, NULL, sizeof(CERTOCSPResponse) },
  1067. { SEC_ASN1_ENUMERATED,
  1068. offsetof(CERTOCSPResponse, responseStatus) },
  1069. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  1070. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  1071. offsetof(CERTOCSPResponse, responseBytes),
  1072. ocsp_PointerToResponseBytesTemplate },
  1073. { 0 }
  1074. };
  1075. /*
  1076. * ResponseBytes ::= SEQUENCE {
  1077. * responseType OBJECT IDENTIFIER,
  1078. * response OCTET STRING }
  1079. */
  1080. static const SEC_ASN1Template ocsp_ResponseBytesTemplate[] = {
  1081. { SEC_ASN1_SEQUENCE,
  1082. 0, NULL, sizeof(ocspResponseBytes) },
  1083. { SEC_ASN1_OBJECT_ID,
  1084. offsetof(ocspResponseBytes, responseType) },
  1085. { SEC_ASN1_OCTET_STRING,
  1086. offsetof(ocspResponseBytes, response) },
  1087. { 0 }
  1088. };
  1089. /*
  1090. * This template is just an extra level to use in an explicitly-tagged
  1091. * reference to a ResponseBytes.
  1092. *
  1093. * Note: this should be static but the AIX compiler doesn't like it (because it
  1094. * was forward-declared above); it is not meant to be exported, but this
  1095. * is the only way it will compile.
  1096. */
  1097. const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[] = {
  1098. { SEC_ASN1_POINTER, 0, ocsp_ResponseBytesTemplate }
  1099. };
  1100. /*
  1101. * BasicOCSPResponse ::= SEQUENCE {
  1102. * tbsResponseData ResponseData,
  1103. * signatureAlgorithm AlgorithmIdentifier,
  1104. * signature BIT STRING,
  1105. * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
  1106. */
  1107. static const SEC_ASN1Template ocsp_BasicOCSPResponseTemplate[] = {
  1108. { SEC_ASN1_SEQUENCE,
  1109. 0, NULL, sizeof(ocspBasicOCSPResponse) },
  1110. { SEC_ASN1_ANY | SEC_ASN1_SAVE,
  1111. offsetof(ocspBasicOCSPResponse, tbsResponseDataDER) },
  1112. { SEC_ASN1_POINTER,
  1113. offsetof(ocspBasicOCSPResponse, tbsResponseData),
  1114. ocsp_ResponseDataTemplate },
  1115. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  1116. offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm),
  1117. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1118. { SEC_ASN1_BIT_STRING,
  1119. offsetof(ocspBasicOCSPResponse, responseSignature.signature) },
  1120. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  1121. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
  1122. offsetof(ocspBasicOCSPResponse, responseSignature.derCerts),
  1123. SEC_ASN1_SUB(SEC_SequenceOfAnyTemplate) },
  1124. { 0 }
  1125. };
  1126. /*
  1127. * ResponseData ::= SEQUENCE {
  1128. * version [0] EXPLICIT Version DEFAULT v1,
  1129. * responderID ResponderID,
  1130. * producedAt GeneralizedTime,
  1131. * responses SEQUENCE OF SingleResponse,
  1132. * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
  1133. *
  1134. * Note: this should be static but the AIX compiler doesn't like it (because it
  1135. * was forward-declared above); it is not meant to be exported, but this
  1136. * is the only way it will compile.
  1137. */
  1138. const SEC_ASN1Template ocsp_ResponseDataTemplate[] = {
  1139. { SEC_ASN1_SEQUENCE,
  1140. 0, NULL, sizeof(ocspResponseData) },
  1141. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */
  1142. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
  1143. offsetof(ocspResponseData, version),
  1144. SEC_ASN1_SUB(SEC_IntegerTemplate) },
  1145. { SEC_ASN1_ANY,
  1146. offsetof(ocspResponseData, derResponderID) },
  1147. { SEC_ASN1_GENERALIZED_TIME,
  1148. offsetof(ocspResponseData, producedAt) },
  1149. { SEC_ASN1_SEQUENCE_OF,
  1150. offsetof(ocspResponseData, responses),
  1151. ocsp_SingleResponseTemplate },
  1152. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  1153. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
  1154. offsetof(ocspResponseData, responseExtensions),
  1155. CERT_SequenceOfCertExtensionTemplate },
  1156. { 0 }
  1157. };
  1158. /*
  1159. * ResponderID ::= CHOICE {
  1160. * byName [1] EXPLICIT Name,
  1161. * byKey [2] EXPLICIT KeyHash }
  1162. *
  1163. * KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
  1164. * (excluding the tag and length fields)
  1165. *
  1166. * XXX Because the ASN.1 encoder and decoder currently do not provide
  1167. * a way to automatically handle a CHOICE, we need to do it in two
  1168. * steps, looking at the type tag and feeding the exact choice back
  1169. * to the ASN.1 code. Hopefully that will change someday and this
  1170. * can all be simplified down into a single template. Anyway, for
  1171. * now we list each choice as its own template:
  1172. */
  1173. static const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[] = {
  1174. { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
  1175. offsetof(ocspResponderID, responderIDValue.name),
  1176. CERT_NameTemplate }
  1177. };
  1178. static const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[] = {
  1179. { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
  1180. SEC_ASN1_XTRN | 2,
  1181. offsetof(ocspResponderID, responderIDValue.keyHash),
  1182. SEC_ASN1_SUB(SEC_OctetStringTemplate) }
  1183. };
  1184. static const SEC_ASN1Template ocsp_ResponderIDOtherTemplate[] = {
  1185. { SEC_ASN1_ANY,
  1186. offsetof(ocspResponderID, responderIDValue.other) }
  1187. };
  1188. /* Decode choice container, but leave x509 name object encoded */
  1189. static const SEC_ASN1Template ocsp_ResponderIDDerNameTemplate[] = {
  1190. { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
  1191. SEC_ASN1_XTRN | 1, 0, SEC_ASN1_SUB(SEC_AnyTemplate) }
  1192. };
  1193. /*
  1194. * SingleResponse ::= SEQUENCE {
  1195. * certID CertID,
  1196. * certStatus CertStatus,
  1197. * thisUpdate GeneralizedTime,
  1198. * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
  1199. * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
  1200. *
  1201. * Note: this should be static but the AIX compiler doesn't like it (because it
  1202. * was forward-declared above); it is not meant to be exported, but this
  1203. * is the only way it will compile.
  1204. */
  1205. const SEC_ASN1Template ocsp_SingleResponseTemplate[] = {
  1206. { SEC_ASN1_SEQUENCE,
  1207. 0, NULL, sizeof(CERTOCSPSingleResponse) },
  1208. { SEC_ASN1_POINTER,
  1209. offsetof(CERTOCSPSingleResponse, certID),
  1210. ocsp_CertIDTemplate },
  1211. { SEC_ASN1_ANY,
  1212. offsetof(CERTOCSPSingleResponse, derCertStatus) },
  1213. { SEC_ASN1_GENERALIZED_TIME,
  1214. offsetof(CERTOCSPSingleResponse, thisUpdate) },
  1215. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  1216. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
  1217. offsetof(CERTOCSPSingleResponse, nextUpdate),
  1218. SEC_ASN1_SUB(SEC_PointerToGeneralizedTimeTemplate) },
  1219. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  1220. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
  1221. offsetof(CERTOCSPSingleResponse, singleExtensions),
  1222. CERT_SequenceOfCertExtensionTemplate },
  1223. { 0 }
  1224. };
  1225. /*
  1226. * CertStatus ::= CHOICE {
  1227. * good [0] IMPLICIT NULL,
  1228. * revoked [1] IMPLICIT RevokedInfo,
  1229. * unknown [2] IMPLICIT UnknownInfo }
  1230. *
  1231. * Because the ASN.1 encoder and decoder currently do not provide
  1232. * a way to automatically handle a CHOICE, we need to do it in two
  1233. * steps, looking at the type tag and feeding the exact choice back
  1234. * to the ASN.1 code. Hopefully that will change someday and this
  1235. * can all be simplified down into a single template. Anyway, for
  1236. * now we list each choice as its own template:
  1237. */
  1238. static const SEC_ASN1Template ocsp_CertStatusGoodTemplate[] = {
  1239. { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
  1240. offsetof(ocspCertStatus, certStatusInfo.goodInfo),
  1241. SEC_ASN1_SUB(SEC_NullTemplate) }
  1242. };
  1243. static const SEC_ASN1Template ocsp_CertStatusRevokedTemplate[] = {
  1244. { SEC_ASN1_POINTER | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
  1245. offsetof(ocspCertStatus, certStatusInfo.revokedInfo),
  1246. ocsp_RevokedInfoTemplate }
  1247. };
  1248. static const SEC_ASN1Template ocsp_CertStatusUnknownTemplate[] = {
  1249. { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2,
  1250. offsetof(ocspCertStatus, certStatusInfo.unknownInfo),
  1251. SEC_ASN1_SUB(SEC_NullTemplate) }
  1252. };
  1253. static const SEC_ASN1Template ocsp_CertStatusOtherTemplate[] = {
  1254. { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
  1255. offsetof(ocspCertStatus, certStatusInfo.otherInfo),
  1256. SEC_ASN1_SUB(SEC_AnyTemplate) }
  1257. };
  1258. /*
  1259. * RevokedInfo ::= SEQUENCE {
  1260. * revocationTime GeneralizedTime,
  1261. * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
  1262. *
  1263. * Note: this should be static but the AIX compiler doesn't like it (because it
  1264. * was forward-declared above); it is not meant to be exported, but this
  1265. * is the only way it will compile.
  1266. */
  1267. const SEC_ASN1Template ocsp_RevokedInfoTemplate[] = {
  1268. { SEC_ASN1_SEQUENCE,
  1269. 0, NULL, sizeof(ocspRevokedInfo) },
  1270. { SEC_ASN1_GENERALIZED_TIME,
  1271. offsetof(ocspRevokedInfo, revocationTime) },
  1272. { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  1273. SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
  1274. SEC_ASN1_XTRN | 0,
  1275. offsetof(ocspRevokedInfo, revocationReason),
  1276. SEC_ASN1_SUB(SEC_PointerToEnumeratedTemplate) },
  1277. { 0 }
  1278. };
  1279. /*
  1280. * OCSP-specific extension templates:
  1281. */
  1282. /*
  1283. * ServiceLocator ::= SEQUENCE {
  1284. * issuer Name,
  1285. * locator AuthorityInfoAccessSyntax OPTIONAL }
  1286. */
  1287. static const SEC_ASN1Template ocsp_ServiceLocatorTemplate[] = {
  1288. { SEC_ASN1_SEQUENCE,
  1289. 0, NULL, sizeof(ocspServiceLocator) },
  1290. { SEC_ASN1_POINTER,
  1291. offsetof(ocspServiceLocator, issuer),
  1292. CERT_NameTemplate },
  1293. { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
  1294. offsetof(ocspServiceLocator, locator) },
  1295. { 0 }
  1296. };
  1297. /*
  1298. * REQUEST SUPPORT FUNCTIONS (encode/create/decode/destroy):
  1299. */
  1300. /*
  1301. * FUNCTION: CERT_EncodeOCSPRequest
  1302. * DER encodes an OCSP Request, possibly adding a signature as well.
  1303. * XXX Signing is not yet supported, however; see comments in code.
  1304. * INPUTS:
  1305. * PRArenaPool *arena
  1306. * The return value is allocated from here.
  1307. * If a NULL is passed in, allocation is done from the heap instead.
  1308. * CERTOCSPRequest *request
  1309. * The request to be encoded.
  1310. * void *pwArg
  1311. * Pointer to argument for password prompting, if needed. (Definitely
  1312. * not needed if not signing.)
  1313. * RETURN:
  1314. * Returns a NULL on error and a pointer to the SECItem with the
  1315. * encoded value otherwise. Any error is likely to be low-level
  1316. * (e.g. no memory).
  1317. */
  1318. SECItem *
  1319. CERT_EncodeOCSPRequest(PRArenaPool *arena, CERTOCSPRequest *request,
  1320. void *pwArg)
  1321. {
  1322. ocspTBSRequest *tbsRequest;
  1323. SECStatus rv;
  1324. /* XXX All of these should generate errors if they fail. */
  1325. PORT_Assert(request);
  1326. PORT_Assert(request->tbsRequest);
  1327. tbsRequest = request->tbsRequest;
  1328. if (request->tbsRequest->extensionHandle != NULL) {
  1329. rv = CERT_FinishExtensions(request->tbsRequest->extensionHandle);
  1330. request->tbsRequest->extensionHandle = NULL;
  1331. if (rv != SECSuccess)
  1332. return NULL;
  1333. }
  1334. /*
  1335. * XXX When signed requests are supported and request->optionalSignature
  1336. * is not NULL:
  1337. * - need to encode tbsRequest->requestorName
  1338. * - need to encode tbsRequest
  1339. * - need to sign that encoded result (using cert in sig), filling in the
  1340. * request->optionalSignature structure with the result, the signing
  1341. * algorithm and (perhaps?) the cert (and its chain?) in derCerts
  1342. */
  1343. return SEC_ASN1EncodeItem(arena, NULL, request, ocsp_OCSPRequestTemplate);
  1344. }
  1345. /*
  1346. * FUNCTION: CERT_DecodeOCSPRequest
  1347. * Decode a DER encoded OCSP Request.
  1348. * INPUTS:
  1349. * SECItem *src
  1350. * Pointer to a SECItem holding DER encoded OCSP Request.
  1351. * RETURN:
  1352. * Returns a pointer to a CERTOCSPRequest containing the decoded request.
  1353. * On error, returns NULL. Most likely error is trouble decoding
  1354. * (SEC_ERROR_OCSP_MALFORMED_REQUEST), or low-level problem (no memory).
  1355. */
  1356. CERTOCSPRequest *
  1357. CERT_DecodeOCSPRequest(SECItem *src)
  1358. {
  1359. PRArenaPool *arena = NULL;
  1360. SECStatus rv = SECFailure;
  1361. CERTOCSPRequest *dest = NULL;
  1362. int i;
  1363. SECItem newSrc;
  1364. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1365. if (arena == NULL) {
  1366. goto loser;
  1367. }
  1368. dest = (CERTOCSPRequest *) PORT_ArenaZAlloc(arena,
  1369. siz