/security/nss/lib/ckfw/nssmkey/mfind.c

http://github.com/zpao/v8monkey · C · 404 lines · 292 code · 46 blank · 66 comment · 54 complexity · 455191a3fede912ffdae164876b7d919 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. * Portions created by Red Hat, Inc, are Copyright (C) 2005
  21. *
  22. * Contributor(s):
  23. * Bob Relyea (rrelyea@redhat.com)
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either the GNU General Public License Version 2 or later (the "GPL"), or
  27. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK ***** */
  38. #ifdef DEBUG
  39. static const char CVS_ID[] = "@(#) $RCSfile: mfind.c,v $ $Revision: 1.1 $ $Date: 2005/11/23 23:04:08 $";
  40. #endif /* DEBUG */
  41. #ifndef CKMK_H
  42. #include "ckmk.h"
  43. #endif /* CKMK_H */
  44. /*
  45. * nssmkey/mfind.c
  46. *
  47. * This file implements the NSSCKMDFindObjects object for the
  48. * "nssmkey" cryptoki module.
  49. */
  50. struct ckmkFOStr {
  51. NSSArena *arena;
  52. CK_ULONG n;
  53. CK_ULONG i;
  54. ckmkInternalObject **objs;
  55. };
  56. static void
  57. ckmk_mdFindObjects_Final
  58. (
  59. NSSCKMDFindObjects *mdFindObjects,
  60. NSSCKFWFindObjects *fwFindObjects,
  61. NSSCKMDSession *mdSession,
  62. NSSCKFWSession *fwSession,
  63. NSSCKMDToken *mdToken,
  64. NSSCKFWToken *fwToken,
  65. NSSCKMDInstance *mdInstance,
  66. NSSCKFWInstance *fwInstance
  67. )
  68. {
  69. struct ckmkFOStr *fo = (struct ckmkFOStr *)mdFindObjects->etc;
  70. NSSArena *arena = fo->arena;
  71. PRUint32 i;
  72. /* walk down an free the unused 'objs' */
  73. for (i=fo->i; i < fo->n ; i++) {
  74. nss_ckmk_DestroyInternalObject(fo->objs[i]);
  75. }
  76. nss_ZFreeIf(fo->objs);
  77. nss_ZFreeIf(fo);
  78. nss_ZFreeIf(mdFindObjects);
  79. if ((NSSArena *)NULL != arena) {
  80. NSSArena_Destroy(arena);
  81. }
  82. return;
  83. }
  84. static NSSCKMDObject *
  85. ckmk_mdFindObjects_Next
  86. (
  87. NSSCKMDFindObjects *mdFindObjects,
  88. NSSCKFWFindObjects *fwFindObjects,
  89. NSSCKMDSession *mdSession,
  90. NSSCKFWSession *fwSession,
  91. NSSCKMDToken *mdToken,
  92. NSSCKFWToken *fwToken,
  93. NSSCKMDInstance *mdInstance,
  94. NSSCKFWInstance *fwInstance,
  95. NSSArena *arena,
  96. CK_RV *pError
  97. )
  98. {
  99. struct ckmkFOStr *fo = (struct ckmkFOStr *)mdFindObjects->etc;
  100. ckmkInternalObject *io;
  101. if( fo->i == fo->n ) {
  102. *pError = CKR_OK;
  103. return (NSSCKMDObject *)NULL;
  104. }
  105. io = fo->objs[ fo->i ];
  106. fo->i++;
  107. return nss_ckmk_CreateMDObject(arena, io, pError);
  108. }
  109. static CK_BBOOL
  110. ckmk_attrmatch
  111. (
  112. CK_ATTRIBUTE_PTR a,
  113. ckmkInternalObject *o
  114. )
  115. {
  116. PRBool prb;
  117. const NSSItem *b;
  118. CK_RV error;
  119. b = nss_ckmk_FetchAttribute(o, a->type, &error);
  120. if (b == NULL) {
  121. return CK_FALSE;
  122. }
  123. if( a->ulValueLen != b->size ) {
  124. /* match a decoded serial number */
  125. if ((a->type == CKA_SERIAL_NUMBER) && (a->ulValueLen < b->size)) {
  126. int len;
  127. unsigned char *data;
  128. data = nss_ckmk_DERUnwrap(b->data, b->size, &len, NULL);
  129. if ((len == a->ulValueLen) &&
  130. nsslibc_memequal(a->pValue, data, len, (PRStatus *)NULL)) {
  131. return CK_TRUE;
  132. }
  133. }
  134. return CK_FALSE;
  135. }
  136. prb = nsslibc_memequal(a->pValue, b->data, b->size, (PRStatus *)NULL);
  137. if( PR_TRUE == prb ) {
  138. return CK_TRUE;
  139. } else {
  140. return CK_FALSE;
  141. }
  142. }
  143. static CK_BBOOL
  144. ckmk_match
  145. (
  146. CK_ATTRIBUTE_PTR pTemplate,
  147. CK_ULONG ulAttributeCount,
  148. ckmkInternalObject *o
  149. )
  150. {
  151. CK_ULONG i;
  152. for( i = 0; i < ulAttributeCount; i++ ) {
  153. if (CK_FALSE == ckmk_attrmatch(&pTemplate[i], o)) {
  154. return CK_FALSE;
  155. }
  156. }
  157. /* Every attribute passed */
  158. return CK_TRUE;
  159. }
  160. #define CKMK_ITEM_CHUNK 20
  161. #define PUT_OBJECT(obj, err, size, count, list) \
  162. { \
  163. if (count >= size) { \
  164. (list) = (list) ? \
  165. nss_ZREALLOCARRAY(list, ckmkInternalObject *, \
  166. ((size)+CKMK_ITEM_CHUNK) ) : \
  167. nss_ZNEWARRAY(NULL, ckmkInternalObject *, \
  168. ((size)+CKMK_ITEM_CHUNK) ) ; \
  169. if ((ckmkInternalObject **)NULL == list) { \
  170. err = CKR_HOST_MEMORY; \
  171. goto loser; \
  172. } \
  173. (size) += CKMK_ITEM_CHUNK; \
  174. } \
  175. (list)[ count ] = (obj); \
  176. count++; \
  177. }
  178. /* find all the certs that represent the appropriate object (cert, priv key, or
  179. * pub key) in the cert store.
  180. */
  181. static PRUint32
  182. collect_class(
  183. CK_OBJECT_CLASS objClass,
  184. SecItemClass itemClass,
  185. CK_ATTRIBUTE_PTR pTemplate,
  186. CK_ULONG ulAttributeCount,
  187. ckmkInternalObject ***listp,
  188. PRUint32 *sizep,
  189. PRUint32 count,
  190. CK_RV *pError
  191. )
  192. {
  193. ckmkInternalObject *next = NULL;
  194. SecKeychainSearchRef searchRef = 0;
  195. SecKeychainItemRef itemRef = 0;
  196. OSStatus error;
  197. /* future, build the attribute list based on the template
  198. * so we can refine the search */
  199. error = SecKeychainSearchCreateFromAttributes(
  200. NULL, itemClass, NULL, &searchRef);
  201. while (noErr == SecKeychainSearchCopyNext(searchRef, &itemRef)) {
  202. /* if we don't have an internal object structure, get one */
  203. if ((ckmkInternalObject *)NULL == next) {
  204. next = nss_ZNEW(NULL, ckmkInternalObject);
  205. if ((ckmkInternalObject *)NULL == next) {
  206. *pError = CKR_HOST_MEMORY;
  207. goto loser;
  208. }
  209. }
  210. /* fill in the relevant object data */
  211. next->type = ckmkItem;
  212. next->objClass = objClass;
  213. next->u.item.itemRef = itemRef;
  214. next->u.item.itemClass = itemClass;
  215. /* see if this is one of the objects we are looking for */
  216. if( CK_TRUE == ckmk_match(pTemplate, ulAttributeCount, next) ) {
  217. /* yes, put it on the list */
  218. PUT_OBJECT(next, *pError, *sizep, count, *listp);
  219. next = NULL; /* this one is on the list, need to allocate a new one now */
  220. } else {
  221. /* no , release the current item and clear out the structure for reuse */
  222. CFRelease(itemRef);
  223. /* don't cache the values we just loaded */
  224. nsslibc_memset(next, 0, sizeof(*next));
  225. }
  226. }
  227. loser:
  228. if (searchRef) {
  229. CFRelease(searchRef);
  230. }
  231. nss_ZFreeIf(next);
  232. return count;
  233. }
  234. static PRUint32
  235. collect_objects(
  236. CK_ATTRIBUTE_PTR pTemplate,
  237. CK_ULONG ulAttributeCount,
  238. ckmkInternalObject ***listp,
  239. CK_RV *pError
  240. )
  241. {
  242. PRUint32 i;
  243. PRUint32 count = 0;
  244. PRUint32 size = 0;
  245. CK_OBJECT_CLASS objClass;
  246. /*
  247. * first handle the static build in objects (if any)
  248. */
  249. for( i = 0; i < nss_ckmk_nObjects; i++ ) {
  250. ckmkInternalObject *o = (ckmkInternalObject *)&nss_ckmk_data[i];
  251. if( CK_TRUE == ckmk_match(pTemplate, ulAttributeCount, o) ) {
  252. PUT_OBJECT(o, *pError, size, count, *listp);
  253. }
  254. }
  255. /*
  256. * now handle the various object types
  257. */
  258. objClass = nss_ckmk_GetULongAttribute(CKA_CLASS,
  259. pTemplate, ulAttributeCount, pError);
  260. if (CKR_OK != *pError) {
  261. objClass = CK_INVALID_HANDLE;
  262. }
  263. *pError = CKR_OK;
  264. switch (objClass) {
  265. case CKO_CERTIFICATE:
  266. count = collect_class(objClass, kSecCertificateItemClass,
  267. pTemplate, ulAttributeCount, listp,
  268. &size, count, pError);
  269. break;
  270. case CKO_PUBLIC_KEY:
  271. count = collect_class(objClass, CSSM_DL_DB_RECORD_PUBLIC_KEY,
  272. pTemplate, ulAttributeCount, listp,
  273. &size, count, pError);
  274. break;
  275. case CKO_PRIVATE_KEY:
  276. count = collect_class(objClass, CSSM_DL_DB_RECORD_PRIVATE_KEY,
  277. pTemplate, ulAttributeCount, listp,
  278. &size, count, pError);
  279. break;
  280. /* all of them */
  281. case CK_INVALID_HANDLE:
  282. count = collect_class(CKO_CERTIFICATE, kSecCertificateItemClass,
  283. pTemplate, ulAttributeCount, listp,
  284. &size, count, pError);
  285. count = collect_class(CKO_PUBLIC_KEY, CSSM_DL_DB_RECORD_PUBLIC_KEY,
  286. pTemplate, ulAttributeCount, listp,
  287. &size, count, pError);
  288. count = collect_class(CKO_PUBLIC_KEY, CSSM_DL_DB_RECORD_PRIVATE_KEY,
  289. pTemplate, ulAttributeCount, listp,
  290. &size, count, pError);
  291. break;
  292. default:
  293. break;
  294. }
  295. if (CKR_OK != *pError) {
  296. goto loser;
  297. }
  298. return count;
  299. loser:
  300. nss_ZFreeIf(*listp);
  301. return 0;
  302. }
  303. NSS_IMPLEMENT NSSCKMDFindObjects *
  304. nss_ckmk_FindObjectsInit
  305. (
  306. NSSCKFWSession *fwSession,
  307. CK_ATTRIBUTE_PTR pTemplate,
  308. CK_ULONG ulAttributeCount,
  309. CK_RV *pError
  310. )
  311. {
  312. /* This could be made more efficient. I'm rather rushed. */
  313. NSSArena *arena;
  314. NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *)NULL;
  315. struct ckmkFOStr *fo = (struct ckmkFOStr *)NULL;
  316. ckmkInternalObject **temp = (ckmkInternalObject **)NULL;
  317. arena = NSSArena_Create();
  318. if( (NSSArena *)NULL == arena ) {
  319. goto loser;
  320. }
  321. rv = nss_ZNEW(arena, NSSCKMDFindObjects);
  322. if( (NSSCKMDFindObjects *)NULL == rv ) {
  323. *pError = CKR_HOST_MEMORY;
  324. goto loser;
  325. }
  326. fo = nss_ZNEW(arena, struct ckmkFOStr);
  327. if( (struct ckmkFOStr *)NULL == fo ) {
  328. *pError = CKR_HOST_MEMORY;
  329. goto loser;
  330. }
  331. fo->arena = arena;
  332. /* fo->n and fo->i are already zero */
  333. rv->etc = (void *)fo;
  334. rv->Final = ckmk_mdFindObjects_Final;
  335. rv->Next = ckmk_mdFindObjects_Next;
  336. rv->null = (void *)NULL;
  337. fo->n = collect_objects(pTemplate, ulAttributeCount, &temp, pError);
  338. if (*pError != CKR_OK) {
  339. goto loser;
  340. }
  341. fo->objs = nss_ZNEWARRAY(arena, ckmkInternalObject *, fo->n);
  342. if( (ckmkInternalObject **)NULL == fo->objs ) {
  343. *pError = CKR_HOST_MEMORY;
  344. goto loser;
  345. }
  346. (void)nsslibc_memcpy(fo->objs, temp, sizeof(ckmkInternalObject *) * fo->n);
  347. nss_ZFreeIf(temp);
  348. temp = (ckmkInternalObject **)NULL;
  349. return rv;
  350. loser:
  351. nss_ZFreeIf(temp);
  352. nss_ZFreeIf(fo);
  353. nss_ZFreeIf(rv);
  354. if ((NSSArena *)NULL != arena) {
  355. NSSArena_Destroy(arena);
  356. }
  357. return (NSSCKMDFindObjects *)NULL;
  358. }