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: cfind.c,v $ $Revision: 1.2 $ $Date: 2005/11/15 00:13:58 $";
49
* This file implements the NSSCKMDFindObjects object for the
50
* "capi" cryptoki module.
57
ckcapiInternalObject **objs;
61
ckcapi_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 ckcapiFOStr *fo = (struct ckcapiFOStr *)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_ckcapi_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
ckcapi_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 ckcapiFOStr *fo = (struct ckcapiFOStr *)mdFindObjects->etc;
108
ckcapiInternalObject *io;
110
if( fo->i == fo->n ) {
112
return (NSSCKMDObject *)NULL;
115
io = fo->objs[ fo->i ];
118
return nss_ckcapi_CreateMDObject(arena, io, pError);
125
ckcapiInternalObject *o
131
b = nss_ckcapi_FetchAttribute(o, a->type);
136
if( a->ulValueLen != b->size ) {
137
/* match a decoded serial number */
138
if ((a->type == CKA_SERIAL_NUMBER) && (a->ulValueLen < b->size)) {
142
data = nss_ckcapi_DERUnwrap(b->data, b->size, &len, NULL);
143
if ((len == a->ulValueLen) &&
144
nsslibc_memequal(a->pValue, data, len, (PRStatus *)NULL)) {
151
prb = nsslibc_memequal(a->pValue, b->data, b->size, (PRStatus *)NULL);
153
if( PR_TRUE == prb ) {
164
CK_ATTRIBUTE_PTR pTemplate,
165
CK_ULONG ulAttributeCount,
166
ckcapiInternalObject *o
171
for( i = 0; i < ulAttributeCount; i++ ) {
172
if (CK_FALSE == ckcapi_attrmatch(&pTemplate[i], o)) {
177
/* Every attribute passed */
181
#define CKAPI_ITEM_CHUNK 20
183
#define PUT_Object(obj,err) \
185
if (count >= size) { \
187
nss_ZREALLOCARRAY(*listp, ckcapiInternalObject *, \
188
(size+CKAPI_ITEM_CHUNK) ) : \
189
nss_ZNEWARRAY(NULL, ckcapiInternalObject *, \
190
(size+CKAPI_ITEM_CHUNK) ) ; \
191
if ((ckcapiInternalObject **)NULL == *listp) { \
192
err = CKR_HOST_MEMORY; \
195
size += CKAPI_ITEM_CHUNK; \
197
(*listp)[ count ] = (obj); \
203
* pass parameters back through the callback.
205
typedef struct BareCollectParamsStr {
206
CK_OBJECT_CLASS objClass;
207
CK_ATTRIBUTE_PTR pTemplate;
208
CK_ULONG ulAttributeCount;
209
ckcapiInternalObject ***listp;
214
/* collect_bare's callback. Called for each object that
215
* supposedly has a PROVINDER_INFO property */
219
const CRYPT_HASH_BLOB *msKeyID,
229
BareCollectParams *bcp = (BareCollectParams *) args;
230
PRUint32 size = bcp->size;
231
PRUint32 count = bcp->count;
232
ckcapiInternalObject ***listp = bcp->listp;
233
ckcapiInternalObject *io = NULL;
235
CRYPT_KEY_PROV_INFO *keyProvInfo = NULL;
239
/* make sure there is a Key Provider Info property */
240
for (i=0; i < cProp; i++) {
241
if (CERT_KEY_PROV_INFO_PROP_ID == propID[i]) {
242
keyProvInfo = (CRYPT_KEY_PROV_INFO *)propData[i];
246
if ((CRYPT_KEY_PROV_INFO *)NULL == keyProvInfo) {
250
/* copy the key ID */
251
idData = nss_ZNEWARRAY(NULL, char, msKeyID->cbData);
252
if ((void *)NULL == idData) {
255
nsslibc_memcpy(idData, msKeyID->pbData, msKeyID->cbData);
257
/* build a bare internal object */
258
io = nss_ZNEW(NULL, ckcapiInternalObject);
259
if ((ckcapiInternalObject *)NULL == io) {
262
io->type = ckcapiBareKey;
263
io->objClass = bcp->objClass;
264
io->u.key.provInfo = *keyProvInfo;
265
io->u.key.provInfo.pwszContainerName =
266
nss_ckcapi_WideDup(keyProvInfo->pwszContainerName);
267
io->u.key.provInfo.pwszProvName =
268
nss_ckcapi_WideDup(keyProvInfo->pwszProvName);
269
io->u.key.provName = nss_ckcapi_WideToUTF8(keyProvInfo->pwszProvName);
270
io->u.key.containerName =
271
nss_ckcapi_WideToUTF8(keyProvInfo->pwszContainerName);
274
io->id.data = idData;
275
io->id.size = msKeyID->cbData;
278
/* see if it matches */
279
if( CK_FALSE == ckcapi_match(bcp->pTemplate, bcp->ulAttributeCount, io) ) {
282
PUT_Object(io, error);
289
nss_ckcapi_DestroyInternalObject(io);
296
* collect the bare keys running around
300
CK_OBJECT_CLASS objClass,
301
CK_ATTRIBUTE_PTR pTemplate,
302
CK_ULONG ulAttributeCount,
303
ckcapiInternalObject ***listp,
310
BareCollectParams bareCollectParams;
312
bareCollectParams.objClass = objClass;
313
bareCollectParams.pTemplate = pTemplate;
314
bareCollectParams.ulAttributeCount = ulAttributeCount;
315
bareCollectParams.listp = listp;
316
bareCollectParams.size = *sizep;
317
bareCollectParams.count = count;
319
rc = CryptEnumKeyIdentifierProperties(NULL, CERT_KEY_PROV_INFO_PROP_ID, 0,
320
NULL, NULL, &bareCollectParams, doBareCollect);
322
*sizep = bareCollectParams.size;
323
return bareCollectParams.count;
326
/* find all the certs that represent the appropriate object (cert, priv key, or
327
* pub key) in the cert store.
331
CK_OBJECT_CLASS objClass,
334
CK_ATTRIBUTE_PTR pTemplate,
335
CK_ULONG ulAttributeCount,
336
ckcapiInternalObject ***listp,
342
PRUint32 size = *sizep;
343
ckcapiInternalObject *next = NULL;
345
PCCERT_CONTEXT certContext = NULL;
347
(objClass == CKO_PUBLIC_KEY) | (objClass == CKO_PRIVATE_KEY);
349
hStore = CertOpenSystemStore((HCRYPTPROV)NULL, storeStr);
350
if (NULL == hStore) {
351
return count; /* none found does not imply an error */
354
/* FUTURE: use CertFindCertificateInStore to filter better -- so we don't
355
* have to enumerate all the certificates */
356
while ((PCERT_CONTEXT) NULL !=
357
(certContext= CertEnumCertificatesInStore(hStore, certContext))) {
358
/* first filter out non user certs if we are looking for keys */
360
/* make sure there is a Key Provider Info property */
361
CRYPT_KEY_PROV_INFO key_prov;
362
DWORD size = sizeof(CRYPT_KEY_PROV_INFO);
364
rv =CertGetCertificateContextProperty(certContext,
365
CERT_KEY_PROV_INFO_PROP_ID, &key_prov, &size);
367
int reason = GetLastError();
368
/* we only care if it exists, we don't really need to fetch it yet */
369
if (reason == CRYPT_E_NOT_FOUND) {
375
if ((ckcapiInternalObject *)NULL == next) {
376
next = nss_ZNEW(NULL, ckcapiInternalObject);
377
if ((ckcapiInternalObject *)NULL == next) {
378
*pError = CKR_HOST_MEMORY;
382
next->type = ckcapiCert;
383
next->objClass = objClass;
384
next->u.cert.certContext = certContext;
385
next->u.cert.hasID = hasID;
386
next->u.cert.certStore = storeStr;
387
if( CK_TRUE == ckcapi_match(pTemplate, ulAttributeCount, next) ) {
388
/* clear cached values that may be dependent on our old certContext */
389
memset(&next->u.cert, 0, sizeof(next->u.cert));
390
/* get a 'permanent' context */
391
next->u.cert.certContext = CertDuplicateCertificateContext(certContext);
392
next->objClass = objClass;
393
next->u.cert.certContext = certContext;
394
next->u.cert.hasID = hasID;
395
next->u.cert.certStore = storeStr;
396
PUT_Object(next, *pError);
397
next = NULL; /* need to allocate a new one now */
399
/* don't cache the values we just loaded */
400
memset(&next->u.cert, 0, sizeof(next->u.cert));
404
CertCloseStore(hStore, 0);
410
NSS_IMPLEMENT PRUint32
411
nss_ckcapi_collect_all_certs(
412
CK_ATTRIBUTE_PTR pTemplate,
413
CK_ULONG ulAttributeCount,
414
ckcapiInternalObject ***listp,
420
count = collect_class(CKO_CERTIFICATE, "My", PR_TRUE, pTemplate,
421
ulAttributeCount, listp, sizep, count, pError);
422
count = collect_class(CKO_CERTIFICATE, "AddressBook", PR_FALSE, pTemplate,
423
ulAttributeCount, listp, sizep, count, pError);
424
count = collect_class(CKO_CERTIFICATE, "CA", PR_FALSE, pTemplate,
425
ulAttributeCount, listp, sizep, count, pError);
426
count = collect_class(CKO_CERTIFICATE, "Root", PR_FALSE, pTemplate,
427
ulAttributeCount, listp, sizep, count, pError);
428
count = collect_class(CKO_CERTIFICATE, "Trust", PR_FALSE, pTemplate,
429
ulAttributeCount, listp, sizep, count, pError);
430
count = collect_class(CKO_CERTIFICATE, "TrustedPeople", PR_FALSE, pTemplate,
431
ulAttributeCount, listp, sizep, count, pError);
432
count = collect_class(CKO_CERTIFICATE, "AuthRoot", PR_FALSE, pTemplate,
433
ulAttributeCount, listp, sizep, count, pError);
438
ckcapi_GetObjectClass(CK_ATTRIBUTE_PTR pTemplate,
439
CK_ULONG ulAttributeCount)
443
for (i=0; i < ulAttributeCount; i++)
445
if (pTemplate[i].type == CKA_CLASS) {
446
return *(CK_OBJECT_CLASS *) pTemplate[i].pValue;
449
/* need to return a value that says 'fetch them all' */
450
return CK_INVALID_HANDLE;
455
CK_ATTRIBUTE_PTR pTemplate,
456
CK_ULONG ulAttributeCount,
457
ckcapiInternalObject ***listp,
464
CK_OBJECT_CLASS objClass;
467
* first handle the static build in objects (if any)
469
for( i = 0; i < nss_ckcapi_nObjects; i++ ) {
470
ckcapiInternalObject *o = (ckcapiInternalObject *)&nss_ckcapi_data[i];
472
if( CK_TRUE == ckcapi_match(pTemplate, ulAttributeCount, o) ) {
473
PUT_Object(o, *pError);
478
* now handle the various object types
480
objClass = ckcapi_GetObjectClass(pTemplate, ulAttributeCount);
483
case CKO_CERTIFICATE:
484
count = nss_ckcapi_collect_all_certs(pTemplate, ulAttributeCount, listp,
485
&size, count, pError);
488
count = collect_class(objClass, "My", PR_TRUE, pTemplate,
489
ulAttributeCount, listp, &size, count, pError);
490
count = collect_bare(objClass, pTemplate, ulAttributeCount, listp,
491
&size, count, pError);
493
case CKO_PRIVATE_KEY:
494
count = collect_class(objClass, "My", PR_TRUE, pTemplate,
495
ulAttributeCount, listp, &size, count, pError);
496
count = collect_bare(objClass, pTemplate, ulAttributeCount, listp,
497
&size, count, pError);
500
case CK_INVALID_HANDLE:
501
count = nss_ckcapi_collect_all_certs(pTemplate, ulAttributeCount, listp,
502
&size, count, pError);
503
count = collect_class(CKO_PUBLIC_KEY, "My", PR_TRUE, pTemplate,
504
ulAttributeCount, listp, &size, count, pError);
505
count = collect_bare(CKO_PUBLIC_KEY, pTemplate, ulAttributeCount, listp,
506
&size, count, pError);
507
count = collect_class(CKO_PRIVATE_KEY, "My", PR_TRUE, pTemplate,
508
ulAttributeCount, listp, &size, count, pError);
509
count = collect_bare(CKO_PRIVATE_KEY, pTemplate, ulAttributeCount, listp,
510
&size, count, pError);
513
goto done; /* no other object types we understand in this module */
515
if (CKR_OK != *pError) {
529
NSS_IMPLEMENT NSSCKMDFindObjects *
530
nss_ckcapi_FindObjectsInit
532
NSSCKFWSession *fwSession,
533
CK_ATTRIBUTE_PTR pTemplate,
534
CK_ULONG ulAttributeCount,
538
/* This could be made more efficient. I'm rather rushed. */
540
NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *)NULL;
541
struct ckcapiFOStr *fo = (struct ckcapiFOStr *)NULL;
542
ckcapiInternalObject **temp = (ckcapiInternalObject **)NULL;
544
arena = NSSArena_Create();
545
if( (NSSArena *)NULL == arena ) {
549
rv = nss_ZNEW(arena, NSSCKMDFindObjects);
550
if( (NSSCKMDFindObjects *)NULL == rv ) {
551
*pError = CKR_HOST_MEMORY;
555
fo = nss_ZNEW(arena, struct ckcapiFOStr);
556
if( (struct ckcapiFOStr *)NULL == fo ) {
557
*pError = CKR_HOST_MEMORY;
562
/* fo->n and fo->i are already zero */
564
rv->etc = (void *)fo;
565
rv->Final = ckcapi_mdFindObjects_Final;
566
rv->Next = ckcapi_mdFindObjects_Next;
567
rv->null = (void *)NULL;
569
fo->n = collect_objects(pTemplate, ulAttributeCount, &temp, pError);
570
if (*pError != CKR_OK) {
574
fo->objs = nss_ZNEWARRAY(arena, ckcapiInternalObject *, fo->n);
575
if( (ckcapiInternalObject **)NULL == fo->objs ) {
576
*pError = CKR_HOST_MEMORY;
580
(void)nsslibc_memcpy(fo->objs, temp, sizeof(ckcapiInternalObject *) * fo->n);
582
temp = (ckcapiInternalObject **)NULL;
590
if ((NSSArena *)NULL != arena) {
591
NSSArena_Destroy(arena);
593
return (NSSCKMDFindObjects *)NULL;