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

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

mercurial