PageRenderTime 95ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/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
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, LGPL-2.1, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD
  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. sizeof(CERTOCSPRequest));
  1370. if (dest == NULL) {
  1371. goto loser;
  1372. }
  1373. dest->arena = arena;
  1374. /* copy the DER into the arena, since Quick DER returns data that points
  1375. into the DER input, which may get freed by the caller */
  1376. rv = SECITEM_CopyItem(arena, &newSrc, src);
  1377. if ( rv != SECSuccess ) {
  1378. goto loser;
  1379. }
  1380. rv = SEC_QuickDERDecodeItem(arena, dest, ocsp_OCSPRequestTemplate, &newSrc);
  1381. if (rv != SECSuccess) {
  1382. if (PORT_GetError() == SEC_ERROR_BAD_DER)
  1383. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
  1384. goto loser;
  1385. }
  1386. /*
  1387. * XXX I would like to find a way to get rid of the necessity
  1388. * of doing this copying of the arena pointer.
  1389. */
  1390. for (i = 0; dest->tbsRequest->requestList[i] != NULL; i++) {
  1391. dest->tbsRequest->requestList[i]->arena = arena;
  1392. }
  1393. return dest;
  1394. loser:
  1395. if (arena != NULL) {
  1396. PORT_FreeArena(arena, PR_FALSE);
  1397. }
  1398. return NULL;
  1399. }
  1400. SECStatus
  1401. CERT_DestroyOCSPCertID(CERTOCSPCertID* certID)
  1402. {
  1403. if (certID && certID->poolp) {
  1404. PORT_FreeArena(certID->poolp, PR_FALSE);
  1405. return SECSuccess;
  1406. }
  1407. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1408. return SECFailure;
  1409. }
  1410. /*
  1411. * Digest data using the specified algorithm.
  1412. * The necessary storage for the digest data is allocated. If "fill" is
  1413. * non-null, the data is put there, otherwise a SECItem is allocated.
  1414. * Allocation from "arena" if it is non-null, heap otherwise. Any problem
  1415. * results in a NULL being returned (and an appropriate error set).
  1416. */
  1417. static SECItem *
  1418. ocsp_DigestValue(PRArenaPool *arena, SECOidTag digestAlg,
  1419. SECItem *fill, const SECItem *src)
  1420. {
  1421. const SECHashObject *digestObject;
  1422. SECItem *result = NULL;
  1423. void *mark = NULL;
  1424. void *digestBuff = NULL;
  1425. if ( arena != NULL ) {
  1426. mark = PORT_ArenaMark(arena);
  1427. }
  1428. digestObject = HASH_GetHashObjectByOidTag(digestAlg);
  1429. if ( digestObject == NULL ) {
  1430. goto loser;
  1431. }
  1432. if (fill == NULL || fill->data == NULL) {
  1433. result = SECITEM_AllocItem(arena, fill, digestObject->length);
  1434. if ( result == NULL ) {
  1435. goto loser;
  1436. }
  1437. digestBuff = result->data;
  1438. } else {
  1439. if (fill->len < digestObject->length) {
  1440. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1441. goto loser;
  1442. }
  1443. digestBuff = fill->data;
  1444. }
  1445. if (PK11_HashBuf(digestAlg, digestBuff,
  1446. src->data, src->len) != SECSuccess) {
  1447. goto loser;
  1448. }
  1449. if ( arena != NULL ) {
  1450. PORT_ArenaUnmark(arena, mark);
  1451. }
  1452. if (result == NULL) {
  1453. result = fill;
  1454. }
  1455. return result;
  1456. loser:
  1457. if (arena != NULL) {
  1458. PORT_ArenaRelease(arena, mark);
  1459. } else {
  1460. if (result != NULL) {
  1461. SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE);
  1462. }
  1463. }
  1464. return(NULL);
  1465. }
  1466. /*
  1467. * Digest the cert's subject public key using the specified algorithm.
  1468. * The necessary storage for the digest data is allocated. If "fill" is
  1469. * non-null, the data is put there, otherwise a SECItem is allocated.
  1470. * Allocation from "arena" if it is non-null, heap otherwise. Any problem
  1471. * results in a NULL being returned (and an appropriate error set).
  1472. */
  1473. SECItem *
  1474. CERT_GetSPKIDigest(PRArenaPool *arena, const CERTCertificate *cert,
  1475. SECOidTag digestAlg, SECItem *fill)
  1476. {
  1477. SECItem spk;
  1478. /*
  1479. * Copy just the length and data pointer (nothing needs to be freed)
  1480. * of the subject public key so we can convert the length from bits
  1481. * to bytes, which is what the digest function expects.
  1482. */
  1483. spk = cert->subjectPublicKeyInfo.subjectPublicKey;
  1484. DER_ConvertBitString(&spk);
  1485. return ocsp_DigestValue(arena, digestAlg, fill, &spk);
  1486. }
  1487. /*
  1488. * Digest the cert's subject name using the specified algorithm.
  1489. */
  1490. static SECItem *
  1491. cert_GetSubjectNameDigest(PRArenaPool *arena, const CERTCertificate *cert,
  1492. SECOidTag digestAlg, SECItem *fill)
  1493. {
  1494. SECItem name;
  1495. /*
  1496. * Copy just the length and data pointer (nothing needs to be freed)
  1497. * of the subject name
  1498. */
  1499. name = cert->derSubject;
  1500. return ocsp_DigestValue(arena, digestAlg, fill, &name);
  1501. }
  1502. /*
  1503. * Create and fill-in a CertID. This function fills in the hash values
  1504. * (issuerNameHash and issuerKeyHash), and is hardwired to use SHA1.
  1505. * Someday it might need to be more flexible about hash algorithm, but
  1506. * for now we have no intention/need to create anything else.
  1507. *
  1508. * Error causes a null to be returned; most likely cause is trouble
  1509. * finding the certificate issuer (SEC_ERROR_UNKNOWN_ISSUER).
  1510. * Other errors are low-level problems (no memory, bad database, etc.).
  1511. */
  1512. static CERTOCSPCertID *
  1513. ocsp_CreateCertID(PRArenaPool *arena, CERTCertificate *cert, int64 time)
  1514. {
  1515. CERTOCSPCertID *certID;
  1516. CERTCertificate *issuerCert = NULL;
  1517. void *mark = PORT_ArenaMark(arena);
  1518. SECStatus rv;
  1519. PORT_Assert(arena != NULL);
  1520. certID = PORT_ArenaZNew(arena, CERTOCSPCertID);
  1521. if (certID == NULL) {
  1522. goto loser;
  1523. }
  1524. rv = SECOID_SetAlgorithmID(arena, &certID->hashAlgorithm, SEC_OID_SHA1,
  1525. NULL);
  1526. if (rv != SECSuccess) {
  1527. goto loser;
  1528. }
  1529. issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
  1530. if (issuerCert == NULL) {
  1531. goto loser;
  1532. }
  1533. if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_SHA1,
  1534. &(certID->issuerNameHash)) == NULL) {
  1535. goto loser;
  1536. }
  1537. certID->issuerSHA1NameHash.data = certID->issuerNameHash.data;
  1538. certID->issuerSHA1NameHash.len = certID->issuerNameHash.len;
  1539. if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD5,
  1540. &(certID->issuerMD5NameHash)) == NULL) {
  1541. goto loser;
  1542. }
  1543. if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD2,
  1544. &(certID->issuerMD2NameHash)) == NULL) {
  1545. goto loser;
  1546. }
  1547. if (CERT_GetSPKIDigest(arena, issuerCert, SEC_OID_SHA1,
  1548. &(certID->issuerKeyHash)) == NULL) {
  1549. goto loser;
  1550. }
  1551. certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data;
  1552. certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len;
  1553. /* cache the other two hash algorithms as well */
  1554. if (CERT_GetSPKIDigest(arena, issuerCert, SEC_OID_MD5,
  1555. &(certID->issuerMD5KeyHash)) == NULL) {
  1556. goto loser;
  1557. }
  1558. if (CERT_GetSPKIDigest(arena, issuerCert, SEC_OID_MD2,
  1559. &(certID->issuerMD2KeyHash)) == NULL) {
  1560. goto loser;
  1561. }
  1562. /* now we are done with issuerCert */
  1563. CERT_DestroyCertificate(issuerCert);
  1564. issuerCert = NULL;
  1565. rv = SECITEM_CopyItem(arena, &certID->serialNumber, &cert->serialNumber);
  1566. if (rv != SECSuccess) {
  1567. goto loser;
  1568. }
  1569. PORT_ArenaUnmark(arena, mark);
  1570. return certID;
  1571. loser:
  1572. if (issuerCert != NULL) {
  1573. CERT_DestroyCertificate(issuerCert);
  1574. }
  1575. PORT_ArenaRelease(arena, mark);
  1576. return NULL;
  1577. }
  1578. CERTOCSPCertID*
  1579. CERT_CreateOCSPCertID(CERTCertificate *cert, int64 time)
  1580. {
  1581. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1582. CERTOCSPCertID *certID;
  1583. PORT_Assert(arena != NULL);
  1584. if (!arena)
  1585. return NULL;
  1586. certID = ocsp_CreateCertID(arena, cert, time);
  1587. if (!certID) {
  1588. PORT_FreeArena(arena, PR_FALSE);
  1589. return NULL;
  1590. }
  1591. certID->poolp = arena;
  1592. return certID;
  1593. }
  1594. /*
  1595. * Callback to set Extensions in request object
  1596. */
  1597. void SetSingleReqExts(void *object, CERTCertExtension **exts)
  1598. {
  1599. ocspSingleRequest *singleRequest =
  1600. (ocspSingleRequest *)object;
  1601. singleRequest->singleRequestExtensions = exts;
  1602. }
  1603. /*
  1604. * Add the Service Locator extension to the singleRequestExtensions
  1605. * for the given singleRequest.
  1606. *
  1607. * All errors are internal or low-level problems (e.g. no memory).
  1608. */
  1609. static SECStatus
  1610. ocsp_AddServiceLocatorExtension(ocspSingleRequest *singleRequest,
  1611. CERTCertificate *cert)
  1612. {
  1613. ocspServiceLocator *serviceLocator = NULL;
  1614. void *extensionHandle = NULL;
  1615. SECStatus rv = SECFailure;
  1616. serviceLocator = PORT_ZNew(ocspServiceLocator);
  1617. if (serviceLocator == NULL)
  1618. goto loser;
  1619. /*
  1620. * Normally it would be a bad idea to do a direct reference like
  1621. * this rather than allocate and copy the name *or* at least dup
  1622. * a reference of the cert. But all we need is to be able to read
  1623. * the issuer name during the encoding we are about to do, so a
  1624. * copy is just a waste of time.
  1625. */
  1626. serviceLocator->issuer = &cert->issuer;
  1627. rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
  1628. &serviceLocator->locator);
  1629. if (rv != SECSuccess) {
  1630. if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND)
  1631. goto loser;
  1632. }
  1633. /* prepare for following loser gotos */
  1634. rv = SECFailure;
  1635. PORT_SetError(0);
  1636. extensionHandle = cert_StartExtensions(singleRequest,
  1637. singleRequest->arena, SetSingleReqExts);
  1638. if (extensionHandle == NULL)
  1639. goto loser;
  1640. rv = CERT_EncodeAndAddExtension(extensionHandle,
  1641. SEC_OID_PKIX_OCSP_SERVICE_LOCATOR,
  1642. serviceLocator, PR_FALSE,
  1643. ocsp_ServiceLocatorTemplate);
  1644. loser:
  1645. if (extensionHandle != NULL) {
  1646. /*
  1647. * Either way we have to finish out the extension context (so it gets
  1648. * freed). But careful not to override any already-set bad status.
  1649. */
  1650. SECStatus tmprv = CERT_FinishExtensions(extensionHandle);
  1651. if (rv == SECSuccess)
  1652. rv = tmprv;
  1653. }
  1654. /*
  1655. * Finally, free the serviceLocator structure itself and we are done.
  1656. */
  1657. if (serviceLocator != NULL) {
  1658. if (serviceLocator->locator.data != NULL)
  1659. SECITEM_FreeItem(&serviceLocator->locator, PR_FALSE);
  1660. PORT_Free(serviceLocator);
  1661. }
  1662. return rv;
  1663. }
  1664. /*
  1665. * Creates an array of ocspSingleRequest based on a list of certs.
  1666. * Note that the code which later compares the request list with the
  1667. * response expects this array to be in the exact same order as the
  1668. * certs are found in the list. It would be harder to change that
  1669. * order than preserve it, but since the requirement is not obvious,
  1670. * it deserves to be mentioned.
  1671. *
  1672. * Any problem causes a null return and error set:
  1673. * SEC_ERROR_UNKNOWN_ISSUER
  1674. * Other errors are low-level problems (no memory, bad database, etc.).
  1675. */
  1676. static ocspSingleRequest **
  1677. ocsp_CreateSingleRequestList(PRArenaPool *arena, CERTCertList *certList,
  1678. int64 time, PRBool includeLocator)
  1679. {
  1680. ocspSingleRequest **requestList = NULL;
  1681. CERTCertListNode *node = NULL;
  1682. int i, count;
  1683. void *mark = PORT_ArenaMark(arena);
  1684. node = CERT_LIST_HEAD(certList);
  1685. for (count = 0; !CERT_LIST_END(node, certList); count++) {
  1686. node = CERT_LIST_NEXT(node);
  1687. }
  1688. if (count == 0)
  1689. goto loser;
  1690. requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, count + 1);
  1691. if (requestList == NULL)
  1692. goto loser;
  1693. node = CERT_LIST_HEAD(certList);
  1694. for (i = 0; !CERT_LIST_END(node, certList); i++) {
  1695. requestList[i] = PORT_ArenaZNew(arena, ocspSingleRequest);
  1696. if (requestList[i] == NULL)
  1697. goto loser;
  1698. OCSP_TRACE(("OCSP CERT_CreateOCSPRequest %s\n", node->cert->subjectName));
  1699. requestList[i]->arena = arena;
  1700. requestList[i]->reqCert = ocsp_CreateCertID(arena, node->cert, time);
  1701. if (requestList[i]->reqCert == NULL)
  1702. goto loser;
  1703. if (includeLocator == PR_TRUE) {
  1704. SECStatus rv;
  1705. rv = ocsp_AddServiceLocatorExtension(requestList[i], node->cert);
  1706. if (rv != SECSuccess)
  1707. goto loser;
  1708. }
  1709. node = CERT_LIST_NEXT(node);
  1710. }
  1711. PORT_Assert(i == count);
  1712. PORT_ArenaUnmark(arena, mark);
  1713. requestList[i] = NULL;
  1714. return requestList;
  1715. loser:
  1716. PORT_ArenaRelease(arena, mark);
  1717. return NULL;
  1718. }
  1719. static ocspSingleRequest **
  1720. ocsp_CreateRequestFromCert(PRArenaPool *arena,
  1721. CERTOCSPCertID *certID,
  1722. CERTCertificate *singleCert,
  1723. int64 time,
  1724. PRBool includeLocator)
  1725. {
  1726. ocspSingleRequest **requestList = NULL;
  1727. void *mark = PORT_ArenaMark(arena);
  1728. PORT_Assert(certID != NULL && singleCert != NULL);
  1729. /* meaning of value 2: one entry + one end marker */
  1730. requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, 2);
  1731. if (requestList == NULL)
  1732. goto loser;
  1733. requestList[0] = PORT_ArenaZNew(arena, ocspSingleRequest);
  1734. if (requestList[0] == NULL)
  1735. goto loser;
  1736. requestList[0]->arena = arena;
  1737. /* certID will live longer than the request */
  1738. requestList[0]->reqCert = certID;
  1739. if (includeLocator == PR_TRUE) {
  1740. SECStatus rv;
  1741. rv = ocsp_AddServiceLocatorExtension(requestList[0], singleCert);
  1742. if (rv != SECSuccess)
  1743. goto loser;
  1744. }
  1745. PORT_ArenaUnmark(arena, mark);
  1746. requestList[1] = NULL;
  1747. return requestList;
  1748. loser:
  1749. PORT_ArenaRelease(arena, mark);
  1750. return NULL;
  1751. }
  1752. static CERTOCSPRequest *
  1753. ocsp_prepareEmptyOCSPRequest()
  1754. {
  1755. PRArenaPool *arena = NULL;
  1756. CERTOCSPRequest *request = NULL;
  1757. ocspTBSRequest *tbsRequest = NULL;
  1758. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1759. if (arena == NULL) {
  1760. goto loser;
  1761. }
  1762. request = PORT_ArenaZNew(arena, CERTOCSPRequest);
  1763. if (request == NULL) {
  1764. goto loser;
  1765. }
  1766. request->arena = arena;
  1767. tbsRequest = PORT_ArenaZNew(arena, ocspTBSRequest);
  1768. if (tbsRequest == NULL) {
  1769. goto loser;
  1770. }
  1771. request->tbsRequest = tbsRequest;
  1772. /* version 1 is the default, so we need not fill in a version number */
  1773. return request;
  1774. loser:
  1775. if (arena != NULL) {
  1776. PORT_FreeArena(arena, PR_FALSE);
  1777. }
  1778. return NULL;
  1779. }
  1780. CERTOCSPRequest *
  1781. cert_CreateSingleCertOCSPRequest(CERTOCSPCertID *certID,
  1782. CERTCertificate *singleCert,
  1783. int64 time,
  1784. PRBool addServiceLocator,
  1785. CERTCertificate *signerCert)
  1786. {
  1787. CERTOCSPRequest *request;
  1788. OCSP_TRACE(("OCSP cert_CreateSingleCertOCSPRequest %s\n", singleCert->subjectName));
  1789. /* XXX Support for signerCert may be implemented later,
  1790. * see also the comment in CERT_CreateOCSPRequest.
  1791. */
  1792. if (signerCert != NULL) {
  1793. PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
  1794. return NULL;
  1795. }
  1796. request = ocsp_prepareEmptyOCSPRequest();
  1797. if (!request)
  1798. return NULL;
  1799. /*
  1800. * Version 1 is the default, so we need not fill in a version number.
  1801. * Now create the list of single requests, one for each cert.
  1802. */
  1803. request->tbsRequest->requestList =
  1804. ocsp_CreateRequestFromCert(request->arena,
  1805. certID,
  1806. singleCert,
  1807. time,
  1808. addServiceLocator);
  1809. if (request->tbsRequest->requestList == NULL) {
  1810. PORT_FreeArena(request->arena, PR_FALSE);
  1811. return NULL;
  1812. }
  1813. return request;
  1814. }
  1815. /*
  1816. * FUNCTION: CERT_CreateOCSPRequest
  1817. * Creates a CERTOCSPRequest, requesting the status of the certs in
  1818. * the given list.
  1819. * INPUTS:
  1820. * CERTCertList *certList
  1821. * A list of certs for which status will be requested.
  1822. * Note that all of these certificates should have the same issuer,
  1823. * or it's expected the response will be signed by a trusted responder.
  1824. * If the certs need to be broken up into multiple requests, that
  1825. * must be handled by the caller (and thus by having multiple calls
  1826. * to this routine), who knows about where the request(s) are being
  1827. * sent and whether there are any trusted responders in place.
  1828. * int64 time
  1829. * Indicates the time for which the certificate status is to be
  1830. * determined -- this may be used in the search for the cert's issuer
  1831. * but has no effect on the request itself.
  1832. * PRBool addServiceLocator
  1833. * If true, the Service Locator extension should be added to the
  1834. * single request(s) for each cert.
  1835. * CERTCertificate *signerCert
  1836. * If non-NULL, means sign the request using this cert. Otherwise,
  1837. * do not sign.
  1838. * XXX note that request signing is not yet supported; see comment in code
  1839. * RETURN:
  1840. * A pointer to a CERTOCSPRequest structure containing an OCSP request
  1841. * for the cert list. On error, null is returned, with an error set
  1842. * indicating the reason. This is likely SEC_ERROR_UNKNOWN_ISSUER.
  1843. * (The issuer is needed to create a request for the certificate.)
  1844. * Other errors are low-level problems (no memory, bad database, etc.).
  1845. */
  1846. CERTOCSPRequest *
  1847. CERT_CreateOCSPRequest(CERTCertList *certList, int64 time,
  1848. PRBool addServiceLocator,
  1849. CERTCertificate *signerCert)
  1850. {
  1851. CERTOCSPRequest *request = NULL;
  1852. if (!certList) {
  1853. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1854. return NULL;
  1855. }
  1856. /*
  1857. * XXX When we are prepared to put signing of requests back in,
  1858. * we will need to allocate a signature
  1859. * structure for the request, fill in the "derCerts" field in it,
  1860. * save the signerCert there, as well as fill in the "requestorName"
  1861. * field of the tbsRequest.
  1862. */
  1863. if (signerCert != NULL) {
  1864. PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
  1865. return NULL;
  1866. }
  1867. request = ocsp_prepareEmptyOCSPRequest();
  1868. if (!request)
  1869. return NULL;
  1870. /*
  1871. * Now create the list of single requests, one for each cert.
  1872. */
  1873. request->tbsRequest->requestList =
  1874. ocsp_CreateSingleRequestList(request->arena,
  1875. certList,
  1876. time,
  1877. addServiceLocator);
  1878. if (request->tbsRequest->requestList == NULL) {
  1879. PORT_FreeArena(request->arena, PR_FALSE);
  1880. return NULL;
  1881. }
  1882. return request;
  1883. }
  1884. /*
  1885. * FUNCTION: CERT_AddOCSPAcceptableResponses
  1886. * Add the AcceptableResponses extension to an OCSP Request.
  1887. * INPUTS:
  1888. * CERTOCSPRequest *request
  1889. * The request to which the extension should be added.
  1890. * ...
  1891. * A list (of one or more) of SECOidTag -- each of the response types
  1892. * to be added. The last OID *must* be SEC_OID_PKIX_OCSP_BASIC_RESPONSE.
  1893. * (This marks the end of the list, and it must be specified because a
  1894. * client conforming to the OCSP standard is required to handle the basic
  1895. * response type.) The OIDs are not checked in any way.
  1896. * RETURN:
  1897. * SECSuccess if the extension is added; SECFailure if anything goes wrong.
  1898. * All errors are internal or low-level problems (e.g. no memory).
  1899. */
  1900. void SetRequestExts(void *object, CERTCertExtension **exts)
  1901. {
  1902. CERTOCSPRequest *request = (CERTOCSPRequest *)object;
  1903. request->tbsRequest->requestExtensions = exts;
  1904. }
  1905. SECStatus
  1906. CERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request,
  1907. SECOidTag responseType0, ...)
  1908. {
  1909. void *extHandle;
  1910. va_list ap;
  1911. int i, count;
  1912. SECOidTag responseType;
  1913. SECOidData *responseOid;
  1914. SECItem **acceptableResponses = NULL;
  1915. SECStatus rv = SECFailure;
  1916. extHandle = request->tbsRequest->extensionHandle;
  1917. if (extHandle == NULL) {
  1918. extHandle = cert_StartExtensions(request, request->arena, SetRequestExts);
  1919. if (extHandle == NULL)
  1920. goto loser;
  1921. }
  1922. /* Count number of OIDS going into the extension value. */
  1923. count = 1;
  1924. if (responseType0 != SEC_OID_PKIX_OCSP_BASIC_RESPONSE) {
  1925. va_start(ap, responseType0);
  1926. do {
  1927. count++;
  1928. responseType = va_arg(ap, SECOidTag);
  1929. } while (responseType != SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
  1930. va_end(ap);
  1931. }
  1932. acceptableResponses = PORT_NewArray(SECItem *, count + 1);
  1933. if (acceptableResponses == NULL)
  1934. goto loser;
  1935. i = 0;
  1936. responseOid = SECOID_FindOIDByTag(responseType0);
  1937. acceptableResponses[i++] = &(responseOid->oid);
  1938. if (count > 1) {
  1939. va_start(ap, responseType0);
  1940. for ( ; i < count; i++) {
  1941. responseType = va_arg(ap, SECOidTag);
  1942. responseOid = SECOID_FindOIDByTag(responseType);
  1943. acceptableResponses[i] = &(responseOid->oid);
  1944. }
  1945. va_end(ap);
  1946. }
  1947. acceptableResponses[i] = NULL;
  1948. rv = CERT_EncodeAndAddExtension(extHandle, SEC_OID_PKIX_OCSP_RESPONSE,
  1949. &acceptableResponses, PR_FALSE,
  1950. SEC_ASN1_GET(SEC_SequenceOfObjectIDTemplate));
  1951. if (rv != SECSuccess)
  1952. goto loser;
  1953. PORT_Free(acceptableResponses);
  1954. if (request->tbsRequest->extensionHandle == NULL)
  1955. request->tbsRequest->extensionHandle = extHandle;
  1956. return SECSuccess;
  1957. loser:
  1958. if (acceptableResponses != NULL)
  1959. PORT_Free(acceptableResponses);
  1960. if (extHandle != NULL)
  1961. (void) CERT_FinishExtensions(extHandle);
  1962. return rv;
  1963. }
  1964. /*
  1965. * FUNCTION: CERT_DestroyOCSPRequest
  1966. * Frees an OCSP Request structure.
  1967. * INPUTS:
  1968. * CERTOCSPRequest *request
  1969. * Pointer to CERTOCSPRequest to be freed.
  1970. * RETURN:
  1971. * No return value; no errors.
  1972. */
  1973. void
  1974. CERT_DestroyOCSPRequest(CERTOCSPRequest *request)
  1975. {
  1976. if (request == NULL)
  1977. return;
  1978. if (request->tbsRequest != NULL) {
  1979. if (request->tbsRequest->requestorName != NULL)
  1980. CERT_DestroyGeneralNameList(request->tbsRequest->requestorName);
  1981. if (request->tbsRequest->extensionHandle != NULL)
  1982. (void) CERT_FinishExtensions(request->tbsRequest->extensionHandle);
  1983. }
  1984. if (request->optionalSignature != NULL) {
  1985. if (request->optionalSignature->cert != NULL)
  1986. CERT_DestroyCertificate(request->optionalSignature->cert);
  1987. /*
  1988. * XXX Need to free derCerts? Or do they come out of arena?
  1989. * (Currently we never fill in derCerts, which is why the
  1990. * answer is not obvious. Once we do, add any necessary code
  1991. * here and remove this comment.)
  1992. */
  1993. }
  1994. /*
  1995. * We should actually never have a request without an arena,
  1996. * but check just in case. (If there isn't one, there is not
  1997. * much we can do about it...)
  1998. */
  1999. PORT_Assert(request->arena != NULL);
  2000. if (request->arena != NULL)
  2001. PORT_FreeArena(request->arena, PR_FALSE);
  2002. }
  2003. /*
  2004. * RESPONSE SUPPORT FUNCTIONS (encode/create/decode/destroy):
  2005. */
  2006. /*
  2007. * Helper function for encoding or decoding a ResponderID -- based on the
  2008. * given type, return the associated template for that choice.
  2009. */
  2010. static const SEC_ASN1Template *
  2011. ocsp_ResponderIDTemplateByType(ocspResponderIDType responderIDType)
  2012. {
  2013. const SEC_ASN1Template *responderIDTemplate;
  2014. switch (responderIDType) {
  2015. case ocspResponderID_byName:
  2016. responderIDTemplate = ocsp_ResponderIDByNameTemplate;
  2017. break;
  2018. case ocspResponderID_byKey:
  2019. responderIDTemplate = ocsp_ResponderIDByKeyTemplate;
  2020. break;
  2021. case ocspResponderID_other:
  2022. default:
  2023. PORT_Assert(responderIDType == ocspResponderID_other);
  2024. responderIDTemplate = ocsp_ResponderIDOtherTemplate;
  2025. break;
  2026. }
  2027. return responderIDTemplate;
  2028. }
  2029. /*
  2030. * Helper function for encoding or decoding a CertStatus -- based on the
  2031. * given type, return the associated template for that choice.
  2032. */
  2033. static const SEC_ASN1Template *
  2034. ocsp_CertStatusTemplateByType(ocspCertStatusType certStatusType)
  2035. {
  2036. const SEC_ASN1Template *certStatusTemplate;
  2037. switch (certStatusType) {
  2038. case ocspCertStatus_good:
  2039. certStatusTemplate = ocsp_CertStatusGoodTemplate;
  2040. break;
  2041. case ocspCertStatus_revoked:
  2042. certStatusTemplate = ocsp_CertStatusRevokedTemplate;
  2043. break;
  2044. case ocspCertStatus_unknown:
  2045. certStatusTemplate = ocsp_CertStatusUnknownTemplate;
  2046. break;
  2047. case ocspCertStatus_other:
  2048. default:
  2049. PORT_Assert(certStatusType == ocspCertStatus_other);
  2050. certStatusTemplate = ocsp_CertStatusOtherTemplate;
  2051. break;
  2052. }
  2053. return certStatusTemplate;
  2054. }
  2055. /*
  2056. * Helper function for decoding a certStatus -- turn the actual DER tag
  2057. * into our local translation.
  2058. */
  2059. static ocspCertStatusType
  2060. ocsp_CertStatusTypeByTag(int derTag)
  2061. {
  2062. ocspCertStatusType certStatusType;
  2063. switch (derTag) {
  2064. case 0:
  2065. certStatusType = ocspCertStatus_good;
  2066. break;
  2067. case 1:
  2068. certStatusType = ocspCertStatus_revoked;
  2069. break;
  2070. case 2:
  2071. certStatusType = ocspCertStatus_unknown;
  2072. break;
  2073. default:
  2074. certStatusType = ocspCertStatus_other;
  2075. break;
  2076. }
  2077. return certStatusType;
  2078. }
  2079. /*
  2080. * Helper function for decoding SingleResponses -- they each contain
  2081. * a status which is encoded as CHOICE, which needs to be decoded "by hand".
  2082. *
  2083. * Note -- on error, this routine does not release the memory it may
  2084. * have allocated; it expects its caller to do that.
  2085. */
  2086. static SECStatus
  2087. ocsp_FinishDecodingSingleResponses(PRArenaPool *reqArena,
  2088. CERTOCSPSingleResponse **responses)
  2089. {
  2090. ocspCertStatus *certStatus;
  2091. ocspCertStatusType certStatusType;
  2092. const SEC_ASN1Template *certStatusTemplate;
  2093. int derTag;
  2094. int i;
  2095. SECStatus rv = SECFailure;
  2096. if (!reqArena) {
  2097. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  2098. return SECFailure;
  2099. }
  2100. if (responses == NULL) /* nothing to do */
  2101. return SECSuccess;
  2102. for (i = 0; responses[i] != NULL; i++) {
  2103. SECItem* newStatus;
  2104. /*
  2105. * The following assert points out internal errors (problems in
  2106. * the template definitions or in the ASN.1 decoder itself, etc.).
  2107. */
  2108. PORT_Assert(responses[i]->derCertStatus.data != NULL);
  2109. derTag = responses[i]->derCertStatus.data[0] & SEC_ASN1_TAGNUM_MASK;
  2110. certStatusType = ocsp_CertStatusTypeByTag(derTag);
  2111. certStatusTemplate = ocsp_CertStatusTemplateByType(certStatusType);
  2112. certStatus = PORT_ArenaZAlloc(reqArena, sizeof(ocspCertStatus));
  2113. if (certStatus == NULL) {
  2114. goto loser;
  2115. }
  2116. newStatus = SECITEM_ArenaDupItem(reqArena, &responses[i]->derCertStatus);
  2117. if (!newStatus) {
  2118. goto loser;
  2119. }
  2120. rv = SEC_QuickDERDecodeItem(reqArena, certStatus, certStatusTemplate,
  2121. newStatus);
  2122. if (rv != SECSuccess) {
  2123. if (PORT_GetError() == SEC_ERROR_BAD_DER)
  2124. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  2125. goto loser;
  2126. }
  2127. certStatus->certStatusType = certStatusType;
  2128. responses[i]->certStatus = certStatus;
  2129. }
  2130. return SECSuccess;
  2131. loser:
  2132. return rv;
  2133. }
  2134. /*
  2135. * Helper function for decoding a responderID -- turn the actual DER tag
  2136. * into our local translation.
  2137. */
  2138. static ocspResponderIDType
  2139. ocsp_ResponderIDTypeByTag(int derTag)
  2140. {
  2141. ocspResponderIDType responderIDType;
  2142. switch (derTag) {
  2143. case 1:
  2144. responderIDType = ocspResponderID_byName;
  2145. break;
  2146. case 2:
  2147. responderIDType = ocspResponderID_byKey;
  2148. break;
  2149. default:
  2150. responderIDType = ocspResponderID_other;
  2151. break;
  2152. }
  2153. return responderIDType;
  2154. }
  2155. /*
  2156. * Decode "src" as a BasicOCSPResponse, returning the result.
  2157. */
  2158. static ocspBasicOCSPResponse *
  2159. ocsp_DecodeBasicOCSPResponse(PRArenaPool *arena, SECItem *src)
  2160. {
  2161. void *mark;
  2162. ocspBasicOCSPResponse *basicResponse;
  2163. ocspResponseData *responseData;
  2164. ocspResponderID *responderID;
  2165. ocspResponderIDType responderIDType;
  2166. const SEC_ASN1Template *responderIDTemplate;
  2167. int derTag;
  2168. SECStatus rv;
  2169. SECItem newsrc;
  2170. mark = PORT_ArenaMark(arena);
  2171. basicResponse = PORT_ArenaZAlloc(arena, sizeof(ocspBasicOCSPResponse));
  2172. if (basicResponse == NULL) {
  2173. goto loser;
  2174. }
  2175. /* copy the DER into the arena, since Quick DER returns data that points
  2176. into the DER input, which may get freed by the caller */
  2177. rv = SECITEM_CopyItem(arena, &newsrc, src);
  2178. if ( rv != SECSuccess ) {
  2179. goto loser;
  2180. }
  2181. rv = SEC_QuickDERDecodeItem(arena, basicResponse,
  2182. ocsp_BasicOCSPResponseTemplate, &newsrc);
  2183. if (rv != SECSuccess) {
  2184. if (PORT_GetError() == SEC_ERROR_BAD_DER)
  2185. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  2186. goto loser;
  2187. }
  2188. responseData = basicResponse->tbsResponseData;
  2189. /*
  2190. * The following asserts point out internal errors (problems in
  2191. * the template definitions or in the ASN.1 decoder itself, etc.).
  2192. */
  2193. PORT_Assert(responseData != NULL);
  2194. PORT_Assert(responseData->derResponderID.data != NULL);
  2195. /*
  2196. * XXX Because responderID is a CHOICE, which is not currently handled
  2197. * by our ASN.1 decoder, we have to decode it "by hand".
  2198. */
  2199. derTag = responseData->derResponderID.data[0] & SEC_ASN1_TAGNUM_MASK;
  2200. responderIDType = ocsp_ResponderIDTypeByTag(derTag);
  2201. responderIDTemplate = ocsp_ResponderIDTemplateByType(responderIDType);
  2202. responderID = PORT_ArenaZAlloc(arena, sizeof(ocspResponderID));
  2203. if (responderID == NULL) {
  2204. goto loser;
  2205. }
  2206. rv = SEC_QuickDERDecodeItem(arena, responderID, responderIDTemplate,
  2207. &responseData->derResponderID);
  2208. if (rv != SECSuccess) {
  2209. if (PORT_GetError() == SEC_ERROR_BAD_DER)
  2210. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  2211. goto loser;
  2212. }
  2213. responderID->responderIDType = responderIDType;
  2214. responseData->responderID = responderID;
  2215. /*
  2216. * XXX Each SingleResponse also contains a CHOICE, which has to be
  2217. * fixed up by hand.
  2218. */
  2219. rv = ocsp_FinishDecodingSingleResponses(arena, responseData->responses);
  2220. if (rv != SECSuccess) {
  2221. goto loser;
  2222. }
  2223. PORT_ArenaUnmark(arena, mark);
  2224. return basicResponse;
  2225. loser:
  2226. PORT_ArenaRelease(arena, mark);
  2227. return NULL;
  2228. }
  2229. /*
  2230. * Decode the responseBytes based on the responseType found in "rbytes",
  2231. * leaving the resulting translated/decoded information in there as well.
  2232. */
  2233. static SECStatus
  2234. ocsp_DecodeResponseBytes(PRArenaPool *arena, ocspResponseBytes *rbytes)
  2235. {
  2236. PORT_Assert(rbytes != NULL); /* internal error, really */
  2237. if (rbytes == NULL) {
  2238. PORT_SetError(SEC_ERROR_INVALID_ARGS); /* XXX set better error? */
  2239. return SECFailure;
  2240. }
  2241. rbytes->responseTypeTag = SECOID_FindOIDTag(&rbytes->responseType);
  2242. switch (rbytes->responseTypeTag) {
  2243. case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
  2244. {
  2245. ocspBasicOCSPResponse *basicResponse;
  2246. basicResponse = ocsp_DecodeBasicOCSPResponse(arena,
  2247. &rbytes->response);
  2248. if (basicResponse == NULL)
  2249. return SECFailure;
  2250. rbytes->decodedResponse.basic = basicResponse;
  2251. }
  2252. break;
  2253. /*
  2254. * Add new/future response types here.
  2255. */
  2256. default:
  2257. PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE);
  2258. return SECFailure;
  2259. }
  2260. return SECSuccess;
  2261. }
  2262. /*
  2263. * FUNCTION: CERT_DecodeOCSPResponse
  2264. * Decode a DER encoded OCSP Response.
  2265. * INPUTS:
  2266. * SECItem *src
  2267. * Pointer to a SECItem holding DER encoded OCSP Response.
  2268. * RETURN:
  2269. * Returns a pointer to a CERTOCSPResponse (the decoded OCSP Response);
  2270. * the caller is responsible for destroying it. Or NULL if error (either
  2271. * response could not be decoded (SEC_ERROR_OCSP_MALFORMED_RESPONSE),
  2272. * it was of an unexpected type (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE),
  2273. * or a low-level or internal error occurred).
  2274. */
  2275. CERTOCSPResponse *
  2276. CERT_DecodeOCSPResponse(SECItem *src)
  2277. {
  2278. PRArenaPool *arena = NULL;
  2279. CERTOCSPResponse *response = NULL;
  2280. SECStatus rv = SECFailure;
  2281. ocspResponseStatus sv;
  2282. SECItem newSrc;
  2283. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2284. if (arena == NULL) {
  2285. goto loser;
  2286. }
  2287. response = (CERTOCSPResponse *) PORT_ArenaZAlloc(arena,
  2288. sizeof(CERTOCSPResponse));
  2289. if (response == NULL) {
  2290. goto loser;
  2291. }
  2292. response->arena = arena;
  2293. /* copy the DER into the arena, since Quick DER returns data that points
  2294. into the DER input, which may get freed by the caller */
  2295. rv = SECITEM_CopyItem(arena, &newSrc, src);
  2296. if ( rv != SECSuccess ) {
  2297. goto loser;
  2298. }
  2299. rv = SEC_QuickDERDecodeItem(arena, response, ocsp_OCSPResponseTemplate, &newSrc);
  2300. if (rv != SECSuccess) {
  2301. if (PORT_GetError() == SEC_ERROR_BAD_DER)
  2302. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  2303. goto loser;
  2304. }
  2305. sv = (ocspResponseStatus) DER_GetInteger(&response->responseStatus);
  2306. response->statusValue = sv;
  2307. if (sv != ocspResponse_successful) {
  2308. /*
  2309. * If the response status is anything but successful, then we
  2310. * are all done with decoding; the status is all there is.
  2311. */
  2312. return response;
  2313. }
  2314. /*
  2315. * A successful response contains much more information, still encoded.
  2316. * Now we need to decode that.
  2317. */
  2318. rv = ocsp_DecodeResponseBytes(arena, response->responseBytes);
  2319. if (rv != SECSuccess) {
  2320. goto loser;
  2321. }
  2322. return response;
  2323. loser:
  2324. if (arena != NULL) {
  2325. PORT_FreeArena(arena, PR_FALSE);
  2326. }
  2327. return NULL;
  2328. }
  2329. /*
  2330. * The way an OCSPResponse is defined, there are many levels to descend
  2331. * before getting to the actual response information. And along the way
  2332. * we need to check that the response *type* is recognizable, which for
  2333. * now means that it is a BasicOCSPResponse, because that is the only
  2334. * type currently defined. Rather than force all routines to perform
  2335. * a bunch of sanity checking every time they want to work on a response,
  2336. * this function isolates that and gives back the interesting part.
  2337. * Note that no copying is done, this just returns a pointer into the
  2338. * substructure of the response which is passed in.
  2339. *
  2340. * XXX This routine only works when a valid response structure is passed
  2341. * into it; this is checked with many assertions. Assuming the response
  2342. * was creating by decoding, it wouldn't make it this far without being
  2343. * okay. That is a sufficient assumption since the entire OCSP interface
  2344. * is only used internally. When this interface is officially exported,
  2345. * each assertion below will need to be followed-up with setting an error
  2346. * and returning (null).
  2347. *
  2348. * FUNCTION: ocsp_GetResponseData
  2349. * Returns ocspResponseData structure and a pointer to tbs response
  2350. * data DER from a valid ocsp response.
  2351. * INPUTS:
  2352. * CERTOCSPResponse *response
  2353. * structure of a valid ocsp response
  2354. * RETURN:
  2355. * Returns a pointer to ocspResponseData structure: decoded OCSP response
  2356. * data, and a pointer(tbsResponseDataDER) to its undecoded data DER.
  2357. */
  2358. ocspResponseData *
  2359. ocsp_GetResponseData(CERTOCSPResponse *response, SECItem **tbsResponseDataDER)
  2360. {
  2361. ocspBasicOCSPResponse *basic;
  2362. ocspResponseData *responseData;
  2363. PORT_Assert(response != NULL);
  2364. PORT_Assert(response->responseBytes != NULL);
  2365. PORT_Assert(response->responseBytes->responseTypeTag
  2366. == SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
  2367. basic = response->responseBytes->decodedResponse.basic;
  2368. PORT_Assert(basic != NULL);
  2369. responseData = basic->tbsResponseData;
  2370. PORT_Assert(responseData != NULL);
  2371. if (tbsResponseDataDER) {
  2372. *tbsResponseDataDER = &basic->tbsResponseDataDER;
  2373. PORT_Assert((*tbsResponseDataDER)->data != NULL);
  2374. PORT_Assert((*tbsResponseDataDER)->len != 0);
  2375. }
  2376. return responseData;
  2377. }
  2378. /*
  2379. * Much like the routine above, except it returns the response signature.
  2380. * Again, no copy is done.
  2381. */
  2382. ocspSignature *
  2383. ocsp_GetResponseSignature(CERTOCSPResponse *response)
  2384. {
  2385. ocspBasicOCSPResponse *basic;
  2386. PORT_Assert(response != NULL);
  2387. if (NULL == response->responseBytes) {
  2388. return NULL;
  2389. }
  2390. PORT_Assert(response->responseBytes != NULL);
  2391. PORT_Assert(response->responseBytes->responseTypeTag
  2392. == SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
  2393. basic = response->responseBytes->decodedResponse.basic;
  2394. PORT_Assert(basic != NULL);
  2395. return &(basic->responseSignature);
  2396. }
  2397. /*
  2398. * FUNCTION: CERT_DestroyOCSPResponse
  2399. * Frees an OCSP Response structure.
  2400. * INPUTS:
  2401. * CERTOCSPResponse *request
  2402. * Pointer to CERTOCSPResponse to be freed.
  2403. * RETURN:
  2404. * No return value; no errors.
  2405. */
  2406. void
  2407. CERT_DestroyOCSPResponse(CERTOCSPResponse *response)
  2408. {
  2409. if (response != NULL) {
  2410. ocspSignature *signature = ocsp_GetResponseSignature(response);
  2411. if (signature && signature->cert != NULL)
  2412. CERT_DestroyCertificate(signature->cert);
  2413. /*
  2414. * We should actually never have a response without an arena,
  2415. * but check just in case. (If there isn't one, there is not
  2416. * much we can do about it...)
  2417. */
  2418. PORT_Assert(response->arena != NULL);
  2419. if (response->arena != NULL) {
  2420. PORT_FreeArena(response->arena, PR_FALSE);
  2421. }
  2422. }
  2423. }
  2424. /*
  2425. * OVERALL OCSP CLIENT SUPPORT (make and send a request, verify a response):
  2426. */
  2427. /*
  2428. * Pick apart a URL, saving the important things in the passed-in pointers.
  2429. *
  2430. * We expect to find "http://<hostname>[:<port>]/[path]", though we will
  2431. * tolerate that final slash character missing, as well as beginning and
  2432. * trailing whitespace, and any-case-characters for "http". All of that
  2433. * tolerance is what complicates this routine. What we want is just to
  2434. * pick out the hostname, the port, and the path.
  2435. *
  2436. * On a successful return, the caller will need to free the output pieces
  2437. * of hostname and path, which are copies of the values found in the url.
  2438. */
  2439. static SECStatus
  2440. ocsp_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath)
  2441. {
  2442. unsigned short port = 80; /* default, in case not in url */
  2443. char *hostname = NULL;
  2444. char *path = NULL;
  2445. const char *save;
  2446. char c;
  2447. int len;
  2448. if (url == NULL)
  2449. goto loser;
  2450. /*
  2451. * Skip beginning whitespace.
  2452. */
  2453. c = *url;
  2454. while ((c == ' ' || c == '\t') && c != '\0') {
  2455. url++;
  2456. c = *url;
  2457. }
  2458. if (c == '\0')
  2459. goto loser;
  2460. /*
  2461. * Confirm, then skip, protocol. (Since we only know how to do http,
  2462. * that is all we will accept).
  2463. */
  2464. if (PORT_Strncasecmp(url, "http://", 7) != 0)
  2465. goto loser;
  2466. url += 7;
  2467. /*
  2468. * Whatever comes next is the hostname (or host IP address). We just
  2469. * save it aside and then search for its end so we can determine its
  2470. * length and copy it.
  2471. *
  2472. * XXX Note that because we treat a ':' as a terminator character
  2473. * (and below, we expect that to mean there is a port specification
  2474. * immediately following), we will not handle IPv6 addresses. That is
  2475. * apparently an acceptable limitation, for the time being. Some day,
  2476. * when there is a clear way to specify a URL with an IPv6 address that
  2477. * can be parsed unambiguously, this code should be made to do that.
  2478. */
  2479. save = url;
  2480. c = *url;
  2481. while (c != '/' && c != ':' && c != '\0' && c != ' ' && c != '\t') {
  2482. url++;
  2483. c = *url;
  2484. }
  2485. len = url - save;
  2486. hostname = PORT_Alloc(len + 1);
  2487. if (hostname == NULL)
  2488. goto loser;
  2489. PORT_Memcpy(hostname, save, len);
  2490. hostname[len] = '\0';
  2491. /*
  2492. * Now we figure out if there was a port specified or not.
  2493. * If so, we need to parse it (as a number) and skip it.
  2494. */
  2495. if (c == ':') {
  2496. url++;
  2497. port = (unsigned short) PORT_Atoi(url);
  2498. c = *url;
  2499. while (c != '/' && c != '\0' && c != ' ' && c != '\t') {
  2500. if (c < '0' || c > '9')
  2501. goto loser;
  2502. url++;
  2503. c = *url;
  2504. }
  2505. }
  2506. /*
  2507. * Last thing to find is a path. There *should* be a slash,
  2508. * if nothing else -- but if there is not we provide one.
  2509. */
  2510. if (c == '/') {
  2511. save = url;
  2512. while (c != '\0' && c != ' ' && c != '\t') {
  2513. url++;
  2514. c = *url;
  2515. }
  2516. len = url - save;
  2517. path = PORT_Alloc(len + 1);
  2518. if (path == NULL)
  2519. goto loser;
  2520. PORT_Memcpy(path, save, len);
  2521. path[len] = '\0';
  2522. } else {
  2523. path = PORT_Strdup("/");
  2524. if (path == NULL)
  2525. goto loser;
  2526. }
  2527. *pHostname = hostname;
  2528. *pPort = port;
  2529. *pPath = path;
  2530. return SECSuccess;
  2531. loser:
  2532. if (hostname != NULL)
  2533. PORT_Free(hostname);
  2534. PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
  2535. return SECFailure;
  2536. }
  2537. /*
  2538. * Open a socket to the specified host on the specified port, and return it.
  2539. * The host is either a hostname or an IP address.
  2540. */
  2541. static PRFileDesc *
  2542. ocsp_ConnectToHost(const char *host, PRUint16 port)
  2543. {
  2544. PRFileDesc *sock = NULL;
  2545. PRIntervalTime timeout;
  2546. PRNetAddr addr;
  2547. char *netdbbuf = NULL;
  2548. sock = PR_NewTCPSocket();
  2549. if (sock == NULL)
  2550. goto loser;
  2551. /* XXX Some day need a way to set (and get?) the following value */
  2552. timeout = PR_SecondsToInterval(30);
  2553. /*
  2554. * If the following converts an IP address string in "dot notation"
  2555. * into a PRNetAddr. If it fails, we assume that is because we do not
  2556. * have such an address, but instead a host *name*. In that case we
  2557. * then lookup the host by name. Using the NSPR function this way
  2558. * means we do not have to have our own logic for distinguishing a
  2559. * valid numerical IP address from a hostname.
  2560. */
  2561. if (PR_StringToNetAddr(host, &addr) != PR_SUCCESS) {
  2562. PRIntn hostIndex;
  2563. PRHostEnt hostEntry;
  2564. netdbbuf = PORT_Alloc(PR_NETDB_BUF_SIZE);
  2565. if (netdbbuf == NULL)
  2566. goto loser;
  2567. if (PR_GetHostByName(host, netdbbuf, PR_NETDB_BUF_SIZE,
  2568. &hostEntry) != PR_SUCCESS)
  2569. goto loser;
  2570. hostIndex = 0;
  2571. do {
  2572. hostIndex = PR_EnumerateHostEnt(hostIndex, &hostEntry, port, &addr);
  2573. if (hostIndex <= 0)
  2574. goto loser;
  2575. } while (PR_Connect(sock, &addr, timeout) != PR_SUCCESS);
  2576. PORT_Free(netdbbuf);
  2577. } else {
  2578. /*
  2579. * First put the port into the address, then connect.
  2580. */
  2581. if (PR_InitializeNetAddr(PR_IpAddrNull, port, &addr) != PR_SUCCESS)
  2582. goto loser;
  2583. if (PR_Connect(sock, &addr, timeout) != PR_SUCCESS)
  2584. goto loser;
  2585. }
  2586. return sock;
  2587. loser:
  2588. if (sock != NULL)
  2589. PR_Close(sock);
  2590. if (netdbbuf != NULL)
  2591. PORT_Free(netdbbuf);
  2592. return NULL;
  2593. }
  2594. /*
  2595. * Sends an encoded OCSP request to the server identified by "location",
  2596. * and returns the socket on which it was sent (so can listen for the reply).
  2597. * "location" is expected to be a valid URL -- an error parsing it produces
  2598. * SEC_ERROR_CERT_BAD_ACCESS_LOCATION. Other errors are likely problems
  2599. * connecting to it, or writing to it, or allocating memory, and the low-level
  2600. * errors appropriate to the problem will be set.
  2601. */
  2602. static PRFileDesc *
  2603. ocsp_SendEncodedRequest(char *location, SECItem *encodedRequest)
  2604. {
  2605. char *hostname = NULL;
  2606. char *path = NULL;
  2607. PRUint16 port;
  2608. SECStatus rv;
  2609. PRFileDesc *sock = NULL;
  2610. PRFileDesc *returnSock = NULL;
  2611. char *header = NULL;
  2612. char portstr[16];
  2613. /*
  2614. * Take apart the location, getting the hostname, port, and path.
  2615. */
  2616. rv = ocsp_ParseURL(location, &hostname, &port, &path);
  2617. if (rv != SECSuccess)
  2618. goto loser;
  2619. PORT_Assert(hostname != NULL);
  2620. PORT_Assert(path != NULL);
  2621. sock = ocsp_ConnectToHost(hostname, port);
  2622. if (sock == NULL)
  2623. goto loser;
  2624. portstr[0] = '\0';
  2625. if (port != 80) {
  2626. PR_snprintf(portstr, sizeof(portstr), ":%d", port);
  2627. }
  2628. header = PR_smprintf("POST %s HTTP/1.0\r\n"
  2629. "Host: %s%s\r\n"
  2630. "Content-Type: application/ocsp-request\r\n"
  2631. "Content-Length: %u\r\n\r\n",
  2632. path, hostname, portstr, encodedRequest->len);
  2633. if (header == NULL)
  2634. goto loser;
  2635. /*
  2636. * The NSPR documentation promises that if it can, it will write the full
  2637. * amount; this will not return a partial value expecting us to loop.
  2638. */
  2639. if (PR_Write(sock, header, (PRInt32) PORT_Strlen(header)) < 0)
  2640. goto loser;
  2641. if (PR_Write(sock, encodedRequest->data,
  2642. (PRInt32) encodedRequest->len) < 0)
  2643. goto loser;
  2644. returnSock = sock;
  2645. sock = NULL;
  2646. loser:
  2647. if (header != NULL)
  2648. PORT_Free(header);
  2649. if (sock != NULL)
  2650. PR_Close(sock);
  2651. if (path != NULL)
  2652. PORT_Free(path);
  2653. if (hostname != NULL)
  2654. PORT_Free(hostname);
  2655. return returnSock;
  2656. }
  2657. /*
  2658. * Read from "fd" into "buf" -- expect/attempt to read a given number of bytes
  2659. * Obviously, stop if hit end-of-stream. Timeout is passed in.
  2660. */
  2661. static int
  2662. ocsp_read(PRFileDesc *fd, char *buf, int toread, PRIntervalTime timeout)
  2663. {
  2664. int total = 0;
  2665. while (total < toread)
  2666. {
  2667. PRInt32 got;
  2668. got = PR_Recv(fd, buf + total, (PRInt32) (toread - total), 0, timeout);
  2669. if (got < 0)
  2670. {
  2671. if (0 == total)
  2672. {
  2673. total = -1; /* report the error if we didn't read anything yet */
  2674. }
  2675. break;
  2676. }
  2677. else
  2678. if (got == 0)
  2679. { /* EOS */
  2680. break;
  2681. }
  2682. total += got;
  2683. }
  2684. return total;
  2685. }
  2686. #define OCSP_BUFSIZE 1024
  2687. #define AbortHttpDecode(error) \
  2688. { \
  2689. if (inBuffer) \
  2690. PORT_Free(inBuffer); \
  2691. PORT_SetError(error); \
  2692. return NULL; \
  2693. }
  2694. /*
  2695. * Reads on the given socket and returns an encoded response when received.
  2696. * Properly formatted HTTP/1.0 response headers are expected to be read
  2697. * from the socket, preceding a binary-encoded OCSP response. Problems
  2698. * with parsing cause the error SEC_ERROR_OCSP_BAD_HTTP_RESPONSE to be
  2699. * set; any other problems are likely low-level i/o or memory allocation
  2700. * errors.
  2701. */
  2702. static SECItem *
  2703. ocsp_GetEncodedResponse(PRArenaPool *arena, PRFileDesc *sock)
  2704. {
  2705. /* first read HTTP status line and headers */
  2706. char* inBuffer = NULL;
  2707. PRInt32 offset = 0;
  2708. PRInt32 inBufsize = 0;
  2709. const PRInt32 bufSizeIncrement = OCSP_BUFSIZE; /* 1 KB at a time */
  2710. const PRInt32 maxBufSize = 8 * bufSizeIncrement ; /* 8 KB max */
  2711. const char* CRLF = "\r\n";
  2712. const PRInt32 CRLFlen = strlen(CRLF);
  2713. const char* headerEndMark = "\r\n\r\n";
  2714. const PRInt32 markLen = strlen(headerEndMark);
  2715. const PRIntervalTime ocsptimeout =
  2716. PR_SecondsToInterval(30); /* hardcoded to 30s for now */
  2717. char* headerEnd = NULL;
  2718. PRBool EOS = PR_FALSE;
  2719. const char* httpprotocol = "HTTP/";
  2720. const PRInt32 httplen = strlen(httpprotocol);
  2721. const char* httpcode = NULL;
  2722. const char* contenttype = NULL;
  2723. PRInt32 contentlength = 0;
  2724. PRInt32 bytesRead = 0;
  2725. char* statusLineEnd = NULL;
  2726. char* space = NULL;
  2727. char* nextHeader = NULL;
  2728. SECItem* result = NULL;
  2729. /* read up to at least the end of the HTTP headers */
  2730. do
  2731. {
  2732. inBufsize += bufSizeIncrement;
  2733. inBuffer = PORT_Realloc(inBuffer, inBufsize+1);
  2734. if (NULL == inBuffer)
  2735. {
  2736. AbortHttpDecode(SEC_ERROR_NO_MEMORY);
  2737. }
  2738. bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement,
  2739. ocsptimeout);
  2740. if (bytesRead > 0)
  2741. {
  2742. PRInt32 searchOffset = (offset - markLen) >0 ? offset-markLen : 0;
  2743. offset += bytesRead;
  2744. *(inBuffer + offset) = '\0'; /* NULL termination */
  2745. headerEnd = strstr((const char*)inBuffer + searchOffset, headerEndMark);
  2746. if (bytesRead < bufSizeIncrement)
  2747. {
  2748. /* we read less data than requested, therefore we are at
  2749. EOS or there was a read error */
  2750. EOS = PR_TRUE;
  2751. }
  2752. }
  2753. else
  2754. {
  2755. /* recv error or EOS */
  2756. EOS = PR_TRUE;
  2757. }
  2758. } while ( (!headerEnd) && (PR_FALSE == EOS) &&
  2759. (inBufsize < maxBufSize) );
  2760. if (!headerEnd)
  2761. {
  2762. AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  2763. }
  2764. /* parse the HTTP status line */
  2765. statusLineEnd = strstr((const char*)inBuffer, CRLF);
  2766. if (!statusLineEnd)
  2767. {
  2768. AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  2769. }
  2770. *statusLineEnd = '\0';
  2771. /* check for HTTP/ response */
  2772. space = strchr((const char*)inBuffer, ' ');
  2773. if (!space || PORT_Strncasecmp((const char*)inBuffer, httpprotocol, httplen) != 0 )
  2774. {
  2775. AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  2776. }
  2777. /* check the HTTP status code of 200 */
  2778. httpcode = space +1;
  2779. space = strchr(httpcode, ' ');
  2780. if (!space)
  2781. {
  2782. AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  2783. }
  2784. *space = 0;
  2785. if (0 != strcmp(httpcode, "200"))
  2786. {
  2787. AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  2788. }
  2789. /* parse the HTTP headers in the buffer . We only care about
  2790. content-type and content-length
  2791. */
  2792. nextHeader = statusLineEnd + CRLFlen;
  2793. *headerEnd = '\0'; /* terminate */
  2794. do
  2795. {
  2796. char* thisHeaderEnd = NULL;
  2797. char* value = NULL;
  2798. char* colon = strchr(nextHeader, ':');
  2799. if (!colon)
  2800. {
  2801. AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  2802. }
  2803. *colon = '\0';
  2804. value = colon + 1;
  2805. /* jpierre - note : the following code will only handle the basic form
  2806. of HTTP/1.0 response headers, of the form "name: value" . Headers
  2807. split among multiple lines are not supported. This is not common
  2808. and should not be an issue, but it could become one in the
  2809. future */
  2810. if (*value != ' ')
  2811. {
  2812. AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  2813. }
  2814. value++;
  2815. thisHeaderEnd = strstr(value, CRLF);
  2816. if (thisHeaderEnd )
  2817. {
  2818. *thisHeaderEnd = '\0';
  2819. }
  2820. if (0 == PORT_Strcasecmp(nextHeader, "content-type"))
  2821. {
  2822. contenttype = value;
  2823. }
  2824. else
  2825. if (0 == PORT_Strcasecmp(nextHeader, "content-length"))
  2826. {
  2827. contentlength = atoi(value);
  2828. }
  2829. if (thisHeaderEnd )
  2830. {
  2831. nextHeader = thisHeaderEnd + CRLFlen;
  2832. }
  2833. else
  2834. {
  2835. nextHeader = NULL;
  2836. }
  2837. } while (nextHeader && (nextHeader < (headerEnd + CRLFlen) ) );
  2838. /* check content-type */
  2839. if (!contenttype ||
  2840. (0 != PORT_Strcasecmp(contenttype, "application/ocsp-response")) )
  2841. {
  2842. AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  2843. }
  2844. /* read the body of the OCSP response */
  2845. offset = offset - (PRInt32) (headerEnd - (const char*)inBuffer) - markLen;
  2846. if (offset)
  2847. {
  2848. /* move all data to the beginning of the buffer */
  2849. PORT_Memmove(inBuffer, headerEnd + markLen, offset);
  2850. }
  2851. /* resize buffer to only what's needed to hold the current response */
  2852. inBufsize = (1 + (offset-1) / bufSizeIncrement ) * bufSizeIncrement ;
  2853. while ( (PR_FALSE == EOS) &&
  2854. ( (contentlength == 0) || (offset < contentlength) ) &&
  2855. (inBufsize < maxBufSize)
  2856. )
  2857. {
  2858. /* we still need to receive more body data */
  2859. inBufsize += bufSizeIncrement;
  2860. inBuffer = PORT_Realloc(inBuffer, inBufsize+1);
  2861. if (NULL == inBuffer)
  2862. {
  2863. AbortHttpDecode(SEC_ERROR_NO_MEMORY);
  2864. }
  2865. bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement,
  2866. ocsptimeout);
  2867. if (bytesRead > 0)
  2868. {
  2869. offset += bytesRead;
  2870. if (bytesRead < bufSizeIncrement)
  2871. {
  2872. /* we read less data than requested, therefore we are at
  2873. EOS or there was a read error */
  2874. EOS = PR_TRUE;
  2875. }
  2876. }
  2877. else
  2878. {
  2879. /* recv error or EOS */
  2880. EOS = PR_TRUE;
  2881. }
  2882. }
  2883. if (0 == offset)
  2884. {
  2885. AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  2886. }
  2887. /*
  2888. * Now allocate the item to hold the data.
  2889. */
  2890. result = SECITEM_AllocItem(arena, NULL, offset);
  2891. if (NULL == result)
  2892. {
  2893. AbortHttpDecode(SEC_ERROR_NO_MEMORY);
  2894. }
  2895. /*
  2896. * And copy the data left in the buffer.
  2897. */
  2898. PORT_Memcpy(result->data, inBuffer, offset);
  2899. /* and free the temporary buffer */
  2900. PORT_Free(inBuffer);
  2901. return result;
  2902. }
  2903. SECStatus
  2904. CERT_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath)
  2905. {
  2906. return ocsp_ParseURL(url, pHostname, pPort, pPath);
  2907. }
  2908. /*
  2909. * Limit the size of http responses we are willing to accept.
  2910. */
  2911. #define MAX_WANTED_OCSP_RESPONSE_LEN 64*1024
  2912. static SECItem *
  2913. fetchOcspHttpClientV1(PRArenaPool *arena,
  2914. const SEC_HttpClientFcnV1 *hcv1,
  2915. char *location,
  2916. SECItem *encodedRequest)
  2917. {
  2918. char *hostname = NULL;
  2919. char *path = NULL;
  2920. PRUint16 port;
  2921. SECItem *encodedResponse = NULL;
  2922. SEC_HTTP_SERVER_SESSION pServerSession = NULL;
  2923. SEC_HTTP_REQUEST_SESSION pRequestSession = NULL;
  2924. PRUint16 myHttpResponseCode;
  2925. const char *myHttpResponseData;
  2926. PRUint32 myHttpResponseDataLen;
  2927. if (ocsp_ParseURL(location, &hostname, &port, &path) == SECFailure) {
  2928. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
  2929. goto loser;
  2930. }
  2931. PORT_Assert(hostname != NULL);
  2932. PORT_Assert(path != NULL);
  2933. if ((*hcv1->createSessionFcn)(
  2934. hostname,
  2935. port,
  2936. &pServerSession) != SECSuccess) {
  2937. PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
  2938. goto loser;
  2939. }
  2940. /* We use a non-zero timeout, which means:
  2941. - the client will use blocking I/O
  2942. - TryFcn will not return WOULD_BLOCK nor a poll descriptor
  2943. - it's sufficient to call TryFcn once
  2944. No lock for accessing OCSP_Global.timeoutSeconds, bug 406120
  2945. */
  2946. if ((*hcv1->createFcn)(
  2947. pServerSession,
  2948. "http",
  2949. path,
  2950. "POST",
  2951. PR_TicksPerSecond() * OCSP_Global.timeoutSeconds,
  2952. &pRequestSession) != SECSuccess) {
  2953. PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
  2954. goto loser;
  2955. }
  2956. if ((*hcv1->setPostDataFcn)(
  2957. pRequestSession,
  2958. (char*)encodedRequest->data,
  2959. encodedRequest->len,
  2960. "application/ocsp-request") != SECSuccess) {
  2961. PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
  2962. goto loser;
  2963. }
  2964. /* we don't want result objects larger than this: */
  2965. myHttpResponseDataLen = MAX_WANTED_OCSP_RESPONSE_LEN;
  2966. OCSP_TRACE(("OCSP trySendAndReceive %s\n", location));
  2967. if ((*hcv1->trySendAndReceiveFcn)(
  2968. pRequestSession,
  2969. NULL,
  2970. &myHttpResponseCode,
  2971. NULL,
  2972. NULL,
  2973. &myHttpResponseData,
  2974. &myHttpResponseDataLen) != SECSuccess) {
  2975. PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
  2976. goto loser;
  2977. }
  2978. OCSP_TRACE(("OCSP trySendAndReceive result http %d\n", myHttpResponseCode));
  2979. if (myHttpResponseCode != 200) {
  2980. PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  2981. goto loser;
  2982. }
  2983. encodedResponse = SECITEM_AllocItem(arena, NULL, myHttpResponseDataLen);
  2984. if (!encodedResponse) {
  2985. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2986. goto loser;
  2987. }
  2988. PORT_Memcpy(encodedResponse->data, myHttpResponseData, myHttpResponseDataLen);
  2989. loser:
  2990. if (pRequestSession != NULL)
  2991. (*hcv1->freeFcn)(pRequestSession);
  2992. if (pServerSession != NULL)
  2993. (*hcv1->freeSessionFcn)(pServerSession);
  2994. if (path != NULL)
  2995. PORT_Free(path);
  2996. if (hostname != NULL)
  2997. PORT_Free(hostname);
  2998. return encodedResponse;
  2999. }
  3000. /*
  3001. * FUNCTION: CERT_GetEncodedOCSPResponse
  3002. * Creates and sends a request to an OCSP responder, then reads and
  3003. * returns the (encoded) response.
  3004. * INPUTS:
  3005. * PRArenaPool *arena
  3006. * Pointer to arena from which return value will be allocated.
  3007. * If NULL, result will be allocated from the heap (and thus should
  3008. * be freed via SECITEM_FreeItem).
  3009. * CERTCertList *certList
  3010. * A list of certs for which status will be requested.
  3011. * Note that all of these certificates should have the same issuer,
  3012. * or it's expected the response will be signed by a trusted responder.
  3013. * If the certs need to be broken up into multiple requests, that
  3014. * must be handled by the caller (and thus by having multiple calls
  3015. * to this routine), who knows about where the request(s) are being
  3016. * sent and whether there are any trusted responders in place.
  3017. * char *location
  3018. * The location of the OCSP responder (a URL).
  3019. * int64 time
  3020. * Indicates the time for which the certificate status is to be
  3021. * determined -- this may be used in the search for the cert's issuer
  3022. * but has no other bearing on the operation.
  3023. * PRBool addServiceLocator
  3024. * If true, the Service Locator extension should be added to the
  3025. * single request(s) for each cert.
  3026. * CERTCertificate *signerCert
  3027. * If non-NULL, means sign the request using this cert. Otherwise,
  3028. * do not sign.
  3029. * void *pwArg
  3030. * Pointer to argument for password prompting, if needed. (Definitely
  3031. * not needed if not signing.)
  3032. * OUTPUTS:
  3033. * CERTOCSPRequest **pRequest
  3034. * Pointer in which to store the OCSP request created for the given
  3035. * list of certificates. It is only filled in if the entire operation
  3036. * is successful and the pointer is not null -- and in that case the
  3037. * caller is then reponsible for destroying it.
  3038. * RETURN:
  3039. * Returns a pointer to the SECItem holding the response.
  3040. * On error, returns null with error set describing the reason:
  3041. * SEC_ERROR_UNKNOWN_ISSUER
  3042. * SEC_ERROR_CERT_BAD_ACCESS_LOCATION
  3043. * SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
  3044. * Other errors are low-level problems (no memory, bad database, etc.).
  3045. */
  3046. SECItem *
  3047. CERT_GetEncodedOCSPResponse(PRArenaPool *arena, CERTCertList *certList,
  3048. char *location, int64 time,
  3049. PRBool addServiceLocator,
  3050. CERTCertificate *signerCert, void *pwArg,
  3051. CERTOCSPRequest **pRequest)
  3052. {
  3053. CERTOCSPRequest *request;
  3054. request = CERT_CreateOCSPRequest(certList, time, addServiceLocator,
  3055. signerCert);
  3056. if (!request)
  3057. return NULL;
  3058. return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location,
  3059. time, addServiceLocator,
  3060. pwArg, pRequest);
  3061. }
  3062. static SECItem *
  3063. ocsp_GetEncodedOCSPResponseFromRequest(PRArenaPool *arena,
  3064. CERTOCSPRequest *request,
  3065. char *location, int64 time,
  3066. PRBool addServiceLocator,
  3067. void *pwArg,
  3068. CERTOCSPRequest **pRequest)
  3069. {
  3070. SECItem *encodedRequest = NULL;
  3071. SECItem *encodedResponse = NULL;
  3072. PRFileDesc *sock = NULL;
  3073. SECStatus rv;
  3074. const SEC_HttpClientFcn *registeredHttpClient = NULL;
  3075. rv = CERT_AddOCSPAcceptableResponses(request,
  3076. SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
  3077. if (rv != SECSuccess)
  3078. goto loser;
  3079. encodedRequest = CERT_EncodeOCSPRequest(NULL, request, pwArg);
  3080. if (encodedRequest == NULL)
  3081. goto loser;
  3082. registeredHttpClient = SEC_GetRegisteredHttpClient();
  3083. if (registeredHttpClient
  3084. &&
  3085. registeredHttpClient->version == 1) {
  3086. encodedResponse = fetchOcspHttpClientV1(
  3087. arena,
  3088. &registeredHttpClient->fcnTable.ftable1,
  3089. location,
  3090. encodedRequest);
  3091. }
  3092. else {
  3093. /* use internal http client */
  3094. sock = ocsp_SendEncodedRequest(location, encodedRequest);
  3095. if (sock == NULL)
  3096. goto loser;
  3097. encodedResponse = ocsp_GetEncodedResponse(arena, sock);
  3098. }
  3099. if (encodedResponse != NULL && pRequest != NULL) {
  3100. *pRequest = request;
  3101. request = NULL; /* avoid destroying below */
  3102. }
  3103. loser:
  3104. if (request != NULL)
  3105. CERT_DestroyOCSPRequest(request);
  3106. if (encodedRequest != NULL)
  3107. SECITEM_FreeItem(encodedRequest, PR_TRUE);
  3108. if (sock != NULL)
  3109. PR_Close(sock);
  3110. return encodedResponse;
  3111. }
  3112. static SECItem *
  3113. ocsp_GetEncodedOCSPResponseForSingleCert(PRArenaPool *arena,
  3114. CERTOCSPCertID *certID,
  3115. CERTCertificate *singleCert,
  3116. char *location, int64 time,
  3117. PRBool addServiceLocator,
  3118. void *pwArg,
  3119. CERTOCSPRequest **pRequest)
  3120. {
  3121. CERTOCSPRequest *request;
  3122. request = cert_CreateSingleCertOCSPRequest(certID, singleCert, time,
  3123. addServiceLocator, NULL);
  3124. if (!request)
  3125. return NULL;
  3126. return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location,
  3127. time, addServiceLocator,
  3128. pwArg, pRequest);
  3129. }
  3130. /* Checks a certificate for the key usage extension of OCSP signer. */
  3131. static PRBool
  3132. ocsp_CertIsOCSPDesignatedResponder(CERTCertificate *cert)
  3133. {
  3134. SECStatus rv;
  3135. SECItem extItem;
  3136. SECItem **oids;
  3137. SECItem *oid;
  3138. SECOidTag oidTag;
  3139. PRBool retval;
  3140. CERTOidSequence *oidSeq = NULL;
  3141. extItem.data = NULL;
  3142. rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem);
  3143. if ( rv != SECSuccess ) {
  3144. goto loser;
  3145. }
  3146. oidSeq = CERT_DecodeOidSequence(&extItem);
  3147. if ( oidSeq == NULL ) {
  3148. goto loser;
  3149. }
  3150. oids = oidSeq->oids;
  3151. while ( *oids != NULL ) {
  3152. oid = *oids;
  3153. oidTag = SECOID_FindOIDTag(oid);
  3154. if ( oidTag == SEC_OID_OCSP_RESPONDER ) {
  3155. goto success;
  3156. }
  3157. oids++;
  3158. }
  3159. loser:
  3160. retval = PR_FALSE;
  3161. PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
  3162. goto done;
  3163. success:
  3164. retval = PR_TRUE;
  3165. done:
  3166. if ( extItem.data != NULL ) {
  3167. PORT_Free(extItem.data);
  3168. }
  3169. if ( oidSeq != NULL ) {
  3170. CERT_DestroyOidSequence(oidSeq);
  3171. }
  3172. return(retval);
  3173. }
  3174. #ifdef LATER /*
  3175. * XXX This function is not currently used, but will
  3176. * be needed later when we do revocation checking of
  3177. * the responder certificate. Of course, it may need
  3178. * revising then, if the cert extension interface has
  3179. * changed. (Hopefully it will!)
  3180. */
  3181. /* Checks a certificate to see if it has the OCSP no check extension. */
  3182. static PRBool
  3183. ocsp_CertHasNoCheckExtension(CERTCertificate *cert)
  3184. {
  3185. SECStatus rv;
  3186. rv = CERT_FindCertExtension(cert, SEC_OID_PKIX_OCSP_NO_CHECK,
  3187. NULL);
  3188. if (rv == SECSuccess) {
  3189. return PR_TRUE;
  3190. }
  3191. return PR_FALSE;
  3192. }
  3193. #endif /* LATER */
  3194. static PRBool
  3195. ocsp_matchcert(SECItem *certIndex,CERTCertificate *testCert)
  3196. {
  3197. SECItem item;
  3198. unsigned char buf[HASH_LENGTH_MAX];
  3199. item.data = buf;
  3200. item.len = SHA1_LENGTH;
  3201. if (CERT_GetSPKIDigest(NULL,testCert,SEC_OID_SHA1, &item) == NULL) {
  3202. return PR_FALSE;
  3203. }
  3204. if (SECITEM_ItemsAreEqual(certIndex,&item)) {
  3205. return PR_TRUE;
  3206. }
  3207. if (CERT_GetSPKIDigest(NULL,testCert,SEC_OID_MD5, &item) == NULL) {
  3208. return PR_FALSE;
  3209. }
  3210. if (SECITEM_ItemsAreEqual(certIndex,&item)) {
  3211. return PR_TRUE;
  3212. }
  3213. if (CERT_GetSPKIDigest(NULL,testCert,SEC_OID_MD2, &item) == NULL) {
  3214. return PR_FALSE;
  3215. }
  3216. if (SECITEM_ItemsAreEqual(certIndex,&item)) {
  3217. return PR_TRUE;
  3218. }
  3219. return PR_FALSE;
  3220. }
  3221. static CERTCertificate *
  3222. ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle,CERTOCSPCertID *certID);
  3223. CERTCertificate *
  3224. ocsp_GetSignerCertificate(CERTCertDBHandle *handle, ocspResponseData *tbsData,
  3225. ocspSignature *signature, CERTCertificate *issuer)
  3226. {
  3227. CERTCertificate **certs = NULL;
  3228. CERTCertificate *signerCert = NULL;
  3229. SECStatus rv = SECFailure;
  3230. PRBool lookupByName = PR_TRUE;
  3231. void *certIndex = NULL;
  3232. int certCount = 0;
  3233. PORT_Assert(tbsData->responderID != NULL);
  3234. switch (tbsData->responderID->responderIDType) {
  3235. case ocspResponderID_byName:
  3236. lookupByName = PR_TRUE;
  3237. certIndex = &tbsData->derResponderID;
  3238. break;
  3239. case ocspResponderID_byKey:
  3240. lookupByName = PR_FALSE;
  3241. certIndex = &tbsData->responderID->responderIDValue.keyHash;
  3242. break;
  3243. case ocspResponderID_other:
  3244. default:
  3245. PORT_Assert(0);
  3246. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  3247. return NULL;
  3248. }
  3249. /*
  3250. * If the signature contains some certificates as well, temporarily
  3251. * import them in case they are needed for verification.
  3252. *
  3253. * Note that the result of this is that each cert in "certs" needs
  3254. * to be destroyed.
  3255. */
  3256. if (signature->derCerts != NULL) {
  3257. for (; signature->derCerts[certCount] != NULL; certCount++) {
  3258. /* just counting */
  3259. }
  3260. rv = CERT_ImportCerts(handle, certUsageStatusResponder, certCount,
  3261. signature->derCerts, &certs,
  3262. PR_FALSE, PR_FALSE, NULL);
  3263. if (rv != SECSuccess)
  3264. goto finish;
  3265. }
  3266. /*
  3267. * Now look up the certificate that did the signing.
  3268. * The signer can be specified either by name or by key hash.
  3269. */
  3270. if (lookupByName) {
  3271. SECItem *crIndex = (SECItem*)certIndex;
  3272. SECItem encodedName;
  3273. PLArenaPool *arena;
  3274. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  3275. if (arena != NULL) {
  3276. rv = SEC_QuickDERDecodeItem(arena, &encodedName,
  3277. ocsp_ResponderIDDerNameTemplate,
  3278. crIndex);
  3279. if (rv != SECSuccess) {
  3280. if (PORT_GetError() == SEC_ERROR_BAD_DER)
  3281. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  3282. } else {
  3283. signerCert = CERT_FindCertByName(handle, &encodedName);
  3284. }
  3285. PORT_FreeArena(arena, PR_FALSE);
  3286. }
  3287. } else {
  3288. /*
  3289. * The signer is either 1) a known issuer CA we passed in,
  3290. * 2) the default OCSP responder, or 3) an intermediate CA
  3291. * passed in the cert list to use. Figure out which it is.
  3292. */
  3293. int i;
  3294. CERTCertificate *responder =
  3295. ocsp_CertGetDefaultResponder(handle, NULL);
  3296. if (responder && ocsp_matchcert(certIndex,responder)) {
  3297. signerCert = CERT_DupCertificate(responder);
  3298. } else if (issuer && ocsp_matchcert(certIndex,issuer)) {
  3299. signerCert = CERT_DupCertificate(issuer);
  3300. }
  3301. for (i=0; (signerCert == NULL) && (i < certCount); i++) {
  3302. if (ocsp_matchcert(certIndex,certs[i])) {
  3303. signerCert = CERT_DupCertificate(certs[i]);
  3304. }
  3305. }
  3306. }
  3307. finish:
  3308. if (certs != NULL) {
  3309. CERT_DestroyCertArray(certs, certCount);
  3310. }
  3311. return signerCert;
  3312. }
  3313. SECStatus
  3314. ocsp_VerifyResponseSignature(CERTCertificate *signerCert,
  3315. ocspSignature *signature,
  3316. SECItem *tbsResponseDataDER,
  3317. void *pwArg)
  3318. {
  3319. SECItem rawSignature;
  3320. SECKEYPublicKey *signerKey = NULL;
  3321. SECStatus rv = SECFailure;
  3322. /*
  3323. * Now get the public key from the signer's certificate; we need
  3324. * it to perform the verification.
  3325. */
  3326. signerKey = CERT_ExtractPublicKey(signerCert);
  3327. if (signerKey == NULL)
  3328. return SECFailure;
  3329. /*
  3330. * We copy the signature data *pointer* and length, so that we can
  3331. * modify the length without damaging the original copy. This is a
  3332. * simple copy, not a dup, so no destroy/free is necessary.
  3333. */
  3334. rawSignature = signature->signature;
  3335. /*
  3336. * The raw signature is a bit string, but we need to represent its
  3337. * length in bytes, because that is what the verify function expects.
  3338. */
  3339. DER_ConvertBitString(&rawSignature);
  3340. rv = VFY_VerifyDataWithAlgorithmID(tbsResponseDataDER->data,
  3341. tbsResponseDataDER->len,
  3342. signerKey, &rawSignature,
  3343. &signature->signatureAlgorithm,
  3344. NULL, pwArg);
  3345. if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_BAD_SIGNATURE) {
  3346. PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE);
  3347. }
  3348. if (signerKey != NULL) {
  3349. SECKEY_DestroyPublicKey(signerKey);
  3350. }
  3351. return rv;
  3352. }
  3353. /*
  3354. * FUNCTION: CERT_VerifyOCSPResponseSignature
  3355. * Check the signature on an OCSP Response. Will also perform a
  3356. * verification of the signer's certificate. Note, however, that a
  3357. * successful verification does not make any statement about the
  3358. * signer's *authority* to provide status for the certificate(s),
  3359. * that must be checked individually for each certificate.
  3360. * INPUTS:
  3361. * CERTOCSPResponse *response
  3362. * Pointer to response structure with signature to be checked.
  3363. * CERTCertDBHandle *handle
  3364. * Pointer to CERTCertDBHandle for certificate DB to use for verification.
  3365. * void *pwArg
  3366. * Pointer to argument for password prompting, if needed.
  3367. * OUTPUTS:
  3368. * CERTCertificate **pSignerCert
  3369. * Pointer in which to store signer's certificate; only filled-in if
  3370. * non-null.
  3371. * RETURN:
  3372. * Returns SECSuccess when signature is valid, anything else means invalid.
  3373. * Possible errors set:
  3374. * SEC_ERROR_OCSP_MALFORMED_RESPONSE - unknown type of ResponderID
  3375. * SEC_ERROR_INVALID_TIME - bad format of "ProducedAt" time
  3376. * SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found
  3377. * SEC_ERROR_BAD_SIGNATURE - the signature did not verify
  3378. * Other errors are any of the many possible failures in cert verification
  3379. * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
  3380. * verifying the signer's cert, or low-level problems (no memory, etc.)
  3381. */
  3382. SECStatus
  3383. CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response,
  3384. CERTCertDBHandle *handle, void *pwArg,
  3385. CERTCertificate **pSignerCert,
  3386. CERTCertificate *issuer)
  3387. {
  3388. SECItem *tbsResponseDataDER;
  3389. CERTCertificate *signerCert = NULL;
  3390. SECStatus rv = SECFailure;
  3391. int64 producedAt;
  3392. /* ocsp_DecodeBasicOCSPResponse will fail if asn1 decoder is unable
  3393. * to properly decode tbsData (see the function and
  3394. * ocsp_BasicOCSPResponseTemplate). Thus, tbsData can not be
  3395. * equal to null */
  3396. ocspResponseData *tbsData = ocsp_GetResponseData(response,
  3397. &tbsResponseDataDER);
  3398. ocspSignature *signature = ocsp_GetResponseSignature(response);
  3399. if (!signature) {
  3400. PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE);
  3401. return SECFailure;
  3402. }
  3403. /*
  3404. * If this signature has already gone through verification, just
  3405. * return the cached result.
  3406. */
  3407. if (signature->wasChecked) {
  3408. if (signature->status == SECSuccess) {
  3409. if (pSignerCert != NULL)
  3410. *pSignerCert = CERT_DupCertificate(signature->cert);
  3411. } else {
  3412. PORT_SetError(signature->failureReason);
  3413. }
  3414. return signature->status;
  3415. }
  3416. signerCert = ocsp_GetSignerCertificate(handle, tbsData,
  3417. signature, issuer);
  3418. if (signerCert == NULL) {
  3419. rv = SECFailure;
  3420. if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) {
  3421. /* Make the error a little more specific. */
  3422. PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
  3423. }
  3424. goto finish;
  3425. }
  3426. /*
  3427. * We could mark this true at the top of this function, or always
  3428. * below at "finish", but if the problem was just that we could not
  3429. * find the signer's cert, leave that as if the signature hasn't
  3430. * been checked in case a subsequent call might have better luck.
  3431. */
  3432. signature->wasChecked = PR_TRUE;
  3433. /*
  3434. * The function will also verify the signer certificate; we
  3435. * need to tell it *when* that certificate must be valid -- for our
  3436. * purposes we expect it to be valid when the response was signed.
  3437. * The value of "producedAt" is the signing time.
  3438. */
  3439. rv = DER_GeneralizedTimeToTime(&producedAt, &tbsData->producedAt);
  3440. if (rv != SECSuccess)
  3441. goto finish;
  3442. /*
  3443. * Just because we have a cert does not mean it is any good; check
  3444. * it for validity, trust and usage.
  3445. */
  3446. if (ocsp_CertIsOCSPDefaultResponder(handle, signerCert)) {
  3447. rv = SECSuccess;
  3448. } else {
  3449. SECCertUsage certUsage;
  3450. if (CERT_IsCACert(signerCert, NULL)) {
  3451. certUsage = certUsageAnyCA;
  3452. } else {
  3453. certUsage = certUsageStatusResponder;
  3454. }
  3455. rv = CERT_VerifyCert(handle, signerCert, PR_TRUE,
  3456. certUsage, producedAt, pwArg, NULL);
  3457. if (rv != SECSuccess) {
  3458. PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
  3459. goto finish;
  3460. }
  3461. }
  3462. rv = ocsp_VerifyResponseSignature(signerCert, signature,
  3463. tbsResponseDataDER,
  3464. pwArg);
  3465. finish:
  3466. if (signature->wasChecked)
  3467. signature->status = rv;
  3468. if (rv != SECSuccess) {
  3469. signature->failureReason = PORT_GetError();
  3470. if (signerCert != NULL)
  3471. CERT_DestroyCertificate(signerCert);
  3472. } else {
  3473. /*
  3474. * Save signer's certificate in signature.
  3475. */
  3476. signature->cert = signerCert;
  3477. if (pSignerCert != NULL) {
  3478. /*
  3479. * Pass pointer to signer's certificate back to our caller,
  3480. * who is also now responsible for destroying it.
  3481. */
  3482. *pSignerCert = CERT_DupCertificate(signerCert);
  3483. }
  3484. }
  3485. return rv;
  3486. }
  3487. /*
  3488. * See if the request's certID and the single response's certID match.
  3489. * This can be easy or difficult, depending on whether the same hash
  3490. * algorithm was used.
  3491. */
  3492. static PRBool
  3493. ocsp_CertIDsMatch(CERTCertDBHandle *handle,
  3494. CERTOCSPCertID *requestCertID,
  3495. CERTOCSPCertID *responseCertID)
  3496. {
  3497. PRBool match = PR_FALSE;
  3498. SECOidTag hashAlg;
  3499. SECItem *keyHash = NULL;
  3500. SECItem *nameHash = NULL;
  3501. /*
  3502. * In order to match, they must have the same issuer and the same
  3503. * serial number.
  3504. *
  3505. * We just compare the easier things first.
  3506. */
  3507. if (SECITEM_CompareItem(&requestCertID->serialNumber,
  3508. &responseCertID->serialNumber) != SECEqual) {
  3509. goto done;
  3510. }
  3511. /*
  3512. * Make sure the "parameters" are not too bogus. Since we encoded
  3513. * requestCertID->hashAlgorithm, we don't need to check it.
  3514. */
  3515. if (responseCertID->hashAlgorithm.parameters.len > 2) {
  3516. goto done;
  3517. }
  3518. if (SECITEM_CompareItem(&requestCertID->hashAlgorithm.algorithm,
  3519. &responseCertID->hashAlgorithm.algorithm) == SECEqual) {
  3520. /*
  3521. * If the hash algorithms match then we can do a simple compare
  3522. * of the hash values themselves.
  3523. */
  3524. if ((SECITEM_CompareItem(&requestCertID->issuerNameHash,
  3525. &responseCertID->issuerNameHash) == SECEqual)
  3526. && (SECITEM_CompareItem(&requestCertID->issuerKeyHash,
  3527. &responseCertID->issuerKeyHash) == SECEqual)) {
  3528. match = PR_TRUE;
  3529. }
  3530. goto done;
  3531. }
  3532. hashAlg = SECOID_FindOIDTag(&responseCertID->hashAlgorithm.algorithm);
  3533. switch (hashAlg) {
  3534. case SEC_OID_SHA1:
  3535. keyHash = &requestCertID->issuerSHA1KeyHash;
  3536. nameHash = &requestCertID->issuerSHA1NameHash;
  3537. break;
  3538. case SEC_OID_MD5:
  3539. keyHash = &requestCertID->issuerMD5KeyHash;
  3540. nameHash = &requestCertID->issuerMD5NameHash;
  3541. break;
  3542. case SEC_OID_MD2:
  3543. keyHash = &requestCertID->issuerMD2KeyHash;
  3544. nameHash = &requestCertID->issuerMD2NameHash;
  3545. break;
  3546. default:
  3547. PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  3548. return SECFailure;
  3549. }
  3550. if ((keyHash != NULL)
  3551. && (SECITEM_CompareItem(nameHash,
  3552. &responseCertID->issuerNameHash) == SECEqual)
  3553. && (SECITEM_CompareItem(keyHash,
  3554. &responseCertID->issuerKeyHash) == SECEqual)) {
  3555. match = PR_TRUE;
  3556. }
  3557. done:
  3558. return match;
  3559. }
  3560. /*
  3561. * Find the single response for the cert specified by certID.
  3562. * No copying is done; this just returns a pointer to the appropriate
  3563. * response within responses, if it is found (and null otherwise).
  3564. * This is fine, of course, since this function is internal-use only.
  3565. */
  3566. static CERTOCSPSingleResponse *
  3567. ocsp_GetSingleResponseForCertID(CERTOCSPSingleResponse **responses,
  3568. CERTCertDBHandle *handle,
  3569. CERTOCSPCertID *certID)
  3570. {
  3571. CERTOCSPSingleResponse *single;
  3572. int i;
  3573. if (responses == NULL)
  3574. return NULL;
  3575. for (i = 0; responses[i] != NULL; i++) {
  3576. single = responses[i];
  3577. if (ocsp_CertIDsMatch(handle, certID, single->certID)) {
  3578. return single;
  3579. }
  3580. }
  3581. /*
  3582. * The OCSP server should have included a response even if it knew
  3583. * nothing about the certificate in question. Since it did not,
  3584. * this will make it look as if it had.
  3585. *
  3586. * XXX Should we make this a separate error to notice the server's
  3587. * bad behavior?
  3588. */
  3589. PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
  3590. return NULL;
  3591. }
  3592. static ocspCheckingContext *
  3593. ocsp_GetCheckingContext(CERTCertDBHandle *handle)
  3594. {
  3595. CERTStatusConfig *statusConfig;
  3596. ocspCheckingContext *ocspcx = NULL;
  3597. statusConfig = CERT_GetStatusConfig(handle);
  3598. if (statusConfig != NULL) {
  3599. ocspcx = statusConfig->statusContext;
  3600. /*
  3601. * This is actually an internal error, because we should never
  3602. * have a good statusConfig without a good statusContext, too.
  3603. * For lack of anything better, though, we just assert and use
  3604. * the same error as if there were no statusConfig (set below).
  3605. */
  3606. PORT_Assert(ocspcx != NULL);
  3607. }
  3608. if (ocspcx == NULL)
  3609. PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED);
  3610. return ocspcx;
  3611. }
  3612. /*
  3613. * Return cert reference if the given signerCert is the default responder for
  3614. * the given certID. If not, or if any error, return NULL.
  3615. */
  3616. static CERTCertificate *
  3617. ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle, CERTOCSPCertID *certID)
  3618. {
  3619. ocspCheckingContext *ocspcx;
  3620. ocspcx = ocsp_GetCheckingContext(handle);
  3621. if (ocspcx == NULL)
  3622. goto loser;
  3623. /*
  3624. * Right now we have only one default responder. It applies to
  3625. * all certs when it is used, so the check is simple and certID
  3626. * has no bearing on the answer. Someday in the future we may
  3627. * allow configuration of different responders for different
  3628. * issuers, and then we would have to use the issuer specified
  3629. * in certID to determine if signerCert is the right one.
  3630. */
  3631. if (ocspcx->useDefaultResponder) {
  3632. PORT_Assert(ocspcx->defaultResponderCert != NULL);
  3633. return ocspcx->defaultResponderCert;
  3634. }
  3635. loser:
  3636. return NULL;
  3637. }
  3638. /*
  3639. * Return true if the cert is one of the default responders configured for
  3640. * ocsp context. If not, or if any error, return false.
  3641. */
  3642. PRBool
  3643. ocsp_CertIsOCSPDefaultResponder(CERTCertDBHandle *handle, CERTCertificate *cert)
  3644. {
  3645. ocspCheckingContext *ocspcx;
  3646. ocspcx = ocsp_GetCheckingContext(handle);
  3647. if (ocspcx == NULL)
  3648. return PR_FALSE;
  3649. /*
  3650. * Right now we have only one default responder. It applies to
  3651. * all certs when it is used, so the check is simple and certID
  3652. * has no bearing on the answer. Someday in the future we may
  3653. * allow configuration of different responders for different
  3654. * issuers, and then we would have to use the issuer specified
  3655. * in certID to determine if signerCert is the right one.
  3656. */
  3657. if (ocspcx->useDefaultResponder &&
  3658. CERT_CompareCerts(ocspcx->defaultResponderCert, cert)) {
  3659. return PR_TRUE;
  3660. }
  3661. return PR_FALSE;
  3662. }
  3663. /*
  3664. * Check that the given signer certificate is authorized to sign status
  3665. * information for the given certID. Return true if it is, false if not
  3666. * (or if there is any error along the way). If false is returned because
  3667. * the signer is not authorized, the following error will be set:
  3668. * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
  3669. * Other errors are low-level problems (no memory, bad database, etc.).
  3670. *
  3671. * There are three ways to be authorized. In the order in which we check,
  3672. * using the terms used in the OCSP spec, the signer must be one of:
  3673. * 1. A "trusted responder" -- it matches a local configuration
  3674. * of OCSP signing authority for the certificate in question.
  3675. * 2. The CA who issued the certificate in question.
  3676. * 3. A "CA designated responder", aka an "authorized responder" -- it
  3677. * must be represented by a special cert issued by the CA who issued
  3678. * the certificate in question.
  3679. */
  3680. static PRBool
  3681. ocsp_AuthorizedResponderForCertID(CERTCertDBHandle *handle,
  3682. CERTCertificate *signerCert,
  3683. CERTOCSPCertID *certID,
  3684. int64 thisUpdate)
  3685. {
  3686. CERTCertificate *issuerCert = NULL, *defRespCert;
  3687. SECItem *keyHash = NULL;
  3688. SECItem *nameHash = NULL;
  3689. SECOidTag hashAlg;
  3690. PRBool keyHashEQ = PR_FALSE, nameHashEQ = PR_FALSE;
  3691. /*
  3692. * Check first for a trusted responder, which overrides everything else.
  3693. */
  3694. if ((defRespCert = ocsp_CertGetDefaultResponder(handle, certID)) &&
  3695. CERT_CompareCerts(defRespCert, signerCert)) {
  3696. return PR_TRUE;
  3697. }
  3698. /*
  3699. * In the other two cases, we need to do an issuer comparison.
  3700. * How we do it depends on whether the signer certificate has the
  3701. * special extension (for a designated responder) or not.
  3702. *
  3703. * First, lets check if signer of the response is the actual issuer
  3704. * of the cert. For that we will use signer cert key hash and cert subj
  3705. * name hash and will compare them with already calculated issuer key
  3706. * hash and issuer name hash. The hash algorithm is picked from response
  3707. * certID hash to avoid second hash calculation.
  3708. */
  3709. hashAlg = SECOID_FindOIDTag(&certID->hashAlgorithm.algorithm);
  3710. keyHash = CERT_GetSPKIDigest(NULL, signerCert, hashAlg, NULL);
  3711. if (keyHash != NULL) {
  3712. keyHashEQ =
  3713. (SECITEM_CompareItem(keyHash,
  3714. &certID->issuerKeyHash) == SECEqual);
  3715. SECITEM_FreeItem(keyHash, PR_TRUE);
  3716. }
  3717. if (keyHashEQ &&
  3718. (nameHash = cert_GetSubjectNameDigest(NULL, signerCert,
  3719. hashAlg, NULL))) {
  3720. nameHashEQ =
  3721. (SECITEM_CompareItem(nameHash,
  3722. &certID->issuerNameHash) == SECEqual);
  3723. SECITEM_FreeItem(nameHash, PR_TRUE);
  3724. if (nameHashEQ) {
  3725. /* The issuer of the cert is the the signer of the response */
  3726. return PR_TRUE;
  3727. }
  3728. }
  3729. keyHashEQ = PR_FALSE;
  3730. nameHashEQ = PR_FALSE;
  3731. if (!ocsp_CertIsOCSPDesignatedResponder(signerCert)) {
  3732. PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
  3733. return PR_FALSE;
  3734. }
  3735. /*
  3736. * The signer is a designated responder. Its issuer must match
  3737. * the issuer of the cert being checked.
  3738. */
  3739. issuerCert = CERT_FindCertIssuer(signerCert, thisUpdate,
  3740. certUsageAnyCA);
  3741. if (issuerCert == NULL) {
  3742. /*
  3743. * We could leave the SEC_ERROR_UNKNOWN_ISSUER error alone,
  3744. * but the following will give slightly more information.
  3745. * Once we have an error stack, things will be much better.
  3746. */
  3747. PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
  3748. return PR_FALSE;
  3749. }
  3750. keyHash = CERT_GetSPKIDigest(NULL, issuerCert, hashAlg, NULL);
  3751. nameHash = cert_GetSubjectNameDigest(NULL, issuerCert, hashAlg, NULL);
  3752. CERT_DestroyCertificate(issuerCert);
  3753. if (keyHash != NULL && nameHash != NULL) {
  3754. keyHashEQ =
  3755. (SECITEM_CompareItem(keyHash,
  3756. &certID->issuerKeyHash) == SECEqual);
  3757. nameHashEQ =
  3758. (SECITEM_CompareItem(nameHash,
  3759. &certID->issuerNameHash) == SECEqual);
  3760. }
  3761. if (keyHash) {
  3762. SECITEM_FreeItem(keyHash, PR_TRUE);
  3763. }
  3764. if (nameHash) {
  3765. SECITEM_FreeItem(nameHash, PR_TRUE);
  3766. }
  3767. if (keyHashEQ && nameHashEQ) {
  3768. return PR_TRUE;
  3769. }
  3770. PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
  3771. return PR_FALSE;
  3772. }
  3773. /*
  3774. * We need to check that a responder gives us "recent" information.
  3775. * Since a responder can pre-package responses, we need to pick an amount
  3776. * of time that is acceptable to us, and reject any response that is
  3777. * older than that.
  3778. *
  3779. * XXX This *should* be based on some configuration parameter, so that
  3780. * different usages could specify exactly what constitutes "sufficiently
  3781. * recent". But that is not going to happen right away. For now, we
  3782. * want something from within the last 24 hours. This macro defines that
  3783. * number in seconds.
  3784. */
  3785. #define OCSP_ALLOWABLE_LAPSE_SECONDS (24L * 60L * 60L)
  3786. static PRBool
  3787. ocsp_TimeIsRecent(int64 checkTime)
  3788. {
  3789. int64 now = PR_Now();
  3790. int64 lapse, tmp;
  3791. LL_I2L(lapse, OCSP_ALLOWABLE_LAPSE_SECONDS);
  3792. LL_I2L(tmp, PR_USEC_PER_SEC);
  3793. LL_MUL(lapse, lapse, tmp); /* allowable lapse in microseconds */
  3794. LL_ADD(checkTime, checkTime, lapse);
  3795. if (LL_CMP(now, >, checkTime))
  3796. return PR_FALSE;
  3797. return PR_TRUE;
  3798. }
  3799. #define OCSP_SLOP (5L*60L) /* OCSP responses are allowed to be 5 minutes
  3800. in the future by default */
  3801. static PRUint32 ocspsloptime = OCSP_SLOP; /* seconds */
  3802. /*
  3803. * If an old response contains the revoked certificate status, we want
  3804. * to return SECSuccess so the response will be used.
  3805. */
  3806. static SECStatus
  3807. ocsp_HandleOldSingleResponse(CERTOCSPSingleResponse *single, PRTime time)
  3808. {
  3809. SECStatus rv;
  3810. ocspCertStatus *status = single->certStatus;
  3811. if (status->certStatusType == ocspCertStatus_revoked) {
  3812. rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
  3813. if (rv != SECSuccess &&
  3814. PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE) {
  3815. /*
  3816. * Return SECSuccess now. The subsequent ocsp_CertRevokedAfter
  3817. * call in ocsp_CertHasGoodStatus will cause
  3818. * ocsp_CertHasGoodStatus to fail with
  3819. * SEC_ERROR_REVOKED_CERTIFICATE.
  3820. */
  3821. return SECSuccess;
  3822. }
  3823. }
  3824. PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
  3825. return SECFailure;
  3826. }
  3827. /*
  3828. * Check that this single response is okay. A return of SECSuccess means:
  3829. * 1. The signer (represented by "signerCert") is authorized to give status
  3830. * for the cert represented by the individual response in "single".
  3831. * 2. The value of thisUpdate is earlier than now.
  3832. * 3. The value of producedAt is later than or the same as thisUpdate.
  3833. * 4. If nextUpdate is given:
  3834. * - The value of nextUpdate is later than now.
  3835. * - The value of producedAt is earlier than nextUpdate.
  3836. * Else if no nextUpdate:
  3837. * - The value of thisUpdate is fairly recent.
  3838. * - The value of producedAt is fairly recent.
  3839. * However we do not need to perform an explicit check for this last
  3840. * constraint because it is already guaranteed by checking that
  3841. * producedAt is later than thisUpdate and thisUpdate is recent.
  3842. * Oh, and any responder is "authorized" to say that a cert is unknown to it.
  3843. *
  3844. * If any of those checks fail, SECFailure is returned and an error is set:
  3845. * SEC_ERROR_OCSP_FUTURE_RESPONSE
  3846. * SEC_ERROR_OCSP_OLD_RESPONSE
  3847. * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
  3848. * Other errors are low-level problems (no memory, bad database, etc.).
  3849. */
  3850. static SECStatus
  3851. ocsp_VerifySingleResponse(CERTOCSPSingleResponse *single,
  3852. CERTCertDBHandle *handle,
  3853. CERTCertificate *signerCert,
  3854. int64 producedAt)
  3855. {
  3856. CERTOCSPCertID *certID = single->certID;
  3857. int64 now, thisUpdate, nextUpdate, tmstamp, tmp;
  3858. SECStatus rv;
  3859. OCSP_TRACE(("OCSP ocsp_VerifySingleResponse, nextUpdate: %d\n",
  3860. ((single->nextUpdate) != 0)));
  3861. /*
  3862. * If all the responder said was that the given cert was unknown to it,
  3863. * that is a valid response. Not very interesting to us, of course,
  3864. * but all this function is concerned with is validity of the response,
  3865. * not the status of the cert.
  3866. */
  3867. PORT_Assert(single->certStatus != NULL);
  3868. if (single->certStatus->certStatusType == ocspCertStatus_unknown)
  3869. return SECSuccess;
  3870. /*
  3871. * We need to extract "thisUpdate" for use below and to pass along
  3872. * to AuthorizedResponderForCertID in case it needs it for doing an
  3873. * issuer look-up.
  3874. */
  3875. rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate);
  3876. if (rv != SECSuccess)
  3877. return rv;
  3878. /*
  3879. * First confirm that signerCert is authorized to give this status.
  3880. */
  3881. if (ocsp_AuthorizedResponderForCertID(handle, signerCert, certID,
  3882. thisUpdate) != PR_TRUE)
  3883. return SECFailure;
  3884. /*
  3885. * Now check the time stuff, as described above.
  3886. */
  3887. now = PR_Now();
  3888. /* allow slop time for future response */
  3889. LL_UI2L(tmstamp, ocspsloptime); /* get slop time in seconds */
  3890. LL_UI2L(tmp, PR_USEC_PER_SEC);
  3891. LL_MUL(tmp, tmstamp, tmp); /* convert the slop time to PRTime */
  3892. LL_ADD(tmstamp, tmp, now); /* add current time to it */
  3893. if (LL_CMP(thisUpdate, >, tmstamp) || LL_CMP(producedAt, <, thisUpdate)) {
  3894. PORT_SetError(SEC_ERROR_OCSP_FUTURE_RESPONSE);
  3895. return SECFailure;
  3896. }
  3897. if (single->nextUpdate != NULL) {
  3898. rv = DER_GeneralizedTimeToTime(&nextUpdate, single->nextUpdate);
  3899. if (rv != SECSuccess)
  3900. return rv;
  3901. LL_ADD(tmp, tmp, nextUpdate);
  3902. if (LL_CMP(tmp, <, now) || LL_CMP(producedAt, >, nextUpdate))
  3903. return ocsp_HandleOldSingleResponse(single, now);
  3904. } else if (ocsp_TimeIsRecent(thisUpdate) != PR_TRUE) {
  3905. return ocsp_HandleOldSingleResponse(single, now);
  3906. }
  3907. return SECSuccess;
  3908. }
  3909. /*
  3910. * FUNCTION: CERT_GetOCSPAuthorityInfoAccessLocation
  3911. * Get the value of the URI of the OCSP responder for the given cert.
  3912. * This is found in the (optional) Authority Information Access extension
  3913. * in the cert.
  3914. * INPUTS:
  3915. * CERTCertificate *cert
  3916. * The certificate being examined.
  3917. * RETURN:
  3918. * char *
  3919. * A copy of the URI for the OCSP method, if found. If either the
  3920. * extension is not present or it does not contain an entry for OCSP,
  3921. * SEC_ERROR_CERT_BAD_ACCESS_LOCATION will be set and a NULL returned.
  3922. * Any other error will also result in a NULL being returned.
  3923. *
  3924. * This result should be freed (via PORT_Free) when no longer in use.
  3925. */
  3926. char *
  3927. CERT_GetOCSPAuthorityInfoAccessLocation(CERTCertificate *cert)
  3928. {
  3929. CERTGeneralName *locname = NULL;
  3930. SECItem *location = NULL;
  3931. SECItem *encodedAuthInfoAccess = NULL;
  3932. CERTAuthInfoAccess **authInfoAccess = NULL;
  3933. char *locURI = NULL;
  3934. PRArenaPool *arena = NULL;
  3935. SECStatus rv;
  3936. int i;
  3937. /*
  3938. * Allocate this one from the heap because it will get filled in
  3939. * by CERT_FindCertExtension which will also allocate from the heap,
  3940. * and we can free the entire thing on our way out.
  3941. */
  3942. encodedAuthInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
  3943. if (encodedAuthInfoAccess == NULL)
  3944. goto loser;
  3945. rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
  3946. encodedAuthInfoAccess);
  3947. if (rv == SECFailure) {
  3948. PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
  3949. goto loser;
  3950. }
  3951. /*
  3952. * The rest of the things allocated in the routine will come out of
  3953. * this arena, which is temporary just for us to decode and get at the
  3954. * AIA extension. The whole thing will be destroyed on our way out,
  3955. * after we have copied the location string (url) itself (if found).
  3956. */
  3957. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  3958. if (arena == NULL)
  3959. goto loser;
  3960. authInfoAccess = CERT_DecodeAuthInfoAccessExtension(arena,
  3961. encodedAuthInfoAccess);
  3962. if (authInfoAccess == NULL)
  3963. goto loser;
  3964. for (i = 0; authInfoAccess[i] != NULL; i++) {
  3965. if (SECOID_FindOIDTag(&authInfoAccess[i]->method) == SEC_OID_PKIX_OCSP)
  3966. locname = authInfoAccess[i]->location;
  3967. }
  3968. /*
  3969. * If we found an AIA extension, but it did not include an OCSP method,
  3970. * that should look to our caller as if we did not find the extension
  3971. * at all, because it is only an OCSP method that we care about.
  3972. * So set the same error that would be set if the AIA extension was
  3973. * not there at all.
  3974. */
  3975. if (locname == NULL) {
  3976. PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
  3977. goto loser;
  3978. }
  3979. /*
  3980. * The following is just a pointer back into locname (i.e. not a copy);
  3981. * thus it should not be freed.
  3982. */
  3983. location = CERT_GetGeneralNameByType(locname, certURI, PR_FALSE);
  3984. if (location == NULL) {
  3985. /*
  3986. * XXX Appears that CERT_GetGeneralNameByType does not set an
  3987. * error if there is no name by that type. For lack of anything
  3988. * better, act as if the extension was not found. In the future
  3989. * this should probably be something more like the extension was
  3990. * badly formed.
  3991. */
  3992. PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
  3993. goto loser;
  3994. }
  3995. /*
  3996. * That location is really a string, but it has a specified length
  3997. * without a null-terminator. We need a real string that does have
  3998. * a null-terminator, and we need a copy of it anyway to return to
  3999. * our caller -- so allocate and copy.
  4000. */
  4001. locURI = PORT_Alloc(location->len + 1);
  4002. if (locURI == NULL) {
  4003. goto loser;
  4004. }
  4005. PORT_Memcpy(locURI, location->data, location->len);
  4006. locURI[location->len] = '\0';
  4007. loser:
  4008. if (arena != NULL)
  4009. PORT_FreeArena(arena, PR_FALSE);
  4010. if (encodedAuthInfoAccess != NULL)
  4011. SECITEM_FreeItem(encodedAuthInfoAccess, PR_TRUE);
  4012. return locURI;
  4013. }
  4014. /*
  4015. * Figure out where we should go to find out the status of the given cert
  4016. * via OCSP. If allowed to use a default responder uri and a default
  4017. * responder is set up, then that is our answer.
  4018. * If not, see if the certificate has an Authority Information Access (AIA)
  4019. * extension for OCSP, and return the value of that. Otherwise return NULL.
  4020. * We also let our caller know whether or not the responder chosen was
  4021. * a default responder or not through the output variable isDefault;
  4022. * its value has no meaning unless a good (non-null) value is returned
  4023. * for the location.
  4024. *
  4025. * The result needs to be freed (PORT_Free) when no longer in use.
  4026. */
  4027. char *
  4028. ocsp_GetResponderLocation(CERTCertDBHandle *handle, CERTCertificate *cert,
  4029. PRBool canUseDefault, PRBool *isDefault)
  4030. {
  4031. ocspCheckingContext *ocspcx = NULL;
  4032. char *ocspUrl = NULL;
  4033. if (canUseDefault) {
  4034. ocspcx = ocsp_GetCheckingContext(handle);
  4035. }
  4036. if (ocspcx != NULL && ocspcx->useDefaultResponder) {
  4037. /*
  4038. * A default responder wins out, if specified.
  4039. * XXX Someday this may be a more complicated determination based
  4040. * on the cert's issuer. (That is, we could have different default
  4041. * responders configured for different issuers.)
  4042. */
  4043. PORT_Assert(ocspcx->defaultResponderURI != NULL);
  4044. *isDefault = PR_TRUE;
  4045. return (PORT_Strdup(ocspcx->defaultResponderURI));
  4046. }
  4047. /*
  4048. * No default responder set up, so go see if we can find an AIA
  4049. * extension that has a value for OCSP, and get the url from that.
  4050. */
  4051. *isDefault = PR_FALSE;
  4052. ocspUrl = CERT_GetOCSPAuthorityInfoAccessLocation(cert);
  4053. if (!ocspUrl) {
  4054. CERT_StringFromCertFcn altFcn;
  4055. PR_EnterMonitor(OCSP_Global.monitor);
  4056. altFcn = OCSP_Global.alternateOCSPAIAFcn;
  4057. PR_ExitMonitor(OCSP_Global.monitor);
  4058. if (altFcn) {
  4059. ocspUrl = (*altFcn)(cert);
  4060. if (ocspUrl)
  4061. *isDefault = PR_TRUE;
  4062. }
  4063. }
  4064. return ocspUrl;
  4065. }
  4066. /*
  4067. * Return SECSuccess if the cert was revoked *after* "time",
  4068. * SECFailure otherwise.
  4069. */
  4070. static SECStatus
  4071. ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, int64 time)
  4072. {
  4073. int64 revokedTime;
  4074. SECStatus rv;
  4075. rv = DER_GeneralizedTimeToTime(&revokedTime, &revokedInfo->revocationTime);
  4076. if (rv != SECSuccess)
  4077. return rv;
  4078. /*
  4079. * Set the error even if we will return success; someone might care.
  4080. */
  4081. PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
  4082. if (LL_CMP(revokedTime, >, time))
  4083. return SECSuccess;
  4084. return SECFailure;
  4085. }
  4086. /*
  4087. * See if the cert represented in the single response had a good status
  4088. * at the specified time.
  4089. */
  4090. static SECStatus
  4091. ocsp_CertHasGoodStatus(ocspCertStatus *status, int64 time)
  4092. {
  4093. SECStatus rv;
  4094. switch (status->certStatusType) {
  4095. case ocspCertStatus_good:
  4096. rv = SECSuccess;
  4097. break;
  4098. case ocspCertStatus_revoked:
  4099. rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
  4100. break;
  4101. case ocspCertStatus_unknown:
  4102. PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
  4103. rv = SECFailure;
  4104. break;
  4105. case ocspCertStatus_other:
  4106. default:
  4107. PORT_Assert(0);
  4108. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  4109. rv = SECFailure;
  4110. break;
  4111. }
  4112. return rv;
  4113. }
  4114. static SECStatus
  4115. ocsp_SingleResponseCertHasGoodStatus(CERTOCSPSingleResponse *single,
  4116. int64 time)
  4117. {
  4118. return ocsp_CertHasGoodStatus(single->certStatus, time);
  4119. }
  4120. /* Return value SECFailure means: not found or not fresh.
  4121. * On SECSuccess, the out parameters contain the OCSP status.
  4122. * rvOcsp contains the overall result of the OCSP operation.
  4123. * Depending on input parameter ignoreGlobalOcspFailureSetting,
  4124. * a soft failure might be converted into *rvOcsp=SECSuccess.
  4125. * If the cached attempt to obtain OCSP information had resulted
  4126. * in a failure, missingResponseError shows the error code of
  4127. * that failure.
  4128. */
  4129. SECStatus
  4130. ocsp_GetCachedOCSPResponseStatusIfFresh(CERTOCSPCertID *certID,
  4131. int64 time,
  4132. PRBool ignoreGlobalOcspFailureSetting,
  4133. SECStatus *rvOcsp,
  4134. SECErrorCodes *missingResponseError)
  4135. {
  4136. OCSPCacheItem *cacheItem = NULL;
  4137. SECStatus rv = SECFailure;
  4138. if (!certID || !missingResponseError || !rvOcsp) {
  4139. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  4140. return SECFailure;
  4141. }
  4142. *rvOcsp = SECFailure;
  4143. *missingResponseError = 0;
  4144. PR_EnterMonitor(OCSP_Global.monitor);
  4145. cacheItem = ocsp_FindCacheEntry(&OCSP_Global.cache, certID);
  4146. if (cacheItem && ocsp_IsCacheItemFresh(cacheItem)) {
  4147. /* having an arena means, we have a cached certStatus */
  4148. if (cacheItem->certStatusArena) {
  4149. *rvOcsp = ocsp_CertHasGoodStatus(&cacheItem->certStatus, time);
  4150. if (*rvOcsp != SECSuccess) {
  4151. *missingResponseError = PORT_GetError();
  4152. }
  4153. rv = SECSuccess;
  4154. } else {
  4155. /*
  4156. * No status cached, the previous attempt failed.
  4157. * If OCSP is required, we never decide based on a failed attempt
  4158. * However, if OCSP is optional, a recent OCSP failure is
  4159. * an allowed good state.
  4160. */
  4161. if (!ignoreGlobalOcspFailureSetting &&
  4162. OCSP_Global.ocspFailureMode ==
  4163. ocspMode_FailureIsNotAVerificationFailure) {
  4164. rv = SECSuccess;
  4165. *rvOcsp = SECSuccess;
  4166. }
  4167. *missingResponseError = cacheItem->missingResponseError;
  4168. }
  4169. }
  4170. PR_ExitMonitor(OCSP_Global.monitor);
  4171. return rv;
  4172. }
  4173. PRBool
  4174. ocsp_FetchingFailureIsVerificationFailure()
  4175. {
  4176. PRBool isFailure;
  4177. PR_EnterMonitor(OCSP_Global.monitor);
  4178. isFailure =
  4179. OCSP_Global.ocspFailureMode == ocspMode_FailureIsVerificationFailure;
  4180. PR_ExitMonitor(OCSP_Global.monitor);
  4181. return isFailure;
  4182. }
  4183. /*
  4184. * FUNCTION: CERT_CheckOCSPStatus
  4185. * Checks the status of a certificate via OCSP. Will only check status for
  4186. * a certificate that has an AIA (Authority Information Access) extension
  4187. * for OCSP *or* when a "default responder" is specified and enabled.
  4188. * (If no AIA extension for OCSP and no default responder in place, the
  4189. * cert is considered to have a good status and SECSuccess is returned.)
  4190. * INPUTS:
  4191. * CERTCertDBHandle *handle
  4192. * certificate DB of the cert that is being checked
  4193. * CERTCertificate *cert
  4194. * the certificate being checked
  4195. * XXX in the long term also need a boolean parameter that specifies
  4196. * whether to check the cert chain, as well; for now we check only
  4197. * the leaf (the specified certificate)
  4198. * int64 time
  4199. * time for which status is to be determined
  4200. * void *pwArg
  4201. * argument for password prompting, if needed
  4202. * RETURN:
  4203. * Returns SECSuccess if an approved OCSP responder "knows" the cert
  4204. * *and* returns a non-revoked status for it; SECFailure otherwise,
  4205. * with an error set describing the reason:
  4206. *
  4207. * SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
  4208. * SEC_ERROR_OCSP_FUTURE_RESPONSE
  4209. * SEC_ERROR_OCSP_MALFORMED_REQUEST
  4210. * SEC_ERROR_OCSP_MALFORMED_RESPONSE
  4211. * SEC_ERROR_OCSP_OLD_RESPONSE
  4212. * SEC_ERROR_OCSP_REQUEST_NEEDS_SIG
  4213. * SEC_ERROR_OCSP_SERVER_ERROR
  4214. * SEC_ERROR_OCSP_TRY_SERVER_LATER
  4215. * SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST
  4216. * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
  4217. * SEC_ERROR_OCSP_UNKNOWN_CERT
  4218. * SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS
  4219. * SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE
  4220. *
  4221. * SEC_ERROR_BAD_SIGNATURE
  4222. * SEC_ERROR_CERT_BAD_ACCESS_LOCATION
  4223. * SEC_ERROR_INVALID_TIME
  4224. * SEC_ERROR_REVOKED_CERTIFICATE
  4225. * SEC_ERROR_UNKNOWN_ISSUER
  4226. * SEC_ERROR_UNKNOWN_SIGNER
  4227. *
  4228. * Other errors are any of the many possible failures in cert verification
  4229. * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
  4230. * verifying the signer's cert, or low-level problems (error allocating
  4231. * memory, error performing ASN.1 decoding, etc.).
  4232. */
  4233. SECStatus
  4234. CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
  4235. int64 time, void *pwArg)
  4236. {
  4237. CERTOCSPCertID *certID;
  4238. PRBool certIDWasConsumed = PR_FALSE;
  4239. SECStatus rv = SECFailure;
  4240. SECStatus rvOcsp;
  4241. SECErrorCodes dummy_error_code; /* we ignore this */
  4242. OCSP_TRACE_CERT(cert);
  4243. OCSP_TRACE_TIME("## requested validity time:", time);
  4244. certID = CERT_CreateOCSPCertID(cert, time);
  4245. if (!certID)
  4246. return SECFailure;
  4247. rv = ocsp_GetCachedOCSPResponseStatusIfFresh(
  4248. certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */
  4249. &rvOcsp, &dummy_error_code);
  4250. if (rv == SECSuccess) {
  4251. CERT_DestroyOCSPCertID(certID);
  4252. return rvOcsp;
  4253. }
  4254. rv = ocsp_GetOCSPStatusFromNetwork(handle, certID, cert, time, pwArg,
  4255. &certIDWasConsumed,
  4256. &rvOcsp);
  4257. if (rv != SECSuccess) {
  4258. /* we were unable to obtain ocsp status. Check if we should
  4259. * return cert status revoked. */
  4260. rvOcsp = ocsp_FetchingFailureIsVerificationFailure() ?
  4261. SECFailure : SECSuccess;
  4262. }
  4263. if (!certIDWasConsumed) {
  4264. CERT_DestroyOCSPCertID(certID);
  4265. }
  4266. return rvOcsp;
  4267. }
  4268. /*
  4269. * FUNCTION: CERT_CacheOCSPResponseFromSideChannel
  4270. * First, this function checks the OCSP cache to see if a good response
  4271. * for the given certificate already exists. If it does, then the function
  4272. * returns successfully.
  4273. *
  4274. * If not, then it validates that the given OCSP response is a valid,
  4275. * good response for the given certificate and inserts it into the
  4276. * cache.
  4277. *
  4278. * This function is intended for use when OCSP responses are provided via a
  4279. * side-channel, i.e. TLS OCSP stapling (a.k.a. the status_request extension).
  4280. *
  4281. * INPUTS:
  4282. * CERTCertDBHandle *handle
  4283. * certificate DB of the cert that is being checked
  4284. * CERTCertificate *cert
  4285. * the certificate being checked
  4286. * int64 time
  4287. * time for which status is to be determined
  4288. * SECItem *encodedResponse
  4289. * the DER encoded bytes of the OCSP response
  4290. * void *pwArg
  4291. * argument for password prompting, if needed
  4292. * RETURN:
  4293. * SECSuccess if the cert was found in the cache, or if the OCSP response was
  4294. * found to be valid and inserted into the cache. SECFailure otherwise.
  4295. */
  4296. SECStatus
  4297. CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle,
  4298. CERTCertificate *cert,
  4299. int64 time,
  4300. SECItem *encodedResponse,
  4301. void *pwArg)
  4302. {
  4303. CERTOCSPCertID *certID;
  4304. PRBool certIDWasConsumed = PR_FALSE;
  4305. SECStatus rv = SECFailure;
  4306. SECStatus rvOcsp;
  4307. SECErrorCodes dummy_error_code; /* we ignore this */
  4308. certID = CERT_CreateOCSPCertID(cert, time);
  4309. if (!certID)
  4310. return SECFailure;
  4311. rv = ocsp_GetCachedOCSPResponseStatusIfFresh(
  4312. certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */
  4313. &rvOcsp, &dummy_error_code);
  4314. if (rv == SECSuccess && rvOcsp == SECSuccess) {
  4315. /* The cached value is good. We don't want to waste time validating
  4316. * this OCSP response. */
  4317. CERT_DestroyOCSPCertID(certID);
  4318. return rv;
  4319. }
  4320. /* Since the OCSP response came from a side channel it is attacker
  4321. * controlled. The attacker can have chosen any valid OCSP response,
  4322. * including responses from the past. In this case,
  4323. * ocsp_GetVerifiedSingleResponseForCertID will fail. If we recorded a
  4324. * negative cache entry in this case, then the attacker would have
  4325. * 'poisoned' our cache (denial of service), so we don't record negative
  4326. * results. */
  4327. rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, pwArg,
  4328. encodedResponse, &certIDWasConsumed,
  4329. PR_FALSE /* don't cache failures */,
  4330. &rvOcsp);
  4331. if (!certIDWasConsumed) {
  4332. CERT_DestroyOCSPCertID(certID);
  4333. }
  4334. return rv == SECSuccess ? rvOcsp : rv;
  4335. }
  4336. /*
  4337. * Status in *certIDWasConsumed will always be correct, regardless of
  4338. * return value.
  4339. */
  4340. static SECStatus
  4341. ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle,
  4342. CERTOCSPCertID *certID,
  4343. CERTCertificate *cert,
  4344. int64 time,
  4345. void *pwArg,
  4346. PRBool *certIDWasConsumed,
  4347. SECStatus *rv_ocsp)
  4348. {
  4349. char *location = NULL;
  4350. PRBool locationIsDefault;
  4351. SECItem *encodedResponse = NULL;
  4352. CERTOCSPRequest *request = NULL;
  4353. SECStatus rv = SECFailure;
  4354. if (!certIDWasConsumed || !rv_ocsp) {
  4355. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  4356. return SECFailure;
  4357. }
  4358. *certIDWasConsumed = PR_FALSE;
  4359. *rv_ocsp = SECFailure;
  4360. /*
  4361. * The first thing we need to do is find the location of the responder.
  4362. * This will be the value of the default responder (if enabled), else
  4363. * it will come out of the AIA extension in the cert (if present).
  4364. * If we have no such location, then this cert does not "deserve" to
  4365. * be checked -- that is, we consider it a success and just return.
  4366. * The way we tell that is by looking at the error number to see if
  4367. * the problem was no AIA extension was found; any other error was
  4368. * a true failure that we unfortunately have to treat as an overall
  4369. * failure here.
  4370. */
  4371. location = ocsp_GetResponderLocation(handle, cert, PR_TRUE,
  4372. &locationIsDefault);
  4373. if (location == NULL) {
  4374. int err = PORT_GetError();
  4375. if (err == SEC_ERROR_EXTENSION_NOT_FOUND ||
  4376. err == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) {
  4377. PORT_SetError(0);
  4378. *rv_ocsp = SECSuccess;
  4379. return SECSuccess;
  4380. }
  4381. return SECFailure;
  4382. }
  4383. /*
  4384. * XXX In the fullness of time, we will want/need to handle a
  4385. * certificate chain. This will be done either when a new parameter
  4386. * tells us to, or some configuration variable tells us to. In any
  4387. * case, handling it is complicated because we may need to send as
  4388. * many requests (and receive as many responses) as we have certs
  4389. * in the chain. If we are going to talk to a default responder,
  4390. * and we only support one default responder, we can put all of the
  4391. * certs together into one request. Otherwise, we must break them up
  4392. * into multiple requests. (Even if all of the requests will go to
  4393. * the same location, the signature on each response will be different,
  4394. * because each issuer is different. Carefully read the OCSP spec
  4395. * if you do not understand this.)
  4396. */
  4397. /*
  4398. * XXX If/when signing of requests is supported, that second NULL
  4399. * should be changed to be the signer certificate. Not sure if that
  4400. * should be passed into this function or retrieved via some operation
  4401. * on the handle/context.
  4402. */
  4403. encodedResponse =
  4404. ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert, location,
  4405. time, locationIsDefault,
  4406. pwArg, &request);
  4407. if (encodedResponse == NULL) {
  4408. goto loser;
  4409. }
  4410. rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, pwArg,
  4411. encodedResponse, certIDWasConsumed,
  4412. PR_TRUE /* cache failures */, rv_ocsp);
  4413. loser:
  4414. if (request != NULL)
  4415. CERT_DestroyOCSPRequest(request);
  4416. if (encodedResponse != NULL)
  4417. SECITEM_FreeItem(encodedResponse, PR_TRUE);
  4418. if (location != NULL)
  4419. PORT_Free(location);
  4420. return rv;
  4421. }
  4422. /*
  4423. * FUNCTION: ocsp_CacheEncodedOCSPResponse
  4424. * This function decodes an OCSP response and checks for a valid response
  4425. * concerning the given certificate. If such a response is not found
  4426. * then nothing is cached. Otherwise, if it is a good response, or if
  4427. * cacheNegative is true, the results are stored in the OCSP cache.
  4428. *
  4429. * Note: a 'valid' response is one that parses successfully, is not an OCSP
  4430. * exception (see RFC 2560 Section 2.3), is correctly signed and is current.
  4431. * A 'good' response is a valid response that attests that the certificate
  4432. * is not currently revoked (see RFC 2560 Section 2.2).
  4433. *
  4434. * INPUTS:
  4435. * CERTCertDBHandle *handle
  4436. * certificate DB of the cert that is being checked
  4437. * CERTOCSPCertID *certID
  4438. * the cert ID corresponding to |cert|
  4439. * CERTCertificate *cert
  4440. * the certificate being checked
  4441. * int64 time
  4442. * time for which status is to be determined
  4443. * void *pwArg
  4444. * the opaque argument to the password prompting function.
  4445. * SECItem *encodedResponse
  4446. * the DER encoded bytes of the OCSP response
  4447. * PRBool *certIDWasConsumed
  4448. * (output) on return, this is true iff |certID| was consumed by this
  4449. * function.
  4450. * SECStatus *rv_ocsp
  4451. * (output) on return, this is SECSuccess iff the response is good (see
  4452. * definition of 'good' above).
  4453. * RETURN:
  4454. * SECSuccess iff the response is valid.
  4455. */
  4456. static SECStatus
  4457. ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle,
  4458. CERTOCSPCertID *certID,
  4459. CERTCertificate *cert,
  4460. int64 time,
  4461. void *pwArg,
  4462. SECItem *encodedResponse,
  4463. PRBool *certIDWasConsumed,
  4464. PRBool cacheNegative,
  4465. SECStatus *rv_ocsp)
  4466. {
  4467. CERTOCSPResponse *response = NULL;
  4468. CERTCertificate *signerCert = NULL;
  4469. CERTCertificate *issuerCert = NULL;
  4470. CERTOCSPSingleResponse *single = NULL;
  4471. SECStatus rv = SECFailure;
  4472. *certIDWasConsumed = PR_FALSE;
  4473. *rv_ocsp = SECFailure;
  4474. response = CERT_DecodeOCSPResponse(encodedResponse);
  4475. if (response == NULL) {
  4476. goto loser;
  4477. }
  4478. /*
  4479. * Okay, we at least have a response that *looks* like a response!
  4480. * Now see if the overall response status value is good or not.
  4481. * If not, we set an error and give up. (It means that either the
  4482. * server had a problem, or it didn't like something about our
  4483. * request. Either way there is nothing to do but give up.)
  4484. * Otherwise, we continue to find the actual per-cert status
  4485. * in the response.
  4486. */
  4487. if (CERT_GetOCSPResponseStatus(response) != SECSuccess) {
  4488. goto loser;
  4489. }
  4490. /*
  4491. * If we've made it this far, we expect a response with a good signature.
  4492. * So, check for that.
  4493. */
  4494. issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
  4495. rv = CERT_VerifyOCSPResponseSignature(response, handle, pwArg, &signerCert,
  4496. issuerCert);
  4497. if (rv != SECSuccess)
  4498. goto loser;
  4499. PORT_Assert(signerCert != NULL); /* internal consistency check */
  4500. /* XXX probably should set error, return failure if signerCert is null */
  4501. /*
  4502. * Again, we are only doing one request for one cert.
  4503. * XXX When we handle cert chains, the following code will obviously
  4504. * have to be modified, in coordation with the code above that will
  4505. * have to determine how to make multiple requests, etc.
  4506. */
  4507. rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID,
  4508. signerCert, time, &single);
  4509. if (rv != SECSuccess)
  4510. goto loser;
  4511. *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(single, time);
  4512. loser:
  4513. if (cacheNegative || *rv_ocsp == SECSuccess) {
  4514. PR_EnterMonitor(OCSP_Global.monitor);
  4515. if (OCSP_Global.maxCacheEntries >= 0) {
  4516. /* single == NULL means: remember response failure */
  4517. ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single,
  4518. certIDWasConsumed);
  4519. /* ignore cache update failures */
  4520. }
  4521. PR_ExitMonitor(OCSP_Global.monitor);
  4522. }
  4523. /* 'single' points within the response so there's no need to free it. */
  4524. if (issuerCert != NULL)
  4525. CERT_DestroyCertificate(issuerCert);
  4526. if (signerCert != NULL)
  4527. CERT_DestroyCertificate(signerCert);
  4528. if (response != NULL)
  4529. CERT_DestroyOCSPResponse(response);
  4530. return rv;
  4531. }
  4532. static SECStatus
  4533. ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle,
  4534. CERTOCSPResponse *response,
  4535. CERTOCSPCertID *certID,
  4536. CERTCertificate *signerCert,
  4537. int64 time,
  4538. CERTOCSPSingleResponse
  4539. **pSingleResponse)
  4540. {
  4541. SECStatus rv;
  4542. ocspResponseData *responseData;
  4543. int64 producedAt;
  4544. CERTOCSPSingleResponse *single;
  4545. /*
  4546. * The ResponseData part is the real guts of the response.
  4547. */
  4548. responseData = ocsp_GetResponseData(response, NULL);
  4549. if (responseData == NULL) {
  4550. rv = SECFailure;
  4551. goto loser;
  4552. }
  4553. /*
  4554. * There is one producedAt time for the entire response (and a separate
  4555. * thisUpdate time for each individual single response). We need to
  4556. * compare them, so get the overall time to pass into the check of each
  4557. * single response.
  4558. */
  4559. rv = DER_GeneralizedTimeToTime(&producedAt, &responseData->producedAt);
  4560. if (rv != SECSuccess)
  4561. goto loser;
  4562. single = ocsp_GetSingleResponseForCertID(responseData->responses,
  4563. handle, certID);
  4564. if (single == NULL) {
  4565. rv = SECFailure;
  4566. goto loser;
  4567. }
  4568. rv = ocsp_VerifySingleResponse(single, handle, signerCert, producedAt);
  4569. if (rv != SECSuccess)
  4570. goto loser;
  4571. *pSingleResponse = single;
  4572. loser:
  4573. return rv;
  4574. }
  4575. SECStatus
  4576. CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle,
  4577. CERTOCSPResponse *response,
  4578. CERTOCSPCertID *certID,
  4579. CERTCertificate *signerCert,
  4580. int64 time)
  4581. {
  4582. /*
  4583. * We do not update the cache, because:
  4584. *
  4585. * CERT_GetOCSPStatusForCertID is an old exported API that was introduced
  4586. * before the OCSP cache got implemented.
  4587. *
  4588. * The implementation of helper function cert_ProcessOCSPResponse
  4589. * requires the ability to transfer ownership of the the given certID to
  4590. * the cache. The external API doesn't allow us to prevent the caller from
  4591. * destroying the certID. We don't have the original certificate available,
  4592. * therefore we are unable to produce another certID object (that could
  4593. * be stored in the cache).
  4594. *
  4595. * Should we ever implement code to produce a deep copy of certID,
  4596. * then this could be changed to allow updating the cache.
  4597. * The duplication would have to be done in
  4598. * cert_ProcessOCSPResponse, if the out parameter to indicate
  4599. * a transfer of ownership is NULL.
  4600. */
  4601. return cert_ProcessOCSPResponse(handle, response, certID,
  4602. signerCert, time,
  4603. NULL, NULL);
  4604. }
  4605. /*
  4606. * The first 5 parameters match the definition of CERT_GetOCSPStatusForCertID.
  4607. */
  4608. SECStatus
  4609. cert_ProcessOCSPResponse(CERTCertDBHandle *handle,
  4610. CERTOCSPResponse *response,
  4611. CERTOCSPCertID *certID,
  4612. CERTCertificate *signerCert,
  4613. int64 time,
  4614. PRBool *certIDWasConsumed,
  4615. SECStatus *cacheUpdateStatus)
  4616. {
  4617. SECStatus rv;
  4618. SECStatus rv_cache = SECSuccess;
  4619. CERTOCSPSingleResponse *single = NULL;
  4620. rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID,
  4621. signerCert, time, &single);
  4622. if (rv == SECSuccess) {
  4623. /*
  4624. * Check whether the status says revoked, and if so
  4625. * how that compares to the time value passed into this routine.
  4626. */
  4627. rv = ocsp_SingleResponseCertHasGoodStatus(single, time);
  4628. }
  4629. if (certIDWasConsumed) {
  4630. /*
  4631. * We don't have copy-of-certid implemented. In order to update
  4632. * the cache, the caller must supply an out variable
  4633. * certIDWasConsumed, allowing us to return ownership status.
  4634. */
  4635. PR_EnterMonitor(OCSP_Global.monitor);
  4636. if (OCSP_Global.maxCacheEntries >= 0) {
  4637. /* single == NULL means: remember response failure */
  4638. rv_cache =
  4639. ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID,
  4640. single, certIDWasConsumed);
  4641. }
  4642. PR_ExitMonitor(OCSP_Global.monitor);
  4643. if (cacheUpdateStatus) {
  4644. *cacheUpdateStatus = rv_cache;
  4645. }
  4646. }
  4647. return rv;
  4648. }
  4649. SECStatus
  4650. cert_RememberOCSPProcessingFailure(CERTOCSPCertID *certID,
  4651. PRBool *certIDWasConsumed)
  4652. {
  4653. SECStatus rv = SECSuccess;
  4654. PR_EnterMonitor(OCSP_Global.monitor);
  4655. if (OCSP_Global.maxCacheEntries >= 0) {
  4656. rv = ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, NULL,
  4657. certIDWasConsumed);
  4658. }
  4659. PR_ExitMonitor(OCSP_Global.monitor);
  4660. return rv;
  4661. }
  4662. /*
  4663. * Disable status checking and destroy related structures/data.
  4664. */
  4665. static SECStatus
  4666. ocsp_DestroyStatusChecking(CERTStatusConfig *statusConfig)
  4667. {
  4668. ocspCheckingContext *statusContext;
  4669. /*
  4670. * Disable OCSP checking
  4671. */
  4672. statusConfig->statusChecker = NULL;
  4673. statusContext = statusConfig->statusContext;
  4674. PORT_Assert(statusContext != NULL);
  4675. if (statusContext == NULL)
  4676. return SECFailure;
  4677. if (statusContext->defaultResponderURI != NULL)
  4678. PORT_Free(statusContext->defaultResponderURI);
  4679. if (statusContext->defaultResponderNickname != NULL)
  4680. PORT_Free(statusContext->defaultResponderNickname);
  4681. PORT_Free(statusContext);
  4682. statusConfig->statusContext = NULL;
  4683. PORT_Free(statusConfig);
  4684. return SECSuccess;
  4685. }
  4686. /*
  4687. * FUNCTION: CERT_DisableOCSPChecking
  4688. * Turns off OCSP checking for the given certificate database.
  4689. * This routine disables OCSP checking. Though it will return
  4690. * SECFailure if OCSP checking is not enabled, it is "safe" to
  4691. * call it that way and just ignore the return value, if it is
  4692. * easier to just call it than to "remember" whether it is enabled.
  4693. * INPUTS:
  4694. * CERTCertDBHandle *handle
  4695. * Certificate database for which OCSP checking will be disabled.
  4696. * RETURN:
  4697. * Returns SECFailure if an error occurred (usually means that OCSP
  4698. * checking was not enabled or status contexts were not initialized --
  4699. * error set will be SEC_ERROR_OCSP_NOT_ENABLED); SECSuccess otherwise.
  4700. */
  4701. SECStatus
  4702. CERT_DisableOCSPChecking(CERTCertDBHandle *handle)
  4703. {
  4704. CERTStatusConfig *statusConfig;
  4705. ocspCheckingContext *statusContext;
  4706. if (handle == NULL) {
  4707. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  4708. return SECFailure;
  4709. }
  4710. statusConfig = CERT_GetStatusConfig(handle);
  4711. statusContext = ocsp_GetCheckingContext(handle);
  4712. if (statusContext == NULL)
  4713. return SECFailure;
  4714. if (statusConfig->statusChecker != CERT_CheckOCSPStatus) {
  4715. /*
  4716. * Status configuration is present, but either not currently
  4717. * enabled or not for OCSP.
  4718. */
  4719. PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED);
  4720. return SECFailure;
  4721. }
  4722. /* cache no longer necessary */
  4723. CERT_ClearOCSPCache();
  4724. /*
  4725. * This is how we disable status checking. Everything else remains
  4726. * in place in case we are enabled again.
  4727. */
  4728. statusConfig->statusChecker = NULL;
  4729. return SECSuccess;
  4730. }
  4731. /*
  4732. * Allocate and initialize the informational structures for status checking.
  4733. * This is done when some configuration of OCSP is being done or when OCSP
  4734. * checking is being turned on, whichever comes first.
  4735. */
  4736. static SECStatus
  4737. ocsp_InitStatusChecking(CERTCertDBHandle *handle)
  4738. {
  4739. CERTStatusConfig *statusConfig = NULL;
  4740. ocspCheckingContext *statusContext = NULL;
  4741. PORT_Assert(CERT_GetStatusConfig(handle) == NULL);
  4742. if (CERT_GetStatusConfig(handle) != NULL) {
  4743. /* XXX or call statusConfig->statusDestroy and continue? */
  4744. return SECFailure;
  4745. }
  4746. statusConfig = PORT_ZNew(CERTStatusConfig);
  4747. if (statusConfig == NULL)
  4748. goto loser;
  4749. statusContext = PORT_ZNew(ocspCheckingContext);
  4750. if (statusContext == NULL)
  4751. goto loser;
  4752. statusConfig->statusDestroy = ocsp_DestroyStatusChecking;
  4753. statusConfig->statusContext = statusContext;
  4754. CERT_SetStatusConfig(handle, statusConfig);
  4755. return SECSuccess;
  4756. loser:
  4757. if (statusConfig != NULL)
  4758. PORT_Free(statusConfig);
  4759. return SECFailure;
  4760. }
  4761. /*
  4762. * FUNCTION: CERT_EnableOCSPChecking
  4763. * Turns on OCSP checking for the given certificate database.
  4764. * INPUTS:
  4765. * CERTCertDBHandle *handle
  4766. * Certificate database for which OCSP checking will be enabled.
  4767. * RETURN:
  4768. * Returns SECFailure if an error occurred (likely only problem
  4769. * allocating memory); SECSuccess otherwise.
  4770. */
  4771. SECStatus
  4772. CERT_EnableOCSPChecking(CERTCertDBHandle *handle)
  4773. {
  4774. CERTStatusConfig *statusConfig;
  4775. SECStatus rv;
  4776. if (handle == NULL) {
  4777. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  4778. return SECFailure;
  4779. }
  4780. statusConfig = CERT_GetStatusConfig(handle);
  4781. if (statusConfig == NULL) {
  4782. rv = ocsp_InitStatusChecking(handle);
  4783. if (rv != SECSuccess)
  4784. return rv;
  4785. /* Get newly established value */
  4786. statusConfig = CERT_GetStatusConfig(handle);
  4787. PORT_Assert(statusConfig != NULL);
  4788. }
  4789. /*
  4790. * Setting the checker function is what really enables the checking
  4791. * when each cert verification is done.
  4792. */
  4793. statusConfig->statusChecker = CERT_CheckOCSPStatus;
  4794. return SECSuccess;
  4795. }
  4796. /*
  4797. * FUNCTION: CERT_SetOCSPDefaultResponder
  4798. * Specify the location and cert of the default responder.
  4799. * If OCSP checking is already enabled *and* use of a default responder
  4800. * is also already enabled, all OCSP checking from now on will go directly
  4801. * to the specified responder. If OCSP checking is not enabled, or if
  4802. * it is but use of a default responder is not enabled, the information
  4803. * will be recorded and take effect whenever both are enabled.
  4804. * INPUTS:
  4805. * CERTCertDBHandle *handle
  4806. * Cert database on which OCSP checking should use the default responder.
  4807. * char *url
  4808. * The location of the default responder (e.g. "http://foo.com:80/ocsp")
  4809. * Note that the location will not be tested until the first attempt
  4810. * to send a request there.
  4811. * char *name
  4812. * The nickname of the cert to trust (expected) to sign the OCSP responses.
  4813. * If the corresponding cert cannot be found, SECFailure is returned.
  4814. * RETURN:
  4815. * Returns SECFailure if an error occurred; SECSuccess otherwise.
  4816. * The most likely error is that the cert for "name" could not be found
  4817. * (probably SEC_ERROR_UNKNOWN_CERT). Other errors are low-level (no memory,
  4818. * bad database, etc.).
  4819. */
  4820. SECStatus
  4821. CERT_SetOCSPDefaultResponder(CERTCertDBHandle *handle,
  4822. const char *url, const char *name)
  4823. {
  4824. CERTCertificate *cert;
  4825. ocspCheckingContext *statusContext;
  4826. char *url_copy = NULL;
  4827. char *name_copy = NULL;
  4828. SECStatus rv;
  4829. if (handle == NULL || url == NULL || name == NULL) {
  4830. /*
  4831. * XXX When interface is exported, probably want better errors;
  4832. * perhaps different one for each parameter.
  4833. */
  4834. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  4835. return SECFailure;
  4836. }
  4837. /*
  4838. * Find the certificate for the specified nickname. Do this first
  4839. * because it seems the most likely to fail.
  4840. *
  4841. * XXX Shouldn't need that cast if the FindCertByNickname interface
  4842. * used const to convey that it does not modify the name. Maybe someday.
  4843. */
  4844. cert = CERT_FindCertByNickname(handle, (char *) name);
  4845. if (cert == NULL) {
  4846. /*
  4847. * look for the cert on an external token.
  4848. */
  4849. cert = PK11_FindCertFromNickname((char *)name, NULL);
  4850. }
  4851. if (cert == NULL)
  4852. return SECFailure;
  4853. /*
  4854. * Make a copy of the url and nickname.
  4855. */
  4856. url_copy = PORT_Strdup(url);
  4857. name_copy = PORT_Strdup(name);
  4858. if (url_copy == NULL || name_copy == NULL) {
  4859. rv = SECFailure;
  4860. goto loser;
  4861. }
  4862. statusContext = ocsp_GetCheckingContext(handle);
  4863. /*
  4864. * Allocate and init the context if it doesn't already exist.
  4865. */
  4866. if (statusContext == NULL) {
  4867. rv = ocsp_InitStatusChecking(handle);
  4868. if (rv != SECSuccess)
  4869. goto loser;
  4870. statusContext = ocsp_GetCheckingContext(handle);
  4871. PORT_Assert(statusContext != NULL); /* extreme paranoia */
  4872. }
  4873. /*
  4874. * Note -- we do not touch the status context until after all of
  4875. * the steps which could cause errors. If something goes wrong,
  4876. * we want to leave things as they were.
  4877. */
  4878. /*
  4879. * Get rid of old url and name if there.
  4880. */
  4881. if (statusContext->defaultResponderNickname != NULL)
  4882. PORT_Free(statusContext->defaultResponderNickname);
  4883. if (statusContext->defaultResponderURI != NULL)
  4884. PORT_Free(statusContext->defaultResponderURI);
  4885. /*
  4886. * And replace them with the new ones.
  4887. */
  4888. statusContext->defaultResponderURI = url_copy;
  4889. statusContext->defaultResponderNickname = name_copy;
  4890. /*
  4891. * If there was already a cert in place, get rid of it and replace it.
  4892. * Otherwise, we are not currently enabled, so we don't want to save it;
  4893. * it will get re-found and set whenever use of a default responder is
  4894. * enabled.
  4895. */
  4896. if (statusContext->defaultResponderCert != NULL) {
  4897. CERT_DestroyCertificate(statusContext->defaultResponderCert);
  4898. statusContext->defaultResponderCert = cert;
  4899. /*OCSP enabled, switching responder: clear cache*/
  4900. CERT_ClearOCSPCache();
  4901. } else {
  4902. PORT_Assert(statusContext->useDefaultResponder == PR_FALSE);
  4903. CERT_DestroyCertificate(cert);
  4904. /*OCSP currently not enabled, no need to clear cache*/
  4905. }
  4906. return SECSuccess;
  4907. loser:
  4908. CERT_DestroyCertificate(cert);
  4909. if (url_copy != NULL)
  4910. PORT_Free(url_copy);
  4911. if (name_copy != NULL)
  4912. PORT_Free(name_copy);
  4913. return rv;
  4914. }
  4915. /*
  4916. * FUNCTION: CERT_EnableOCSPDefaultResponder
  4917. * Turns on use of a default responder when OCSP checking.
  4918. * If OCSP checking is already enabled, this will make subsequent checks
  4919. * go directly to the default responder. (The location of the responder
  4920. * and the nickname of the responder cert must already be specified.)
  4921. * If OCSP checking is not enabled, this will be recorded and take effect
  4922. * whenever it is enabled.
  4923. * INPUTS:
  4924. * CERTCertDBHandle *handle
  4925. * Cert database on which OCSP checking should use the default responder.
  4926. * RETURN:
  4927. * Returns SECFailure if an error occurred; SECSuccess otherwise.
  4928. * No errors are especially likely unless the caller did not previously
  4929. * perform a successful call to SetOCSPDefaultResponder (in which case
  4930. * the error set will be SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER).
  4931. */
  4932. SECStatus
  4933. CERT_EnableOCSPDefaultResponder(CERTCertDBHandle *handle)
  4934. {
  4935. ocspCheckingContext *statusContext;
  4936. CERTCertificate *cert;
  4937. SECStatus rv;
  4938. SECCertificateUsage usage;
  4939. if (handle == NULL) {
  4940. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  4941. return SECFailure;
  4942. }
  4943. statusContext = ocsp_GetCheckingContext(handle);
  4944. if (statusContext == NULL) {
  4945. /*
  4946. * Strictly speaking, the error already set is "correct",
  4947. * but cover over it with one more helpful in this context.
  4948. */
  4949. PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
  4950. return SECFailure;
  4951. }
  4952. if (statusContext->defaultResponderURI == NULL) {
  4953. PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
  4954. return SECFailure;
  4955. }
  4956. if (statusContext->defaultResponderNickname == NULL) {
  4957. PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
  4958. return SECFailure;
  4959. }
  4960. /*
  4961. * Find the cert for the nickname.
  4962. */
  4963. cert = CERT_FindCertByNickname(handle,
  4964. statusContext->defaultResponderNickname);
  4965. if (cert == NULL) {
  4966. cert = PK11_FindCertFromNickname(statusContext->defaultResponderNickname,
  4967. NULL);
  4968. }
  4969. /*
  4970. * We should never have trouble finding the cert, because its
  4971. * existence should have been proven by SetOCSPDefaultResponder.
  4972. */
  4973. PORT_Assert(cert != NULL);
  4974. if (cert == NULL)
  4975. return SECFailure;
  4976. /*
  4977. * Supplied cert should at least have a signing capability in order for us
  4978. * to use it as a trusted responder cert. Ability to sign is guaranteed if
  4979. * cert is validated to have any set of the usages below.
  4980. */
  4981. rv = CERT_VerifyCertificateNow(handle, cert, PR_TRUE,
  4982. certificateUsageCheckAllUsages,
  4983. NULL, &usage);
  4984. if (rv != SECSuccess || (usage & (certificateUsageSSLClient |
  4985. certificateUsageSSLServer |
  4986. certificateUsageSSLServerWithStepUp |
  4987. certificateUsageEmailSigner |
  4988. certificateUsageObjectSigner |
  4989. certificateUsageStatusResponder |
  4990. certificateUsageSSLCA)) == 0) {
  4991. PORT_SetError(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID);
  4992. return SECFailure;
  4993. }
  4994. /*
  4995. * And hang onto it.
  4996. */
  4997. statusContext->defaultResponderCert = cert;
  4998. /* we don't allow a mix of cache entries from different responders */
  4999. CERT_ClearOCSPCache();
  5000. /*
  5001. * Finally, record the fact that we now have a default responder enabled.
  5002. */
  5003. statusContext->useDefaultResponder = PR_TRUE;
  5004. return SECSuccess;
  5005. }
  5006. /*
  5007. * FUNCTION: CERT_DisableOCSPDefaultResponder
  5008. * Turns off use of a default responder when OCSP checking.
  5009. * (Does nothing if use of a default responder is not enabled.)
  5010. * INPUTS:
  5011. * CERTCertDBHandle *handle
  5012. * Cert database on which OCSP checking should stop using a default
  5013. * responder.
  5014. * RETURN:
  5015. * Returns SECFailure if an error occurred; SECSuccess otherwise.
  5016. * Errors very unlikely (like random memory corruption...).
  5017. */
  5018. SECStatus
  5019. CERT_DisableOCSPDefaultResponder(CERTCertDBHandle *handle)
  5020. {
  5021. CERTStatusConfig *statusConfig;
  5022. ocspCheckingContext *statusContext;
  5023. CERTCertificate *tmpCert;
  5024. if (handle == NULL) {
  5025. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  5026. return SECFailure;
  5027. }
  5028. statusConfig = CERT_GetStatusConfig(handle);
  5029. if (statusConfig == NULL)
  5030. return SECSuccess;
  5031. statusContext = ocsp_GetCheckingContext(handle);
  5032. PORT_Assert(statusContext != NULL);
  5033. if (statusContext == NULL)
  5034. return SECFailure;
  5035. tmpCert = statusContext->defaultResponderCert;
  5036. if (tmpCert) {
  5037. statusContext->defaultResponderCert = NULL;
  5038. CERT_DestroyCertificate(tmpCert);
  5039. /* we don't allow a mix of cache entries from different responders */
  5040. CERT_ClearOCSPCache();
  5041. }
  5042. /*
  5043. * Finally, record the fact.
  5044. */
  5045. statusContext->useDefaultResponder = PR_FALSE;
  5046. return SECSuccess;
  5047. }
  5048. SECStatus
  5049. CERT_GetOCSPResponseStatus(CERTOCSPResponse *response)
  5050. {
  5051. PORT_Assert(response);
  5052. if (response->statusValue == ocspResponse_successful)
  5053. return SECSuccess;
  5054. switch (response->statusValue) {
  5055. case ocspResponse_malformedRequest:
  5056. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
  5057. break;
  5058. case ocspResponse_internalError:
  5059. PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
  5060. break;
  5061. case ocspResponse_tryLater:
  5062. PORT_SetError(SEC_ERROR_OCSP_TRY_SERVER_LATER);
  5063. break;
  5064. case ocspResponse_sigRequired:
  5065. /* XXX We *should* retry with a signature, if possible. */
  5066. PORT_SetError(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG);
  5067. break;
  5068. case ocspResponse_unauthorized:
  5069. PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST);
  5070. break;
  5071. case ocspResponse_other:
  5072. case ocspResponse_unused:
  5073. default:
  5074. PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS);
  5075. break;
  5076. }
  5077. return SECFailure;
  5078. }