1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14 * The Original Code is the Netscape security libraries.
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
23 * Bob Relyea (rrelyea@redhat.com)
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.
37 * ***** END LICENSE BLOCK ***** */
39 static const char CVS_ID
[] = "@(#) $RCSfile: mfind.c,v $ $Revision: 1.1 $ $Date: 2005/11/23 23:04:08 $";
49 * This file implements the NSSCKMDFindObjects object for the
50 * "nssmkey" cryptoki module.
57 ckmkInternalObject
**objs
;
61 ckmk_mdFindObjects_Final
63 NSSCKMDFindObjects
*mdFindObjects
,
64 NSSCKFWFindObjects
*fwFindObjects
,
65 NSSCKMDSession
*mdSession
,
66 NSSCKFWSession
*fwSession
,
67 NSSCKMDToken
*mdToken
,
68 NSSCKFWToken
*fwToken
,
69 NSSCKMDInstance
*mdInstance
,
70 NSSCKFWInstance
*fwInstance
73 struct ckmkFOStr
*fo
= (struct ckmkFOStr
*)mdFindObjects
->etc
;
74 NSSArena
*arena
= fo
->arena
;
77 /* walk down an free the unused 'objs' */
78 for (i
=fo
->i
; i
< fo
->n
; i
++) {
79 nss_ckmk_DestroyInternalObject(fo
->objs
[i
]);
82 nss_ZFreeIf(fo
->objs
);
84 nss_ZFreeIf(mdFindObjects
);
85 if ((NSSArena
*)NULL
!= arena
) {
86 NSSArena_Destroy(arena
);
92 static NSSCKMDObject
*
93 ckmk_mdFindObjects_Next
95 NSSCKMDFindObjects
*mdFindObjects
,
96 NSSCKFWFindObjects
*fwFindObjects
,
97 NSSCKMDSession
*mdSession
,
98 NSSCKFWSession
*fwSession
,
99 NSSCKMDToken
*mdToken
,
100 NSSCKFWToken
*fwToken
,
101 NSSCKMDInstance
*mdInstance
,
102 NSSCKFWInstance
*fwInstance
,
107 struct ckmkFOStr
*fo
= (struct ckmkFOStr
*)mdFindObjects
->etc
;
108 ckmkInternalObject
*io
;
110 if( fo
->i
== fo
->n
) {
112 return (NSSCKMDObject
*)NULL
;
115 io
= fo
->objs
[ fo
->i
];
118 return nss_ckmk_CreateMDObject(arena
, io
, pError
);
125 ckmkInternalObject
*o
132 b
= nss_ckmk_FetchAttribute(o
, a
->type
, &error
);
137 if( a
->ulValueLen
!= b
->size
) {
138 /* match a decoded serial number */
139 if ((a
->type
== CKA_SERIAL_NUMBER
) && (a
->ulValueLen
< b
->size
)) {
143 data
= nss_ckmk_DERUnwrap(b
->data
, b
->size
, &len
, NULL
);
144 if ((len
== a
->ulValueLen
) &&
145 nsslibc_memequal(a
->pValue
, data
, len
, (PRStatus
*)NULL
)) {
152 prb
= nsslibc_memequal(a
->pValue
, b
->data
, b
->size
, (PRStatus
*)NULL
);
154 if( PR_TRUE
== prb
) {
165 CK_ATTRIBUTE_PTR pTemplate
,
166 CK_ULONG ulAttributeCount
,
167 ckmkInternalObject
*o
172 for( i
= 0; i
< ulAttributeCount
; i
++ ) {
173 if (CK_FALSE
== ckmk_attrmatch(&pTemplate
[i
], o
)) {
178 /* Every attribute passed */
182 #define CKMK_ITEM_CHUNK 20
184 #define PUT_OBJECT(obj, err, size, count, list) \
186 if (count >= size) { \
188 nss_ZREALLOCARRAY(list, ckmkInternalObject *, \
189 ((size)+CKMK_ITEM_CHUNK) ) : \
190 nss_ZNEWARRAY(NULL, ckmkInternalObject *, \
191 ((size)+CKMK_ITEM_CHUNK) ) ; \
192 if ((ckmkInternalObject **)NULL == list) { \
193 err = CKR_HOST_MEMORY; \
196 (size) += CKMK_ITEM_CHUNK; \
198 (list)[ count ] = (obj); \
203 /* find all the certs that represent the appropriate object (cert, priv key, or
204 * pub key) in the cert store.
208 CK_OBJECT_CLASS objClass
,
209 SecItemClass itemClass
,
210 CK_ATTRIBUTE_PTR pTemplate
,
211 CK_ULONG ulAttributeCount
,
212 ckmkInternalObject
***listp
,
218 ckmkInternalObject
*next
= NULL
;
219 SecKeychainSearchRef searchRef
= 0;
220 SecKeychainItemRef itemRef
= 0;
223 /* future, build the attribute list based on the template
224 * so we can refine the search */
225 error
= SecKeychainSearchCreateFromAttributes(
226 NULL
, itemClass
, NULL
, &searchRef
);
228 while (noErr
== SecKeychainSearchCopyNext(searchRef
, &itemRef
)) {
229 /* if we don't have an internal object structure, get one */
230 if ((ckmkInternalObject
*)NULL
== next
) {
231 next
= nss_ZNEW(NULL
, ckmkInternalObject
);
232 if ((ckmkInternalObject
*)NULL
== next
) {
233 *pError
= CKR_HOST_MEMORY
;
237 /* fill in the relevant object data */
238 next
->type
= ckmkItem
;
239 next
->objClass
= objClass
;
240 next
->u
.item
.itemRef
= itemRef
;
241 next
->u
.item
.itemClass
= itemClass
;
243 /* see if this is one of the objects we are looking for */
244 if( CK_TRUE
== ckmk_match(pTemplate
, ulAttributeCount
, next
) ) {
245 /* yes, put it on the list */
246 PUT_OBJECT(next
, *pError
, *sizep
, count
, *listp
);
247 next
= NULL
; /* this one is on the list, need to allocate a new one now */
249 /* no , release the current item and clear out the structure for reuse */
251 /* don't cache the values we just loaded */
252 nsslibc_memset(next
, 0, sizeof(*next
));
257 CFRelease(searchRef
);
265 CK_ATTRIBUTE_PTR pTemplate
,
266 CK_ULONG ulAttributeCount
,
267 ckmkInternalObject
***listp
,
274 CK_OBJECT_CLASS objClass
;
277 * first handle the static build in objects (if any)
279 for( i
= 0; i
< nss_ckmk_nObjects
; i
++ ) {
280 ckmkInternalObject
*o
= (ckmkInternalObject
*)&nss_ckmk_data
[i
];
282 if( CK_TRUE
== ckmk_match(pTemplate
, ulAttributeCount
, o
) ) {
283 PUT_OBJECT(o
, *pError
, size
, count
, *listp
);
288 * now handle the various object types
290 objClass
= nss_ckmk_GetULongAttribute(CKA_CLASS
,
291 pTemplate
, ulAttributeCount
, pError
);
292 if (CKR_OK
!= *pError
) {
293 objClass
= CK_INVALID_HANDLE
;
297 case CKO_CERTIFICATE
:
298 count
= collect_class(objClass
, kSecCertificateItemClass
,
299 pTemplate
, ulAttributeCount
, listp
,
300 &size
, count
, pError
);
303 count
= collect_class(objClass
, CSSM_DL_DB_RECORD_PUBLIC_KEY
,
304 pTemplate
, ulAttributeCount
, listp
,
305 &size
, count
, pError
);
307 case CKO_PRIVATE_KEY
:
308 count
= collect_class(objClass
, CSSM_DL_DB_RECORD_PRIVATE_KEY
,
309 pTemplate
, ulAttributeCount
, listp
,
310 &size
, count
, pError
);
313 case CK_INVALID_HANDLE
:
314 count
= collect_class(CKO_CERTIFICATE
, kSecCertificateItemClass
,
315 pTemplate
, ulAttributeCount
, listp
,
316 &size
, count
, pError
);
317 count
= collect_class(CKO_PUBLIC_KEY
, CSSM_DL_DB_RECORD_PUBLIC_KEY
,
318 pTemplate
, ulAttributeCount
, listp
,
319 &size
, count
, pError
);
320 count
= collect_class(CKO_PUBLIC_KEY
, CSSM_DL_DB_RECORD_PRIVATE_KEY
,
321 pTemplate
, ulAttributeCount
, listp
,
322 &size
, count
, pError
);
327 if (CKR_OK
!= *pError
) {
338 NSS_IMPLEMENT NSSCKMDFindObjects
*
339 nss_ckmk_FindObjectsInit
341 NSSCKFWSession
*fwSession
,
342 CK_ATTRIBUTE_PTR pTemplate
,
343 CK_ULONG ulAttributeCount
,
347 /* This could be made more efficient. I'm rather rushed. */
349 NSSCKMDFindObjects
*rv
= (NSSCKMDFindObjects
*)NULL
;
350 struct ckmkFOStr
*fo
= (struct ckmkFOStr
*)NULL
;
351 ckmkInternalObject
**temp
= (ckmkInternalObject
**)NULL
;
353 arena
= NSSArena_Create();
354 if( (NSSArena
*)NULL
== arena
) {
358 rv
= nss_ZNEW(arena
, NSSCKMDFindObjects
);
359 if( (NSSCKMDFindObjects
*)NULL
== rv
) {
360 *pError
= CKR_HOST_MEMORY
;
364 fo
= nss_ZNEW(arena
, struct ckmkFOStr
);
365 if( (struct ckmkFOStr
*)NULL
== fo
) {
366 *pError
= CKR_HOST_MEMORY
;
371 /* fo->n and fo->i are already zero */
373 rv
->etc
= (void *)fo
;
374 rv
->Final
= ckmk_mdFindObjects_Final
;
375 rv
->Next
= ckmk_mdFindObjects_Next
;
376 rv
->null
= (void *)NULL
;
378 fo
->n
= collect_objects(pTemplate
, ulAttributeCount
, &temp
, pError
);
379 if (*pError
!= CKR_OK
) {
383 fo
->objs
= nss_ZNEWARRAY(arena
, ckmkInternalObject
*, fo
->n
);
384 if( (ckmkInternalObject
**)NULL
== fo
->objs
) {
385 *pError
= CKR_HOST_MEMORY
;
389 (void)nsslibc_memcpy(fo
->objs
, temp
, sizeof(ckmkInternalObject
*) * fo
->n
);
391 temp
= (ckmkInternalObject
**)NULL
;
399 if ((NSSArena
*)NULL
!= arena
) {
400 NSSArena_Destroy(arena
);
402 return (NSSCKMDFindObjects
*)NULL
;