/security/nss/lib/pki/pkibase.c

http://github.com/zpao/v8monkey · C · 1268 lines · 1062 code · 65 blank · 141 comment · 177 complexity · 8b6004d84e45ed6af1d6bff8079fa48e MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. *
  23. * Alternatively, the contents of this file may be used under the terms of
  24. * either the GNU General Public License Version 2 or later (the "GPL"), or
  25. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26. * in which case the provisions of the GPL or the LGPL are applicable instead
  27. * of those above. If you wish to allow use of your version of this file only
  28. * under the terms of either the GPL or the LGPL, and not to allow others to
  29. * use your version of this file under the terms of the MPL, indicate your
  30. * decision by deleting the provisions above and replace them with the notice
  31. * and other provisions required by the GPL or the LGPL. If you do not delete
  32. * the provisions above, a recipient may use your version of this file under
  33. * the terms of any one of the MPL, the GPL or the LGPL.
  34. *
  35. * ***** END LICENSE BLOCK ***** */
  36. #ifdef DEBUG
  37. static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.33 $ $Date: 2010/04/03 18:27:32 $";
  38. #endif /* DEBUG */
  39. #ifndef DEV_H
  40. #include "dev.h"
  41. #endif /* DEV_H */
  42. #ifndef PKIM_H
  43. #include "pkim.h"
  44. #endif /* PKIM_H */
  45. #include "pki3hack.h"
  46. extern const NSSError NSS_ERROR_NOT_FOUND;
  47. NSS_IMPLEMENT void
  48. nssPKIObject_Lock(nssPKIObject * object)
  49. {
  50. switch (object->lockType) {
  51. case nssPKIMonitor:
  52. PZ_EnterMonitor(object->sync.mlock);
  53. break;
  54. case nssPKILock:
  55. PZ_Lock(object->sync.lock);
  56. break;
  57. default:
  58. PORT_Assert(0);
  59. }
  60. }
  61. NSS_IMPLEMENT void
  62. nssPKIObject_Unlock(nssPKIObject * object)
  63. {
  64. switch (object->lockType) {
  65. case nssPKIMonitor:
  66. PZ_ExitMonitor(object->sync.mlock);
  67. break;
  68. case nssPKILock:
  69. PZ_Unlock(object->sync.lock);
  70. break;
  71. default:
  72. PORT_Assert(0);
  73. }
  74. }
  75. NSS_IMPLEMENT PRStatus
  76. nssPKIObject_NewLock(nssPKIObject * object, nssPKILockType lockType)
  77. {
  78. object->lockType = lockType;
  79. switch (lockType) {
  80. case nssPKIMonitor:
  81. object->sync.mlock = PZ_NewMonitor(nssILockSSL);
  82. return (object->sync.mlock ? PR_SUCCESS : PR_FAILURE);
  83. case nssPKILock:
  84. object->sync.lock = PZ_NewLock(nssILockSSL);
  85. return (object->sync.lock ? PR_SUCCESS : PR_FAILURE);
  86. default:
  87. PORT_Assert(0);
  88. return PR_FAILURE;
  89. }
  90. }
  91. NSS_IMPLEMENT void
  92. nssPKIObject_DestroyLock(nssPKIObject * object)
  93. {
  94. switch (object->lockType) {
  95. case nssPKIMonitor:
  96. PZ_DestroyMonitor(object->sync.mlock);
  97. object->sync.mlock = NULL;
  98. break;
  99. case nssPKILock:
  100. PZ_DestroyLock(object->sync.lock);
  101. object->sync.lock = NULL;
  102. break;
  103. default:
  104. PORT_Assert(0);
  105. }
  106. }
  107. NSS_IMPLEMENT nssPKIObject *
  108. nssPKIObject_Create (
  109. NSSArena *arenaOpt,
  110. nssCryptokiObject *instanceOpt,
  111. NSSTrustDomain *td,
  112. NSSCryptoContext *cc,
  113. nssPKILockType lockType
  114. )
  115. {
  116. NSSArena *arena;
  117. nssArenaMark *mark = NULL;
  118. nssPKIObject *object;
  119. if (arenaOpt) {
  120. arena = arenaOpt;
  121. mark = nssArena_Mark(arena);
  122. } else {
  123. arena = nssArena_Create();
  124. if (!arena) {
  125. return (nssPKIObject *)NULL;
  126. }
  127. }
  128. object = nss_ZNEW(arena, nssPKIObject);
  129. if (!object) {
  130. goto loser;
  131. }
  132. object->arena = arena;
  133. object->trustDomain = td; /* XXX */
  134. object->cryptoContext = cc;
  135. if (PR_SUCCESS != nssPKIObject_NewLock(object, lockType)) {
  136. goto loser;
  137. }
  138. if (instanceOpt) {
  139. if (nssPKIObject_AddInstance(object, instanceOpt) != PR_SUCCESS) {
  140. goto loser;
  141. }
  142. }
  143. PR_ATOMIC_INCREMENT(&object->refCount);
  144. if (mark) {
  145. nssArena_Unmark(arena, mark);
  146. }
  147. return object;
  148. loser:
  149. if (mark) {
  150. nssArena_Release(arena, mark);
  151. } else {
  152. nssArena_Destroy(arena);
  153. }
  154. return (nssPKIObject *)NULL;
  155. }
  156. NSS_IMPLEMENT PRBool
  157. nssPKIObject_Destroy (
  158. nssPKIObject *object
  159. )
  160. {
  161. PRUint32 i;
  162. PR_ASSERT(object->refCount > 0);
  163. if (PR_ATOMIC_DECREMENT(&object->refCount) == 0) {
  164. for (i=0; i<object->numInstances; i++) {
  165. nssCryptokiObject_Destroy(object->instances[i]);
  166. }
  167. nssPKIObject_DestroyLock(object);
  168. nssArena_Destroy(object->arena);
  169. return PR_TRUE;
  170. }
  171. return PR_FALSE;
  172. }
  173. NSS_IMPLEMENT nssPKIObject *
  174. nssPKIObject_AddRef (
  175. nssPKIObject *object
  176. )
  177. {
  178. PR_ATOMIC_INCREMENT(&object->refCount);
  179. return object;
  180. }
  181. NSS_IMPLEMENT PRStatus
  182. nssPKIObject_AddInstance (
  183. nssPKIObject *object,
  184. nssCryptokiObject *instance
  185. )
  186. {
  187. nssCryptokiObject **newInstances = NULL;
  188. nssPKIObject_Lock(object);
  189. if (object->numInstances == 0) {
  190. newInstances = nss_ZNEWARRAY(object->arena,
  191. nssCryptokiObject *,
  192. object->numInstances + 1);
  193. } else {
  194. PRBool found = PR_FALSE;
  195. PRUint32 i;
  196. for (i=0; i<object->numInstances; i++) {
  197. if (nssCryptokiObject_Equal(object->instances[i], instance)) {
  198. found = PR_TRUE;
  199. break;
  200. }
  201. }
  202. if (found) {
  203. /* The new instance is identical to one in the array, except
  204. * perhaps that the label may be different. So replace
  205. * the label in the array instance with the label from the
  206. * new instance, and discard the new instance.
  207. */
  208. nss_ZFreeIf(object->instances[i]->label);
  209. object->instances[i]->label = instance->label;
  210. nssPKIObject_Unlock(object);
  211. instance->label = NULL;
  212. nssCryptokiObject_Destroy(instance);
  213. return PR_SUCCESS;
  214. }
  215. newInstances = nss_ZREALLOCARRAY(object->instances,
  216. nssCryptokiObject *,
  217. object->numInstances + 1);
  218. }
  219. if (newInstances) {
  220. object->instances = newInstances;
  221. newInstances[object->numInstances++] = instance;
  222. }
  223. nssPKIObject_Unlock(object);
  224. return (newInstances ? PR_SUCCESS : PR_FAILURE);
  225. }
  226. NSS_IMPLEMENT PRBool
  227. nssPKIObject_HasInstance (
  228. nssPKIObject *object,
  229. nssCryptokiObject *instance
  230. )
  231. {
  232. PRUint32 i;
  233. PRBool hasIt = PR_FALSE;;
  234. nssPKIObject_Lock(object);
  235. for (i=0; i<object->numInstances; i++) {
  236. if (nssCryptokiObject_Equal(object->instances[i], instance)) {
  237. hasIt = PR_TRUE;
  238. break;
  239. }
  240. }
  241. nssPKIObject_Unlock(object);
  242. return hasIt;
  243. }
  244. NSS_IMPLEMENT PRStatus
  245. nssPKIObject_RemoveInstanceForToken (
  246. nssPKIObject *object,
  247. NSSToken *token
  248. )
  249. {
  250. PRUint32 i;
  251. nssCryptokiObject *instanceToRemove = NULL;
  252. nssPKIObject_Lock(object);
  253. if (object->numInstances == 0) {
  254. nssPKIObject_Unlock(object);
  255. return PR_SUCCESS;
  256. }
  257. for (i=0; i<object->numInstances; i++) {
  258. if (object->instances[i]->token == token) {
  259. instanceToRemove = object->instances[i];
  260. object->instances[i] = object->instances[object->numInstances-1];
  261. object->instances[object->numInstances-1] = NULL;
  262. break;
  263. }
  264. }
  265. if (--object->numInstances > 0) {
  266. nssCryptokiObject **instances = nss_ZREALLOCARRAY(object->instances,
  267. nssCryptokiObject *,
  268. object->numInstances);
  269. if (instances) {
  270. object->instances = instances;
  271. }
  272. } else {
  273. nss_ZFreeIf(object->instances);
  274. }
  275. nssCryptokiObject_Destroy(instanceToRemove);
  276. nssPKIObject_Unlock(object);
  277. return PR_SUCCESS;
  278. }
  279. /* this needs more thought on what will happen when there are multiple
  280. * instances
  281. */
  282. NSS_IMPLEMENT PRStatus
  283. nssPKIObject_DeleteStoredObject (
  284. nssPKIObject *object,
  285. NSSCallback *uhh,
  286. PRBool isFriendly
  287. )
  288. {
  289. PRUint32 i, numNotDestroyed;
  290. PRStatus status = PR_SUCCESS;
  291. numNotDestroyed = 0;
  292. nssPKIObject_Lock(object);
  293. for (i=0; i<object->numInstances; i++) {
  294. nssCryptokiObject *instance = object->instances[i];
  295. status = nssToken_DeleteStoredObject(instance);
  296. object->instances[i] = NULL;
  297. if (status == PR_SUCCESS) {
  298. nssCryptokiObject_Destroy(instance);
  299. } else {
  300. object->instances[numNotDestroyed++] = instance;
  301. }
  302. }
  303. if (numNotDestroyed == 0) {
  304. nss_ZFreeIf(object->instances);
  305. object->numInstances = 0;
  306. } else {
  307. object->numInstances = numNotDestroyed;
  308. }
  309. nssPKIObject_Unlock(object);
  310. return status;
  311. }
  312. NSS_IMPLEMENT NSSToken **
  313. nssPKIObject_GetTokens (
  314. nssPKIObject *object,
  315. PRStatus *statusOpt
  316. )
  317. {
  318. NSSToken **tokens = NULL;
  319. nssPKIObject_Lock(object);
  320. if (object->numInstances > 0) {
  321. tokens = nss_ZNEWARRAY(NULL, NSSToken *, object->numInstances + 1);
  322. if (tokens) {
  323. PRUint32 i;
  324. for (i=0; i<object->numInstances; i++) {
  325. tokens[i] = nssToken_AddRef(object->instances[i]->token);
  326. }
  327. }
  328. }
  329. nssPKIObject_Unlock(object);
  330. if (statusOpt) *statusOpt = PR_SUCCESS; /* until more logic here */
  331. return tokens;
  332. }
  333. NSS_IMPLEMENT NSSUTF8 *
  334. nssPKIObject_GetNicknameForToken (
  335. nssPKIObject *object,
  336. NSSToken *tokenOpt
  337. )
  338. {
  339. PRUint32 i;
  340. NSSUTF8 *nickname = NULL;
  341. nssPKIObject_Lock(object);
  342. for (i=0; i<object->numInstances; i++) {
  343. if ((!tokenOpt && object->instances[i]->label) ||
  344. (object->instances[i]->token == tokenOpt))
  345. {
  346. /* XXX should be copy? safe as long as caller has reference */
  347. nickname = object->instances[i]->label;
  348. break;
  349. }
  350. }
  351. nssPKIObject_Unlock(object);
  352. return nickname;
  353. }
  354. NSS_IMPLEMENT nssCryptokiObject **
  355. nssPKIObject_GetInstances (
  356. nssPKIObject *object
  357. )
  358. {
  359. nssCryptokiObject **instances = NULL;
  360. PRUint32 i;
  361. if (object->numInstances == 0) {
  362. return (nssCryptokiObject **)NULL;
  363. }
  364. nssPKIObject_Lock(object);
  365. instances = nss_ZNEWARRAY(NULL, nssCryptokiObject *,
  366. object->numInstances + 1);
  367. if (instances) {
  368. for (i=0; i<object->numInstances; i++) {
  369. instances[i] = nssCryptokiObject_Clone(object->instances[i]);
  370. }
  371. }
  372. nssPKIObject_Unlock(object);
  373. return instances;
  374. }
  375. NSS_IMPLEMENT void
  376. nssCertificateArray_Destroy (
  377. NSSCertificate **certs
  378. )
  379. {
  380. if (certs) {
  381. NSSCertificate **certp;
  382. for (certp = certs; *certp; certp++) {
  383. if ((*certp)->decoding) {
  384. CERTCertificate *cc = STAN_GetCERTCertificate(*certp);
  385. if (cc) {
  386. CERT_DestroyCertificate(cc);
  387. }
  388. continue;
  389. }
  390. nssCertificate_Destroy(*certp);
  391. }
  392. nss_ZFreeIf(certs);
  393. }
  394. }
  395. NSS_IMPLEMENT void
  396. NSSCertificateArray_Destroy (
  397. NSSCertificate **certs
  398. )
  399. {
  400. nssCertificateArray_Destroy(certs);
  401. }
  402. NSS_IMPLEMENT NSSCertificate **
  403. nssCertificateArray_Join (
  404. NSSCertificate **certs1,
  405. NSSCertificate **certs2
  406. )
  407. {
  408. if (certs1 && certs2) {
  409. NSSCertificate **certs, **cp;
  410. PRUint32 count = 0;
  411. PRUint32 count1 = 0;
  412. cp = certs1;
  413. while (*cp++) count1++;
  414. count = count1;
  415. cp = certs2;
  416. while (*cp++) count++;
  417. certs = nss_ZREALLOCARRAY(certs1, NSSCertificate *, count + 1);
  418. if (!certs) {
  419. nss_ZFreeIf(certs1);
  420. nss_ZFreeIf(certs2);
  421. return (NSSCertificate **)NULL;
  422. }
  423. for (cp = certs2; *cp; cp++, count1++) {
  424. certs[count1] = *cp;
  425. }
  426. nss_ZFreeIf(certs2);
  427. return certs;
  428. } else if (certs1) {
  429. return certs1;
  430. } else {
  431. return certs2;
  432. }
  433. }
  434. NSS_IMPLEMENT NSSCertificate *
  435. nssCertificateArray_FindBestCertificate (
  436. NSSCertificate **certs,
  437. NSSTime *timeOpt,
  438. const NSSUsage *usage,
  439. NSSPolicies *policiesOpt
  440. )
  441. {
  442. NSSCertificate *bestCert = NULL;
  443. NSSTime *time, sTime;
  444. PRBool haveUsageMatch = PR_FALSE;
  445. PRBool thisCertMatches;
  446. if (timeOpt) {
  447. time = timeOpt;
  448. } else {
  449. NSSTime_Now(&sTime);
  450. time = &sTime;
  451. }
  452. if (!certs) {
  453. return (NSSCertificate *)NULL;
  454. }
  455. for (; *certs; certs++) {
  456. nssDecodedCert *dc, *bestdc;
  457. NSSCertificate *c = *certs;
  458. dc = nssCertificate_GetDecoding(c);
  459. if (!dc) continue;
  460. thisCertMatches = dc->matchUsage(dc, usage);
  461. if (!bestCert) {
  462. /* always take the first cert, but remember whether or not
  463. * the usage matched
  464. */
  465. bestCert = nssCertificate_AddRef(c);
  466. haveUsageMatch = thisCertMatches;
  467. continue;
  468. } else {
  469. if (haveUsageMatch && !thisCertMatches) {
  470. /* if already have a cert for this usage, and if this cert
  471. * doesn't have the correct usage, continue
  472. */
  473. continue;
  474. } else if (!haveUsageMatch && thisCertMatches) {
  475. /* this one does match usage, replace the other */
  476. nssCertificate_Destroy(bestCert);
  477. bestCert = nssCertificate_AddRef(c);
  478. haveUsageMatch = PR_TRUE;
  479. continue;
  480. }
  481. /* this cert match as well as any cert we've found so far,
  482. * defer to time/policies
  483. * */
  484. }
  485. bestdc = nssCertificate_GetDecoding(bestCert);
  486. if (!bestdc) {
  487. nssCertificate_Destroy(bestCert);
  488. bestCert = nssCertificate_AddRef(c);
  489. continue;
  490. }
  491. /* time */
  492. if (bestdc->isValidAtTime(bestdc, time)) {
  493. /* The current best cert is valid at time */
  494. if (!dc->isValidAtTime(dc, time)) {
  495. /* If the new cert isn't valid at time, it's not better */
  496. continue;
  497. }
  498. } else {
  499. /* The current best cert is not valid at time */
  500. if (dc->isValidAtTime(dc, time)) {
  501. /* If the new cert is valid at time, it's better */
  502. nssCertificate_Destroy(bestCert);
  503. bestCert = nssCertificate_AddRef(c);
  504. }
  505. }
  506. /* either they are both valid at time, or neither valid;
  507. * take the newer one
  508. */
  509. if (!bestdc->isNewerThan(bestdc, dc)) {
  510. nssCertificate_Destroy(bestCert);
  511. bestCert = nssCertificate_AddRef(c);
  512. }
  513. /* policies */
  514. /* XXX later -- defer to policies */
  515. }
  516. return bestCert;
  517. }
  518. NSS_IMPLEMENT PRStatus
  519. nssCertificateArray_Traverse (
  520. NSSCertificate **certs,
  521. PRStatus (* callback)(NSSCertificate *c, void *arg),
  522. void *arg
  523. )
  524. {
  525. PRStatus status = PR_SUCCESS;
  526. if (certs) {
  527. NSSCertificate **certp;
  528. for (certp = certs; *certp; certp++) {
  529. status = (*callback)(*certp, arg);
  530. if (status != PR_SUCCESS) {
  531. break;
  532. }
  533. }
  534. }
  535. return status;
  536. }
  537. NSS_IMPLEMENT void
  538. nssCRLArray_Destroy (
  539. NSSCRL **crls
  540. )
  541. {
  542. if (crls) {
  543. NSSCRL **crlp;
  544. for (crlp = crls; *crlp; crlp++) {
  545. nssCRL_Destroy(*crlp);
  546. }
  547. nss_ZFreeIf(crls);
  548. }
  549. }
  550. /*
  551. * Object collections
  552. */
  553. typedef enum
  554. {
  555. pkiObjectType_Certificate = 0,
  556. pkiObjectType_CRL = 1,
  557. pkiObjectType_PrivateKey = 2,
  558. pkiObjectType_PublicKey = 3
  559. } pkiObjectType;
  560. /* Each object is defined by a set of items that uniquely identify it.
  561. * Here are the uid sets:
  562. *
  563. * NSSCertificate ==> { issuer, serial }
  564. * NSSPrivateKey
  565. * (RSA) ==> { modulus, public exponent }
  566. *
  567. */
  568. #define MAX_ITEMS_FOR_UID 2
  569. /* pkiObjectCollectionNode
  570. *
  571. * A node in the collection is the set of unique identifiers for a single
  572. * object, along with either the actual object or a proto-object.
  573. */
  574. typedef struct
  575. {
  576. PRCList link;
  577. PRBool haveObject;
  578. nssPKIObject *object;
  579. NSSItem uid[MAX_ITEMS_FOR_UID];
  580. }
  581. pkiObjectCollectionNode;
  582. /* nssPKIObjectCollection
  583. *
  584. * The collection is the set of all objects, plus the interfaces needed
  585. * to manage the objects.
  586. *
  587. */
  588. struct nssPKIObjectCollectionStr
  589. {
  590. NSSArena *arena;
  591. NSSTrustDomain *td;
  592. NSSCryptoContext *cc;
  593. PRCList head; /* list of pkiObjectCollectionNode's */
  594. PRUint32 size;
  595. pkiObjectType objectType;
  596. void (* destroyObject)(nssPKIObject *o);
  597. PRStatus (* getUIDFromObject)(nssPKIObject *o, NSSItem *uid);
  598. PRStatus (* getUIDFromInstance)(nssCryptokiObject *co, NSSItem *uid,
  599. NSSArena *arena);
  600. nssPKIObject * (* createObject)(nssPKIObject *o);
  601. nssPKILockType lockType; /* type of lock to use for new proto-objects */
  602. };
  603. static nssPKIObjectCollection *
  604. nssPKIObjectCollection_Create (
  605. NSSTrustDomain *td,
  606. NSSCryptoContext *ccOpt,
  607. nssPKILockType lockType
  608. )
  609. {
  610. NSSArena *arena;
  611. nssPKIObjectCollection *rvCollection = NULL;
  612. arena = nssArena_Create();
  613. if (!arena) {
  614. return (nssPKIObjectCollection *)NULL;
  615. }
  616. rvCollection = nss_ZNEW(arena, nssPKIObjectCollection);
  617. if (!rvCollection) {
  618. goto loser;
  619. }
  620. PR_INIT_CLIST(&rvCollection->head);
  621. rvCollection->arena = arena;
  622. rvCollection->td = td; /* XXX */
  623. rvCollection->cc = ccOpt;
  624. rvCollection->lockType = lockType;
  625. return rvCollection;
  626. loser:
  627. nssArena_Destroy(arena);
  628. return (nssPKIObjectCollection *)NULL;
  629. }
  630. NSS_IMPLEMENT void
  631. nssPKIObjectCollection_Destroy (
  632. nssPKIObjectCollection *collection
  633. )
  634. {
  635. if (collection) {
  636. PRCList *link;
  637. pkiObjectCollectionNode *node;
  638. /* first destroy any objects in the collection */
  639. link = PR_NEXT_LINK(&collection->head);
  640. while (link != &collection->head) {
  641. node = (pkiObjectCollectionNode *)link;
  642. if (node->haveObject) {
  643. (*collection->destroyObject)(node->object);
  644. } else {
  645. nssPKIObject_Destroy(node->object);
  646. }
  647. link = PR_NEXT_LINK(link);
  648. }
  649. /* then destroy it */
  650. nssArena_Destroy(collection->arena);
  651. }
  652. }
  653. NSS_IMPLEMENT PRUint32
  654. nssPKIObjectCollection_Count (
  655. nssPKIObjectCollection *collection
  656. )
  657. {
  658. return collection->size;
  659. }
  660. NSS_IMPLEMENT PRStatus
  661. nssPKIObjectCollection_AddObject (
  662. nssPKIObjectCollection *collection,
  663. nssPKIObject *object
  664. )
  665. {
  666. pkiObjectCollectionNode *node;
  667. node = nss_ZNEW(collection->arena, pkiObjectCollectionNode);
  668. if (!node) {
  669. return PR_FAILURE;
  670. }
  671. node->haveObject = PR_TRUE;
  672. node->object = nssPKIObject_AddRef(object);
  673. (*collection->getUIDFromObject)(object, node->uid);
  674. PR_INIT_CLIST(&node->link);
  675. PR_INSERT_BEFORE(&node->link, &collection->head);
  676. collection->size++;
  677. return PR_SUCCESS;
  678. }
  679. static pkiObjectCollectionNode *
  680. find_instance_in_collection (
  681. nssPKIObjectCollection *collection,
  682. nssCryptokiObject *instance
  683. )
  684. {
  685. PRCList *link;
  686. pkiObjectCollectionNode *node;
  687. link = PR_NEXT_LINK(&collection->head);
  688. while (link != &collection->head) {
  689. node = (pkiObjectCollectionNode *)link;
  690. if (nssPKIObject_HasInstance(node->object, instance)) {
  691. return node;
  692. }
  693. link = PR_NEXT_LINK(link);
  694. }
  695. return (pkiObjectCollectionNode *)NULL;
  696. }
  697. static pkiObjectCollectionNode *
  698. find_object_in_collection (
  699. nssPKIObjectCollection *collection,
  700. NSSItem *uid
  701. )
  702. {
  703. PRUint32 i;
  704. PRStatus status;
  705. PRCList *link;
  706. pkiObjectCollectionNode *node;
  707. link = PR_NEXT_LINK(&collection->head);
  708. while (link != &collection->head) {
  709. node = (pkiObjectCollectionNode *)link;
  710. for (i=0; i<MAX_ITEMS_FOR_UID; i++) {
  711. if (!nssItem_Equal(&node->uid[i], &uid[i], &status)) {
  712. break;
  713. }
  714. }
  715. if (i == MAX_ITEMS_FOR_UID) {
  716. return node;
  717. }
  718. link = PR_NEXT_LINK(link);
  719. }
  720. return (pkiObjectCollectionNode *)NULL;
  721. }
  722. static pkiObjectCollectionNode *
  723. add_object_instance (
  724. nssPKIObjectCollection *collection,
  725. nssCryptokiObject *instance,
  726. PRBool *foundIt
  727. )
  728. {
  729. PRUint32 i;
  730. PRStatus status;
  731. pkiObjectCollectionNode *node;
  732. nssArenaMark *mark = NULL;
  733. NSSItem uid[MAX_ITEMS_FOR_UID];
  734. nsslibc_memset(uid, 0, sizeof uid);
  735. /* The list is traversed twice, first (here) looking to match the
  736. * { token, handle } tuple, and if that is not found, below a search
  737. * for unique identifier is done. Here, a match means this exact object
  738. * instance is already in the collection, and we have nothing to do.
  739. */
  740. *foundIt = PR_FALSE;
  741. node = find_instance_in_collection(collection, instance);
  742. if (node) {
  743. /* The collection is assumed to take over the instance. Since we
  744. * are not using it, it must be destroyed.
  745. */
  746. nssCryptokiObject_Destroy(instance);
  747. *foundIt = PR_TRUE;
  748. return node;
  749. }
  750. mark = nssArena_Mark(collection->arena);
  751. if (!mark) {
  752. goto loser;
  753. }
  754. status = (*collection->getUIDFromInstance)(instance, uid,
  755. collection->arena);
  756. if (status != PR_SUCCESS) {
  757. goto loser;
  758. }
  759. /* Search for unique identifier. A match here means the object exists
  760. * in the collection, but does not have this instance, so the instance
  761. * needs to be added.
  762. */
  763. node = find_object_in_collection(collection, uid);
  764. if (node) {
  765. /* This is an object with multiple instances */
  766. status = nssPKIObject_AddInstance(node->object, instance);
  767. } else {
  768. /* This is a completely new object. Create a node for it. */
  769. node = nss_ZNEW(collection->arena, pkiObjectCollectionNode);
  770. if (!node) {
  771. goto loser;
  772. }
  773. node->object = nssPKIObject_Create(NULL, instance,
  774. collection->td, collection->cc,
  775. collection->lockType);
  776. if (!node->object) {
  777. goto loser;
  778. }
  779. for (i=0; i<MAX_ITEMS_FOR_UID; i++) {
  780. node->uid[i] = uid[i];
  781. }
  782. node->haveObject = PR_FALSE;
  783. PR_INIT_CLIST(&node->link);
  784. PR_INSERT_BEFORE(&node->link, &collection->head);
  785. collection->size++;
  786. status = PR_SUCCESS;
  787. }
  788. nssArena_Unmark(collection->arena, mark);
  789. return node;
  790. loser:
  791. if (mark) {
  792. nssArena_Release(collection->arena, mark);
  793. }
  794. nssCryptokiObject_Destroy(instance);
  795. return (pkiObjectCollectionNode *)NULL;
  796. }
  797. NSS_IMPLEMENT PRStatus
  798. nssPKIObjectCollection_AddInstances (
  799. nssPKIObjectCollection *collection,
  800. nssCryptokiObject **instances,
  801. PRUint32 numInstances
  802. )
  803. {
  804. PRStatus status = PR_SUCCESS;
  805. PRUint32 i = 0;
  806. PRBool foundIt;
  807. pkiObjectCollectionNode *node;
  808. if (instances) {
  809. while ((!numInstances || i < numInstances) && *instances) {
  810. if (status == PR_SUCCESS) {
  811. node = add_object_instance(collection, *instances, &foundIt);
  812. if (node == NULL) {
  813. /* add_object_instance freed the current instance */
  814. /* free the remaining instances */
  815. status = PR_FAILURE;
  816. }
  817. } else {
  818. nssCryptokiObject_Destroy(*instances);
  819. }
  820. instances++;
  821. i++;
  822. }
  823. }
  824. return status;
  825. }
  826. static void
  827. nssPKIObjectCollection_RemoveNode (
  828. nssPKIObjectCollection *collection,
  829. pkiObjectCollectionNode *node
  830. )
  831. {
  832. PR_REMOVE_LINK(&node->link);
  833. collection->size--;
  834. }
  835. static PRStatus
  836. nssPKIObjectCollection_GetObjects (
  837. nssPKIObjectCollection *collection,
  838. nssPKIObject **rvObjects,
  839. PRUint32 rvSize
  840. )
  841. {
  842. PRUint32 i = 0;
  843. PRCList *link = PR_NEXT_LINK(&collection->head);
  844. pkiObjectCollectionNode *node;
  845. int error=0;
  846. while ((i < rvSize) && (link != &collection->head)) {
  847. node = (pkiObjectCollectionNode *)link;
  848. if (!node->haveObject) {
  849. /* Convert the proto-object to an object */
  850. node->object = (*collection->createObject)(node->object);
  851. if (!node->object) {
  852. link = PR_NEXT_LINK(link);
  853. /*remove bogus object from list*/
  854. nssPKIObjectCollection_RemoveNode(collection,node);
  855. error++;
  856. continue;
  857. }
  858. node->haveObject = PR_TRUE;
  859. }
  860. rvObjects[i++] = nssPKIObject_AddRef(node->object);
  861. link = PR_NEXT_LINK(link);
  862. }
  863. if (!error && *rvObjects == NULL) {
  864. nss_SetError(NSS_ERROR_NOT_FOUND);
  865. }
  866. return PR_SUCCESS;
  867. }
  868. NSS_IMPLEMENT PRStatus
  869. nssPKIObjectCollection_Traverse (
  870. nssPKIObjectCollection *collection,
  871. nssPKIObjectCallback *callback
  872. )
  873. {
  874. PRStatus status;
  875. PRCList *link = PR_NEXT_LINK(&collection->head);
  876. pkiObjectCollectionNode *node;
  877. while (link != &collection->head) {
  878. node = (pkiObjectCollectionNode *)link;
  879. if (!node->haveObject) {
  880. node->object = (*collection->createObject)(node->object);
  881. if (!node->object) {
  882. link = PR_NEXT_LINK(link);
  883. /*remove bogus object from list*/
  884. nssPKIObjectCollection_RemoveNode(collection,node);
  885. continue;
  886. }
  887. node->haveObject = PR_TRUE;
  888. }
  889. switch (collection->objectType) {
  890. case pkiObjectType_Certificate:
  891. status = (*callback->func.cert)((NSSCertificate *)node->object,
  892. callback->arg);
  893. break;
  894. case pkiObjectType_CRL:
  895. status = (*callback->func.crl)((NSSCRL *)node->object,
  896. callback->arg);
  897. break;
  898. case pkiObjectType_PrivateKey:
  899. status = (*callback->func.pvkey)((NSSPrivateKey *)node->object,
  900. callback->arg);
  901. break;
  902. case pkiObjectType_PublicKey:
  903. status = (*callback->func.pbkey)((NSSPublicKey *)node->object,
  904. callback->arg);
  905. break;
  906. }
  907. link = PR_NEXT_LINK(link);
  908. }
  909. return PR_SUCCESS;
  910. }
  911. NSS_IMPLEMENT PRStatus
  912. nssPKIObjectCollection_AddInstanceAsObject (
  913. nssPKIObjectCollection *collection,
  914. nssCryptokiObject *instance
  915. )
  916. {
  917. pkiObjectCollectionNode *node;
  918. PRBool foundIt;
  919. node = add_object_instance(collection, instance, &foundIt);
  920. if (node == NULL) {
  921. return PR_FAILURE;
  922. }
  923. if (!node->haveObject) {
  924. node->object = (*collection->createObject)(node->object);
  925. if (!node->object) {
  926. /*remove bogus object from list*/
  927. nssPKIObjectCollection_RemoveNode(collection,node);
  928. return PR_FAILURE;
  929. }
  930. node->haveObject = PR_TRUE;
  931. } else if (!foundIt) {
  932. /* The instance was added to a pre-existing node. This
  933. * function is *only* being used for certificates, and having
  934. * multiple instances of certs in 3.X requires updating the
  935. * CERTCertificate.
  936. * But only do it if it was a new instance!!! If the same instance
  937. * is encountered, we set *foundIt to true. Detect that here and
  938. * ignore it.
  939. */
  940. STAN_ForceCERTCertificateUpdate((NSSCertificate *)node->object);
  941. }
  942. return PR_SUCCESS;
  943. }
  944. /*
  945. * Certificate collections
  946. */
  947. static void
  948. cert_destroyObject(nssPKIObject *o)
  949. {
  950. NSSCertificate *c = (NSSCertificate *)o;
  951. if (c->decoding) {
  952. CERTCertificate *cc = STAN_GetCERTCertificate(c);
  953. if (cc) {
  954. CERT_DestroyCertificate(cc);
  955. return;
  956. } /* else destroy it as NSSCertificate below */
  957. }
  958. nssCertificate_Destroy(c);
  959. }
  960. static PRStatus
  961. cert_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
  962. {
  963. NSSCertificate *c = (NSSCertificate *)o;
  964. /* The builtins are still returning decoded serial numbers. Until
  965. * this compatibility issue is resolved, use the full DER of the
  966. * cert to uniquely identify it.
  967. */
  968. NSSDER *derCert;
  969. derCert = nssCertificate_GetEncoding(c);
  970. uid[0].data = NULL; uid[0].size = 0;
  971. uid[1].data = NULL; uid[1].size = 0;
  972. if (derCert != NULL) {
  973. uid[0] = *derCert;
  974. }
  975. return PR_SUCCESS;
  976. }
  977. static PRStatus
  978. cert_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid,
  979. NSSArena *arena)
  980. {
  981. /* The builtins are still returning decoded serial numbers. Until
  982. * this compatibility issue is resolved, use the full DER of the
  983. * cert to uniquely identify it.
  984. */
  985. uid[1].data = NULL; uid[1].size = 0;
  986. return nssCryptokiCertificate_GetAttributes(instance,
  987. NULL, /* XXX sessionOpt */
  988. arena, /* arena */
  989. NULL, /* type */
  990. NULL, /* id */
  991. &uid[0], /* encoding */
  992. NULL, /* issuer */
  993. NULL, /* serial */
  994. NULL); /* subject */
  995. }
  996. static nssPKIObject *
  997. cert_createObject(nssPKIObject *o)
  998. {
  999. NSSCertificate *cert;
  1000. cert = nssCertificate_Create(o);
  1001. /* if (STAN_GetCERTCertificate(cert) == NULL) {
  1002. nssCertificate_Destroy(cert);
  1003. return (nssPKIObject *)NULL;
  1004. } */
  1005. /* In 3.4, have to maintain uniqueness of cert pointers by caching all
  1006. * certs. Cache the cert here, before returning. If it is already
  1007. * cached, take the cached entry.
  1008. */
  1009. {
  1010. NSSTrustDomain *td = o->trustDomain;
  1011. nssTrustDomain_AddCertsToCache(td, &cert, 1);
  1012. }
  1013. return (nssPKIObject *)cert;
  1014. }
  1015. NSS_IMPLEMENT nssPKIObjectCollection *
  1016. nssCertificateCollection_Create (
  1017. NSSTrustDomain *td,
  1018. NSSCertificate **certsOpt
  1019. )
  1020. {
  1021. PRStatus status;
  1022. nssPKIObjectCollection *collection;
  1023. collection = nssPKIObjectCollection_Create(td, NULL, nssPKIMonitor);
  1024. collection->objectType = pkiObjectType_Certificate;
  1025. collection->destroyObject = cert_destroyObject;
  1026. collection->getUIDFromObject = cert_getUIDFromObject;
  1027. collection->getUIDFromInstance = cert_getUIDFromInstance;
  1028. collection->createObject = cert_createObject;
  1029. if (certsOpt) {
  1030. for (; *certsOpt; certsOpt++) {
  1031. nssPKIObject *object = (nssPKIObject *)(*certsOpt);
  1032. status = nssPKIObjectCollection_AddObject(collection, object);
  1033. }
  1034. }
  1035. return collection;
  1036. }
  1037. NSS_IMPLEMENT NSSCertificate **
  1038. nssPKIObjectCollection_GetCertificates (
  1039. nssPKIObjectCollection *collection,
  1040. NSSCertificate **rvOpt,
  1041. PRUint32 maximumOpt,
  1042. NSSArena *arenaOpt
  1043. )
  1044. {
  1045. PRStatus status;
  1046. PRUint32 rvSize;
  1047. PRBool allocated = PR_FALSE;
  1048. if (collection->size == 0) {
  1049. return (NSSCertificate **)NULL;
  1050. }
  1051. if (maximumOpt == 0) {
  1052. rvSize = collection->size;
  1053. } else {
  1054. rvSize = PR_MIN(collection->size, maximumOpt);
  1055. }
  1056. if (!rvOpt) {
  1057. rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, rvSize + 1);
  1058. if (!rvOpt) {
  1059. return (NSSCertificate **)NULL;
  1060. }
  1061. allocated = PR_TRUE;
  1062. }
  1063. status = nssPKIObjectCollection_GetObjects(collection,
  1064. (nssPKIObject **)rvOpt,
  1065. rvSize);
  1066. if (status != PR_SUCCESS) {
  1067. if (allocated) {
  1068. nss_ZFreeIf(rvOpt);
  1069. }
  1070. return (NSSCertificate **)NULL;
  1071. }
  1072. return rvOpt;
  1073. }
  1074. /*
  1075. * CRL/KRL collections
  1076. */
  1077. static void
  1078. crl_destroyObject(nssPKIObject *o)
  1079. {
  1080. NSSCRL *crl = (NSSCRL *)o;
  1081. nssCRL_Destroy(crl);
  1082. }
  1083. static PRStatus
  1084. crl_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
  1085. {
  1086. NSSCRL *crl = (NSSCRL *)o;
  1087. NSSDER *encoding;
  1088. encoding = nssCRL_GetEncoding(crl);
  1089. if (!encoding) {
  1090. nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
  1091. return PR_FALSE;
  1092. }
  1093. uid[0] = *encoding;
  1094. uid[1].data = NULL; uid[1].size = 0;
  1095. return PR_SUCCESS;
  1096. }
  1097. static PRStatus
  1098. crl_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid,
  1099. NSSArena *arena)
  1100. {
  1101. return nssCryptokiCRL_GetAttributes(instance,
  1102. NULL, /* XXX sessionOpt */
  1103. arena, /* arena */
  1104. &uid[0], /* encoding */
  1105. NULL, /* subject */
  1106. NULL, /* class */
  1107. NULL, /* url */
  1108. NULL); /* isKRL */
  1109. }
  1110. static nssPKIObject *
  1111. crl_createObject(nssPKIObject *o)
  1112. {
  1113. return (nssPKIObject *)nssCRL_Create(o);
  1114. }
  1115. NSS_IMPLEMENT nssPKIObjectCollection *
  1116. nssCRLCollection_Create (
  1117. NSSTrustDomain *td,
  1118. NSSCRL **crlsOpt
  1119. )
  1120. {
  1121. PRStatus status;
  1122. nssPKIObjectCollection *collection;
  1123. collection = nssPKIObjectCollection_Create(td, NULL, nssPKILock);
  1124. collection->objectType = pkiObjectType_CRL;
  1125. collection->destroyObject = crl_destroyObject;
  1126. collection->getUIDFromObject = crl_getUIDFromObject;
  1127. collection->getUIDFromInstance = crl_getUIDFromInstance;
  1128. collection->createObject = crl_createObject;
  1129. if (crlsOpt) {
  1130. for (; *crlsOpt; crlsOpt++) {
  1131. nssPKIObject *object = (nssPKIObject *)(*crlsOpt);
  1132. status = nssPKIObjectCollection_AddObject(collection, object);
  1133. }
  1134. }
  1135. return collection;
  1136. }
  1137. NSS_IMPLEMENT NSSCRL **
  1138. nssPKIObjectCollection_GetCRLs (
  1139. nssPKIObjectCollection *collection,
  1140. NSSCRL **rvOpt,
  1141. PRUint32 maximumOpt,
  1142. NSSArena *arenaOpt
  1143. )
  1144. {
  1145. PRStatus status;
  1146. PRUint32 rvSize;
  1147. PRBool allocated = PR_FALSE;
  1148. if (collection->size == 0) {
  1149. return (NSSCRL **)NULL;
  1150. }
  1151. if (maximumOpt == 0) {
  1152. rvSize = collection->size;
  1153. } else {
  1154. rvSize = PR_MIN(collection->size, maximumOpt);
  1155. }
  1156. if (!rvOpt) {
  1157. rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCRL *, rvSize + 1);
  1158. if (!rvOpt) {
  1159. return (NSSCRL **)NULL;
  1160. }
  1161. allocated = PR_TRUE;
  1162. }
  1163. status = nssPKIObjectCollection_GetObjects(collection,
  1164. (nssPKIObject **)rvOpt,
  1165. rvSize);
  1166. if (status != PR_SUCCESS) {
  1167. if (allocated) {
  1168. nss_ZFreeIf(rvOpt);
  1169. }
  1170. return (NSSCRL **)NULL;
  1171. }
  1172. return rvOpt;
  1173. }
  1174. /* how bad would it be to have a static now sitting around, updated whenever
  1175. * this was called? would avoid repeated allocs...
  1176. */
  1177. NSS_IMPLEMENT NSSTime *
  1178. NSSTime_Now (
  1179. NSSTime *timeOpt
  1180. )
  1181. {
  1182. return NSSTime_SetPRTime(timeOpt, PR_Now());
  1183. }
  1184. NSS_IMPLEMENT NSSTime *
  1185. NSSTime_SetPRTime (
  1186. NSSTime *timeOpt,
  1187. PRTime prTime
  1188. )
  1189. {
  1190. NSSTime *rvTime;
  1191. rvTime = (timeOpt) ? timeOpt : nss_ZNEW(NULL, NSSTime);
  1192. if (rvTime) {
  1193. rvTime->prTime = prTime;
  1194. }
  1195. return rvTime;
  1196. }
  1197. NSS_IMPLEMENT PRTime
  1198. NSSTime_GetPRTime (
  1199. NSSTime *time
  1200. )
  1201. {
  1202. return time->prTime;
  1203. }