comparison nss/lib/pk11wrap/pk11obj.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
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 * This file manages object type indepentent functions.
6 */
7 #include "seccomon.h"
8 #include "secmod.h"
9 #include "secmodi.h"
10 #include "secmodti.h"
11 #include "pkcs11.h"
12 #include "pkcs11t.h"
13 #include "pk11func.h"
14 #include "key.h"
15 #include "secitem.h"
16 #include "secerr.h"
17 #include "sslerr.h"
18
19 #define PK11_SEARCH_CHUNKSIZE 10
20
21 /*
22 * Build a block big enough to hold the data
23 */
24 SECItem *
25 PK11_BlockData(SECItem *data,unsigned long size) {
26 SECItem *newData;
27
28 newData = (SECItem *)PORT_Alloc(sizeof(SECItem));
29 if (newData == NULL) return NULL;
30
31 newData->len = (data->len + (size-1))/size;
32 newData->len *= size;
33
34 newData->data = (unsigned char *) PORT_ZAlloc(newData->len);
35 if (newData->data == NULL) {
36 PORT_Free(newData);
37 return NULL;
38 }
39 PORT_Memset(newData->data,newData->len-data->len,newData->len);
40 PORT_Memcpy(newData->data,data->data,data->len);
41 return newData;
42 }
43
44
45 SECStatus
46 PK11_DestroyObject(PK11SlotInfo *slot,CK_OBJECT_HANDLE object) {
47 CK_RV crv;
48
49 PK11_EnterSlotMonitor(slot);
50 crv = PK11_GETTAB(slot)->C_DestroyObject(slot->session,object);
51 PK11_ExitSlotMonitor(slot);
52 if (crv != CKR_OK) {
53 return SECFailure;
54 }
55 return SECSuccess;
56 }
57
58 SECStatus
59 PK11_DestroyTokenObject(PK11SlotInfo *slot,CK_OBJECT_HANDLE object) {
60 CK_RV crv;
61 SECStatus rv = SECSuccess;
62 CK_SESSION_HANDLE rwsession;
63
64
65 rwsession = PK11_GetRWSession(slot);
66 if (rwsession == CK_INVALID_SESSION) {
67 PORT_SetError(SEC_ERROR_BAD_DATA);
68 return SECFailure;
69 }
70
71 crv = PK11_GETTAB(slot)->C_DestroyObject(rwsession,object);
72 if (crv != CKR_OK) {
73 rv = SECFailure;
74 PORT_SetError(PK11_MapError(crv));
75 }
76 PK11_RestoreROSession(slot,rwsession);
77 return rv;
78 }
79
80 /*
81 * Read in a single attribute into a SECItem. Allocate space for it with
82 * PORT_Alloc unless an arena is supplied. In the latter case use the arena
83 * to allocate the space.
84 *
85 * PK11_ReadAttribute sets the 'data' and 'len' fields of the SECItem but
86 * does not modify its 'type' field.
87 */
88 SECStatus
89 PK11_ReadAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
90 CK_ATTRIBUTE_TYPE type, PLArenaPool *arena, SECItem *result) {
91 CK_ATTRIBUTE attr = { 0, NULL, 0 };
92 CK_RV crv;
93
94 attr.type = type;
95
96 PK11_EnterSlotMonitor(slot);
97 crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,id,&attr,1);
98 if (crv != CKR_OK) {
99 PK11_ExitSlotMonitor(slot);
100 PORT_SetError(PK11_MapError(crv));
101 return SECFailure;
102 }
103 if (arena) {
104 attr.pValue = PORT_ArenaAlloc(arena,attr.ulValueLen);
105 } else {
106 attr.pValue = PORT_Alloc(attr.ulValueLen);
107 }
108 if (attr.pValue == NULL) {
109 PK11_ExitSlotMonitor(slot);
110 return SECFailure;
111 }
112 crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,id,&attr,1);
113 PK11_ExitSlotMonitor(slot);
114 if (crv != CKR_OK) {
115 PORT_SetError(PK11_MapError(crv));
116 if (!arena) PORT_Free(attr.pValue);
117 return SECFailure;
118 }
119
120 result->data = (unsigned char*)attr.pValue;
121 result->len = attr.ulValueLen;
122
123 return SECSuccess;
124 }
125
126 /*
127 * Read in a single attribute into As a Ulong.
128 */
129 CK_ULONG
130 PK11_ReadULongAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
131 CK_ATTRIBUTE_TYPE type) {
132 CK_ATTRIBUTE attr;
133 CK_ULONG value = CK_UNAVAILABLE_INFORMATION;
134 CK_RV crv;
135
136 PK11_SETATTRS(&attr,type,&value,sizeof(value));
137
138 PK11_EnterSlotMonitor(slot);
139 crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,id,&attr,1);
140 PK11_ExitSlotMonitor(slot);
141 if (crv != CKR_OK) {
142 PORT_SetError(PK11_MapError(crv));
143 }
144 return value;
145 }
146
147 /*
148 * check to see if a bool has been set.
149 */
150 CK_BBOOL
151 PK11_HasAttributeSet( PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
152 CK_ATTRIBUTE_TYPE type, PRBool haslock )
153 {
154 CK_BBOOL ckvalue = CK_FALSE;
155 CK_ATTRIBUTE theTemplate;
156 CK_RV crv;
157
158 /* Prepare to retrieve the attribute. */
159 PK11_SETATTRS( &theTemplate, type, &ckvalue, sizeof( CK_BBOOL ) );
160
161 /* Retrieve attribute value. */
162 if (!haslock) PK11_EnterSlotMonitor(slot);
163 crv = PK11_GETTAB( slot )->C_GetAttributeValue( slot->session, id,
164 &theTemplate, 1 );
165 if (!haslock) PK11_ExitSlotMonitor(slot);
166 if( crv != CKR_OK ) {
167 PORT_SetError( PK11_MapError( crv ) );
168 return CK_FALSE;
169 }
170
171 return ckvalue;
172 }
173
174 /*
175 * returns a full list of attributes. Allocate space for them. If an arena is
176 * provided, allocate space out of the arena.
177 */
178 CK_RV
179 PK11_GetAttributes(PLArenaPool *arena,PK11SlotInfo *slot,
180 CK_OBJECT_HANDLE obj,CK_ATTRIBUTE *attr, int count)
181 {
182 int i;
183 /* make pedantic happy... note that it's only used arena != NULL */
184 void *mark = NULL;
185 CK_RV crv;
186 PORT_Assert(slot->session != CK_INVALID_SESSION);
187 if (slot->session == CK_INVALID_SESSION)
188 return CKR_SESSION_HANDLE_INVALID;
189
190 /*
191 * first get all the lengths of the parameters.
192 */
193 PK11_EnterSlotMonitor(slot);
194 crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,obj,attr,count);
195 if (crv != CKR_OK) {
196 PK11_ExitSlotMonitor(slot);
197 return crv;
198 }
199
200 if (arena) {
201 mark = PORT_ArenaMark(arena);
202 if (mark == NULL) return CKR_HOST_MEMORY;
203 }
204
205 /*
206 * now allocate space to store the results.
207 */
208 for (i=0; i < count; i++) {
209 if (attr[i].ulValueLen == 0)
210 continue;
211 if (arena) {
212 attr[i].pValue = PORT_ArenaAlloc(arena,attr[i].ulValueLen);
213 if (attr[i].pValue == NULL) {
214 /* arena failures, just release the mark */
215 PORT_ArenaRelease(arena,mark);
216 PK11_ExitSlotMonitor(slot);
217 return CKR_HOST_MEMORY;
218 }
219 } else {
220 attr[i].pValue = PORT_Alloc(attr[i].ulValueLen);
221 if (attr[i].pValue == NULL) {
222 /* Separate malloc failures, loop to release what we have
223 * so far */
224 int j;
225 for (j= 0; j < i; j++) {
226 PORT_Free(attr[j].pValue);
227 /* don't give the caller pointers to freed memory */
228 attr[j].pValue = NULL;
229 }
230 PK11_ExitSlotMonitor(slot);
231 return CKR_HOST_MEMORY;
232 }
233 }
234 }
235
236 /*
237 * finally get the results.
238 */
239 crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,obj,attr,count);
240 PK11_ExitSlotMonitor(slot);
241 if (crv != CKR_OK) {
242 if (arena) {
243 PORT_ArenaRelease(arena,mark);
244 } else {
245 for (i= 0; i < count; i++) {
246 PORT_Free(attr[i].pValue);
247 /* don't give the caller pointers to freed memory */
248 attr[i].pValue = NULL;
249 }
250 }
251 } else if (arena && mark) {
252 PORT_ArenaUnmark(arena,mark);
253 }
254 return crv;
255 }
256
257 PRBool
258 PK11_IsPermObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle)
259 {
260 return (PRBool) PK11_HasAttributeSet(slot, handle, CKA_TOKEN, PR_FALSE);
261 }
262
263 char *
264 PK11_GetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id)
265 {
266 char *nickname = NULL;
267 SECItem result;
268 SECStatus rv;
269
270 rv = PK11_ReadAttribute(slot,id,CKA_LABEL,NULL,&result);
271 if (rv != SECSuccess) {
272 return NULL;
273 }
274
275 nickname = PORT_ZAlloc(result.len+1);
276 if (nickname == NULL) {
277 PORT_Free(result.data);
278 return NULL;
279 }
280 PORT_Memcpy(nickname, result.data, result.len);
281 PORT_Free(result.data);
282 return nickname;
283 }
284
285 SECStatus
286 PK11_SetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
287 const char *nickname)
288 {
289 int len = PORT_Strlen(nickname);
290 CK_ATTRIBUTE setTemplate;
291 CK_RV crv;
292 CK_SESSION_HANDLE rwsession;
293
294 if (len < 0) {
295 return SECFailure;
296 }
297
298 PK11_SETATTRS(&setTemplate, CKA_LABEL, (CK_CHAR *) nickname, len);
299 rwsession = PK11_GetRWSession(slot);
300 if (rwsession == CK_INVALID_SESSION) {
301 PORT_SetError(SEC_ERROR_BAD_DATA);
302 return SECFailure;
303 }
304 crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession, id,
305 &setTemplate, 1);
306 PK11_RestoreROSession(slot, rwsession);
307 if (crv != CKR_OK) {
308 PORT_SetError(PK11_MapError(crv));
309 return SECFailure;
310 }
311 return SECSuccess;
312 }
313
314 /*
315 * strip leading zero's from key material
316 */
317 void
318 pk11_SignedToUnsigned(CK_ATTRIBUTE *attrib) {
319 char *ptr = (char *)attrib->pValue;
320 unsigned long len = attrib->ulValueLen;
321
322 while ((len > 1) && (*ptr == 0)) {
323 len--;
324 ptr++;
325 }
326 attrib->pValue = ptr;
327 attrib->ulValueLen = len;
328 }
329
330 /*
331 * get a new session on a slot. If we run out of session, use the slot's
332 * 'exclusive' session. In this case owner becomes false.
333 */
334 CK_SESSION_HANDLE
335 pk11_GetNewSession(PK11SlotInfo *slot,PRBool *owner)
336 {
337 CK_SESSION_HANDLE session;
338 *owner = PR_TRUE;
339 if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
340 if ( PK11_GETTAB(slot)->C_OpenSession(slot->slotID,CKF_SERIAL_SESSION,
341 slot,pk11_notify,&session) != CKR_OK) {
342 *owner = PR_FALSE;
343 session = slot->session;
344 }
345 if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
346
347 return session;
348 }
349
350 void
351 pk11_CloseSession(PK11SlotInfo *slot,CK_SESSION_HANDLE session,PRBool owner)
352 {
353 if (!owner) return;
354 if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
355 (void) PK11_GETTAB(slot)->C_CloseSession(session);
356 if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
357 }
358
359
360 SECStatus
361 PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
362 const CK_ATTRIBUTE *theTemplate, int count,
363 PRBool token, CK_OBJECT_HANDLE *objectID)
364 {
365 CK_SESSION_HANDLE rwsession;
366 CK_RV crv;
367 SECStatus rv = SECSuccess;
368
369 rwsession = session;
370 if (token) {
371 rwsession = PK11_GetRWSession(slot);
372 } else if (rwsession == CK_INVALID_SESSION) {
373 rwsession = slot->session;
374 if (rwsession != CK_INVALID_SESSION)
375 PK11_EnterSlotMonitor(slot);
376 }
377 if (rwsession == CK_INVALID_SESSION) {
378 PORT_SetError(SEC_ERROR_BAD_DATA);
379 return SECFailure;
380 }
381 crv = PK11_GETTAB(slot)->C_CreateObject(rwsession,
382 /* cast away const :-( */ (CK_ATTRIBUTE_PTR)theTemplate,
383 count, objectID);
384 if(crv != CKR_OK) {
385 PORT_SetError( PK11_MapError(crv) );
386 rv = SECFailure;
387 }
388 if (token) {
389 PK11_RestoreROSession(slot, rwsession);
390 } else if (session == CK_INVALID_SESSION) {
391 PK11_ExitSlotMonitor(slot);
392 }
393
394 return rv;
395 }
396
397
398 /* This function may add a maximum of 9 attributes. */
399 unsigned int
400 pk11_OpFlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue)
401 {
402
403 const static CK_ATTRIBUTE_TYPE attrTypes[12] = {
404 CKA_ENCRYPT, CKA_DECRYPT, 0 /* DIGEST */, CKA_SIGN,
405 CKA_SIGN_RECOVER, CKA_VERIFY, CKA_VERIFY_RECOVER, 0 /* GEN */,
406 0 /* GEN PAIR */, CKA_WRAP, CKA_UNWRAP, CKA_DERIVE
407 };
408
409 const CK_ATTRIBUTE_TYPE *pType = attrTypes;
410 CK_ATTRIBUTE *attr = attrs;
411 CK_FLAGS test = CKF_ENCRYPT;
412
413
414 PR_ASSERT(!(flags & ~CKF_KEY_OPERATION_FLAGS));
415 flags &= CKF_KEY_OPERATION_FLAGS;
416
417 for (; flags && test <= CKF_DERIVE; test <<= 1, ++pType) {
418 if (test & flags) {
419 flags ^= test;
420 PR_ASSERT(*pType);
421 PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue);
422 ++attr;
423 }
424 }
425 return (attr - attrs);
426 }
427
428 /*
429 * Check for conflicting flags, for example, if both PK11_ATTR_PRIVATE
430 * and PK11_ATTR_PUBLIC are set.
431 */
432 PRBool
433 pk11_BadAttrFlags(PK11AttrFlags attrFlags)
434 {
435 PK11AttrFlags trueFlags = attrFlags & 0x55555555;
436 PK11AttrFlags falseFlags = (attrFlags >> 1) & 0x55555555;
437 return ((trueFlags & falseFlags) != 0);
438 }
439
440 /*
441 * This function may add a maximum of 5 attributes.
442 * The caller must make sure the attribute flags don't have conflicts.
443 */
444 unsigned int
445 pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags, CK_ATTRIBUTE *attrs,
446 CK_BBOOL *ckTrue, CK_BBOOL *ckFalse)
447 {
448 const static CK_ATTRIBUTE_TYPE attrTypes[5] = {
449 CKA_TOKEN, CKA_PRIVATE, CKA_MODIFIABLE, CKA_SENSITIVE,
450 CKA_EXTRACTABLE
451 };
452
453 const CK_ATTRIBUTE_TYPE *pType = attrTypes;
454 CK_ATTRIBUTE *attr = attrs;
455 PK11AttrFlags test = PK11_ATTR_TOKEN;
456
457 PR_ASSERT(!pk11_BadAttrFlags(attrFlags));
458
459 /* we test two related bitflags in each iteration */
460 for (; attrFlags && test <= PK11_ATTR_EXTRACTABLE; test <<= 2, ++pType) {
461 if (test & attrFlags) {
462 attrFlags ^= test;
463 PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue);
464 ++attr;
465 } else if ((test << 1) & attrFlags) {
466 attrFlags ^= (test << 1);
467 PK11_SETATTRS(attr, *pType, ckFalse, sizeof *ckFalse);
468 ++attr;
469 }
470 }
471 return (attr - attrs);
472 }
473
474 /*
475 * Some non-compliant PKCS #11 vendors do not give us the modulus, so actually
476 * set up a signature to get the signaure length.
477 */
478 static int
479 pk11_backupGetSignLength(SECKEYPrivateKey *key)
480 {
481 PK11SlotInfo *slot = key->pkcs11Slot;
482 CK_MECHANISM mech = {0, NULL, 0 };
483 PRBool owner = PR_TRUE;
484 CK_SESSION_HANDLE session;
485 CK_ULONG len;
486 CK_RV crv;
487 unsigned char h_data[20] = { 0 };
488 unsigned char buf[20]; /* obviously to small */
489 CK_ULONG smallLen = sizeof(buf);
490
491 mech.mechanism = PK11_MapSignKeyType(key->keyType);
492
493 session = pk11_GetNewSession(slot,&owner);
494 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
495 crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,key->pkcs11ID);
496 if (crv != CKR_OK) {
497 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
498 pk11_CloseSession(slot,session,owner);
499 PORT_SetError( PK11_MapError(crv) );
500 return -1;
501 }
502 len = 0;
503 crv = PK11_GETTAB(slot)->C_Sign(session,h_data,sizeof(h_data),
504 NULL, &len);
505 /* now call C_Sign with too small a buffer to clear the session state */
506 (void) PK11_GETTAB(slot)->
507 C_Sign(session,h_data,sizeof(h_data),buf,&smallLen);
508
509 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
510 pk11_CloseSession(slot,session,owner);
511 if (crv != CKR_OK) {
512 PORT_SetError( PK11_MapError(crv) );
513 return -1;
514 }
515 return len;
516 }
517
518 /*
519 * get the length of a signature object based on the key
520 */
521 int
522 PK11_SignatureLen(SECKEYPrivateKey *key)
523 {
524 int val;
525 SECItem attributeItem = {siBuffer, NULL, 0};
526 SECStatus rv;
527 int length;
528
529 switch (key->keyType) {
530 case rsaKey:
531 val = PK11_GetPrivateModulusLen(key);
532 if (val == -1) {
533 return pk11_backupGetSignLength(key);
534 }
535 return (unsigned long) val;
536
537 case fortezzaKey:
538 return 40;
539
540 case dsaKey:
541 rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, CKA_SUBPRIME,
542 NULL, &attributeItem);
543 if (rv == SECSuccess) {
544 length = attributeItem.len;
545 if ((length > 0) && attributeItem.data[0] == 0) {
546 length--;
547 }
548 PORT_Free(attributeItem.data);
549 return length*2;
550 }
551 return pk11_backupGetSignLength(key);
552
553 case ecKey:
554 rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, CKA_EC_PARAMS,
555 NULL, &attributeItem);
556 if (rv == SECSuccess) {
557 length = SECKEY_ECParamsToBasePointOrderLen(&attributeItem);
558 PORT_Free(attributeItem.data);
559 if (length != 0) {
560 length = ((length + 7)/8) * 2;
561 return length;
562 }
563 }
564 return pk11_backupGetSignLength(key);
565 default:
566 break;
567 }
568 PORT_SetError( SEC_ERROR_INVALID_KEY );
569 return 0;
570 }
571
572 /*
573 * copy a key (or any other object) on a token
574 */
575 CK_OBJECT_HANDLE
576 PK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject)
577 {
578 CK_OBJECT_HANDLE destObject;
579 CK_RV crv;
580
581 PK11_EnterSlotMonitor(slot);
582 crv = PK11_GETTAB(slot)->C_CopyObject(slot->session,srcObject,NULL,0,
583 &destObject);
584 PK11_ExitSlotMonitor(slot);
585 if (crv == CKR_OK) return destObject;
586 PORT_SetError( PK11_MapError(crv) );
587 return CK_INVALID_HANDLE;
588 }
589
590 PRBool
591 pk11_FindAttrInTemplate(CK_ATTRIBUTE *attr, unsigned int numAttrs,
592 CK_ATTRIBUTE_TYPE target)
593 {
594 for (; numAttrs > 0; ++attr, --numAttrs) {
595 if (attr->type == target)
596 return PR_TRUE;
597 }
598 return PR_FALSE;
599 }
600
601 /*
602 * Recover the Signed data. We need this because our old verify can't
603 * figure out which hash algorithm to use until we decryptted this.
604 */
605 SECStatus
606 PK11_VerifyRecover(SECKEYPublicKey *key, const SECItem *sig,
607 SECItem *dsig, void *wincx)
608 {
609 PK11SlotInfo *slot = key->pkcs11Slot;
610 CK_OBJECT_HANDLE id = key->pkcs11ID;
611 CK_MECHANISM mech = {0, NULL, 0 };
612 PRBool owner = PR_TRUE;
613 CK_SESSION_HANDLE session;
614 CK_ULONG len;
615 CK_RV crv;
616
617 mech.mechanism = PK11_MapSignKeyType(key->keyType);
618
619 if (slot == NULL) {
620 slot = PK11_GetBestSlotWithAttributes(mech.mechanism,
621 CKF_VERIFY_RECOVER,0,wincx);
622 if (slot == NULL) {
623 PORT_SetError( SEC_ERROR_NO_MODULE );
624 return SECFailure;
625 }
626 id = PK11_ImportPublicKey(slot,key,PR_FALSE);
627 } else {
628 PK11_ReferenceSlot(slot);
629 }
630
631 if (id == CK_INVALID_HANDLE) {
632 PK11_FreeSlot(slot);
633 PORT_SetError( SEC_ERROR_BAD_KEY );
634 return SECFailure;
635 }
636
637 session = pk11_GetNewSession(slot,&owner);
638 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
639 crv = PK11_GETTAB(slot)->C_VerifyRecoverInit(session,&mech,id);
640 if (crv != CKR_OK) {
641 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
642 pk11_CloseSession(slot,session,owner);
643 PORT_SetError( PK11_MapError(crv) );
644 PK11_FreeSlot(slot);
645 return SECFailure;
646 }
647 len = dsig->len;
648 crv = PK11_GETTAB(slot)->C_VerifyRecover(session,sig->data,
649 sig->len, dsig->data, &len);
650 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
651 pk11_CloseSession(slot,session,owner);
652 dsig->len = len;
653 if (crv != CKR_OK) {
654 PORT_SetError( PK11_MapError(crv) );
655 PK11_FreeSlot(slot);
656 return SECFailure;
657 }
658 PK11_FreeSlot(slot);
659 return SECSuccess;
660 }
661
662 /*
663 * verify a signature from its hash.
664 */
665 SECStatus
666 PK11_Verify(SECKEYPublicKey *key, const SECItem *sig, const SECItem *hash,
667 void *wincx)
668 {
669 PK11SlotInfo *slot = key->pkcs11Slot;
670 CK_OBJECT_HANDLE id = key->pkcs11ID;
671 CK_MECHANISM mech = {0, NULL, 0 };
672 PRBool owner = PR_TRUE;
673 CK_SESSION_HANDLE session;
674 CK_RV crv;
675
676 mech.mechanism = PK11_MapSignKeyType(key->keyType);
677
678 if (slot == NULL) {
679 unsigned int length = 0;
680 if ((mech.mechanism == CKM_DSA) &&
681 /* 129 is 1024 bits translated to bytes and
682 * padded with an optional '0' to maintain a
683 * positive sign */
684 (key->u.dsa.params.prime.len > 129)) {
685 /* we need to get a slot that not only can do DSA, but can do DSA2
686 * key lengths */
687 length = key->u.dsa.params.prime.len;
688 if (key->u.dsa.params.prime.data[0] == 0) {
689 length --;
690 }
691 /* convert keysize to bits for slot lookup */
692 length *= 8;
693 }
694 slot = PK11_GetBestSlotWithAttributes(mech.mechanism,
695 CKF_VERIFY,length,wincx);
696 if (slot == NULL) {
697 PORT_SetError( SEC_ERROR_NO_MODULE );
698 return SECFailure;
699 }
700 id = PK11_ImportPublicKey(slot,key,PR_FALSE);
701
702 } else {
703 PK11_ReferenceSlot(slot);
704 }
705
706 if (id == CK_INVALID_HANDLE) {
707 PK11_FreeSlot(slot);
708 PORT_SetError( SEC_ERROR_BAD_KEY );
709 return SECFailure;
710 }
711
712 session = pk11_GetNewSession(slot,&owner);
713 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
714 crv = PK11_GETTAB(slot)->C_VerifyInit(session,&mech,id);
715 if (crv != CKR_OK) {
716 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
717 pk11_CloseSession(slot,session,owner);
718 PK11_FreeSlot(slot);
719 PORT_SetError( PK11_MapError(crv) );
720 return SECFailure;
721 }
722 crv = PK11_GETTAB(slot)->C_Verify(session,hash->data,
723 hash->len, sig->data, sig->len);
724 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
725 pk11_CloseSession(slot,session,owner);
726 PK11_FreeSlot(slot);
727 if (crv != CKR_OK) {
728 PORT_SetError( PK11_MapError(crv) );
729 return SECFailure;
730 }
731 return SECSuccess;
732 }
733
734 /*
735 * sign a hash. The algorithm is determined by the key.
736 */
737 SECStatus
738 PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, const SECItem *hash)
739 {
740 PK11SlotInfo *slot = key->pkcs11Slot;
741 CK_MECHANISM mech = {0, NULL, 0 };
742 PRBool owner = PR_TRUE;
743 CK_SESSION_HANDLE session;
744 PRBool haslock = PR_FALSE;
745 CK_ULONG len;
746 CK_RV crv;
747
748 mech.mechanism = PK11_MapSignKeyType(key->keyType);
749
750 if (SECKEY_HAS_ATTRIBUTE_SET(key,CKA_PRIVATE)) {
751 PK11_HandlePasswordCheck(slot, key->wincx);
752 }
753
754 session = pk11_GetNewSession(slot,&owner);
755 haslock = (!owner || !(slot->isThreadSafe));
756 if (haslock) PK11_EnterSlotMonitor(slot);
757 crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,key->pkcs11ID);
758 if (crv != CKR_OK) {
759 if (haslock) PK11_ExitSlotMonitor(slot);
760 pk11_CloseSession(slot,session,owner);
761 PORT_SetError( PK11_MapError(crv) );
762 return SECFailure;
763 }
764
765 /* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then
766 * do C_Login with CKU_CONTEXT_SPECIFIC
767 * between C_SignInit and C_Sign */
768 if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)) {
769 PK11_DoPassword(slot, session, PR_FALSE, key->wincx, haslock, PR_TRUE);
770 }
771
772 len = sig->len;
773 crv = PK11_GETTAB(slot)->C_Sign(session,hash->data,
774 hash->len, sig->data, &len);
775 if (haslock) PK11_ExitSlotMonitor(slot);
776 pk11_CloseSession(slot,session,owner);
777 sig->len = len;
778 if (crv != CKR_OK) {
779 PORT_SetError( PK11_MapError(crv) );
780 return SECFailure;
781 }
782 return SECSuccess;
783 }
784
785 /*
786 * sign data with a MAC key.
787 */
788 SECStatus
789 PK11_SignWithSymKey(PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism,
790 SECItem *param, SECItem *sig, const SECItem *data)
791 {
792 PK11SlotInfo *slot = symKey->slot;
793 CK_MECHANISM mech = {0, NULL, 0 };
794 PRBool owner = PR_TRUE;
795 CK_SESSION_HANDLE session;
796 PRBool haslock = PR_FALSE;
797 CK_ULONG len;
798 CK_RV crv;
799
800 mech.mechanism = mechanism;
801 if (param) {
802 mech.pParameter = param->data;
803 mech.ulParameterLen = param->len;
804 }
805
806 session = pk11_GetNewSession(slot,&owner);
807 haslock = (!owner || !(slot->isThreadSafe));
808 if (haslock) PK11_EnterSlotMonitor(slot);
809 crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,symKey->objectID);
810 if (crv != CKR_OK) {
811 if (haslock) PK11_ExitSlotMonitor(slot);
812 pk11_CloseSession(slot,session,owner);
813 PORT_SetError( PK11_MapError(crv) );
814 return SECFailure;
815 }
816
817 len = sig->len;
818 crv = PK11_GETTAB(slot)->C_Sign(session,data->data,
819 data->len, sig->data, &len);
820 if (haslock) PK11_ExitSlotMonitor(slot);
821 pk11_CloseSession(slot,session,owner);
822 sig->len = len;
823 if (crv != CKR_OK) {
824 PORT_SetError( PK11_MapError(crv) );
825 return SECFailure;
826 }
827 return SECSuccess;
828 }
829
830 SECStatus
831 PK11_Decrypt(PK11SymKey *symKey,
832 CK_MECHANISM_TYPE mechanism, SECItem *param,
833 unsigned char *out, unsigned int *outLen,
834 unsigned int maxLen,
835 const unsigned char *enc, unsigned encLen)
836 {
837 PK11SlotInfo *slot = symKey->slot;
838 CK_MECHANISM mech = {0, NULL, 0 };
839 CK_ULONG len = maxLen;
840 PRBool owner = PR_TRUE;
841 CK_SESSION_HANDLE session;
842 PRBool haslock = PR_FALSE;
843 CK_RV crv;
844
845 mech.mechanism = mechanism;
846 if (param) {
847 mech.pParameter = param->data;
848 mech.ulParameterLen = param->len;
849 }
850
851 session = pk11_GetNewSession(slot, &owner);
852 haslock = (!owner || !slot->isThreadSafe);
853 if (haslock) PK11_EnterSlotMonitor(slot);
854 crv = PK11_GETTAB(slot)->C_DecryptInit(session, &mech, symKey->objectID);
855 if (crv != CKR_OK) {
856 if (haslock) PK11_ExitSlotMonitor(slot);
857 pk11_CloseSession(slot, session, owner);
858 PORT_SetError( PK11_MapError(crv) );
859 return SECFailure;
860 }
861
862 crv = PK11_GETTAB(slot)->C_Decrypt(session, (unsigned char *)enc, encLen,
863 out, &len);
864 if (haslock) PK11_ExitSlotMonitor(slot);
865 pk11_CloseSession(slot, session, owner);
866 *outLen = len;
867 if (crv != CKR_OK) {
868 PORT_SetError( PK11_MapError(crv) );
869 return SECFailure;
870 }
871 return SECSuccess;
872 }
873
874 SECStatus
875 PK11_Encrypt(PK11SymKey *symKey,
876 CK_MECHANISM_TYPE mechanism, SECItem *param,
877 unsigned char *out, unsigned int *outLen,
878 unsigned int maxLen,
879 const unsigned char *data, unsigned int dataLen)
880 {
881 PK11SlotInfo *slot = symKey->slot;
882 CK_MECHANISM mech = {0, NULL, 0 };
883 CK_ULONG len = maxLen;
884 PRBool owner = PR_TRUE;
885 CK_SESSION_HANDLE session;
886 PRBool haslock = PR_FALSE;
887 CK_RV crv;
888
889 mech.mechanism = mechanism;
890 if (param) {
891 mech.pParameter = param->data;
892 mech.ulParameterLen = param->len;
893 }
894
895 session = pk11_GetNewSession(slot, &owner);
896 haslock = (!owner || !slot->isThreadSafe);
897 if (haslock) PK11_EnterSlotMonitor(slot);
898 crv = PK11_GETTAB(slot)->C_EncryptInit(session, &mech, symKey->objectID);
899 if (crv != CKR_OK) {
900 if (haslock) PK11_ExitSlotMonitor(slot);
901 pk11_CloseSession(slot,session,owner);
902 PORT_SetError( PK11_MapError(crv) );
903 return SECFailure;
904 }
905 crv = PK11_GETTAB(slot)->C_Encrypt(session, (unsigned char *)data,
906 dataLen, out, &len);
907 if (haslock) PK11_ExitSlotMonitor(slot);
908 pk11_CloseSession(slot,session,owner);
909 *outLen = len;
910 if (crv != CKR_OK) {
911 PORT_SetError( PK11_MapError(crv) );
912 return SECFailure;
913 }
914 return SECSuccess;
915 }
916
917 static SECStatus
918 pk11_PrivDecryptRaw(SECKEYPrivateKey *key,
919 unsigned char *data, unsigned *outLen, unsigned int maxLen,
920 const unsigned char *enc, unsigned encLen,
921 CK_MECHANISM_PTR mech)
922 {
923 PK11SlotInfo *slot = key->pkcs11Slot;
924 CK_ULONG out = maxLen;
925 PRBool owner = PR_TRUE;
926 CK_SESSION_HANDLE session;
927 PRBool haslock = PR_FALSE;
928 CK_RV crv;
929
930 if (key->keyType != rsaKey) {
931 PORT_SetError( SEC_ERROR_INVALID_KEY );
932 return SECFailure;
933 }
934
935 /* Why do we do a PK11_handle check here? for simple
936 * decryption? .. because the user may have asked for 'ask always'
937 * and this is a private key operation. In practice, thought, it's mute
938 * since only servers wind up using this function */
939 if (SECKEY_HAS_ATTRIBUTE_SET(key,CKA_PRIVATE)) {
940 PK11_HandlePasswordCheck(slot, key->wincx);
941 }
942 session = pk11_GetNewSession(slot,&owner);
943 haslock = (!owner || !(slot->isThreadSafe));
944 if (haslock) PK11_EnterSlotMonitor(slot);
945 crv = PK11_GETTAB(slot)->C_DecryptInit(session, mech, key->pkcs11ID);
946 if (crv != CKR_OK) {
947 if (haslock) PK11_ExitSlotMonitor(slot);
948 pk11_CloseSession(slot,session,owner);
949 PORT_SetError( PK11_MapError(crv) );
950 return SECFailure;
951 }
952
953 /* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then
954 * do C_Login with CKU_CONTEXT_SPECIFIC
955 * between C_DecryptInit and C_Decrypt
956 * ... But see note above about servers */
957 if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)) {
958 PK11_DoPassword(slot, session, PR_FALSE, key->wincx, haslock, PR_TRUE);
959 }
960
961 crv = PK11_GETTAB(slot)->C_Decrypt(session, (unsigned char *)enc, encLen,
962 data, &out);
963 if (haslock) PK11_ExitSlotMonitor(slot);
964 pk11_CloseSession(slot,session,owner);
965 *outLen = out;
966 if (crv != CKR_OK) {
967 PORT_SetError( PK11_MapError(crv) );
968 return SECFailure;
969 }
970 return SECSuccess;
971 }
972
973 SECStatus
974 PK11_PubDecryptRaw(SECKEYPrivateKey *key,
975 unsigned char *data, unsigned *outLen, unsigned int maxLen,
976 const unsigned char *enc, unsigned encLen)
977 {
978 CK_MECHANISM mech = {CKM_RSA_X_509, NULL, 0 };
979 return pk11_PrivDecryptRaw(key, data, outLen, maxLen, enc, encLen, &mech);
980 }
981
982 SECStatus
983 PK11_PrivDecryptPKCS1(SECKEYPrivateKey *key,
984 unsigned char *data, unsigned *outLen, unsigned int maxLen,
985 const unsigned char *enc, unsigned encLen)
986 {
987 CK_MECHANISM mech = {CKM_RSA_PKCS, NULL, 0 };
988 return pk11_PrivDecryptRaw(key, data, outLen, maxLen, enc, encLen, &mech);
989 }
990
991 static SECStatus
992 pk11_PubEncryptRaw(SECKEYPublicKey *key,
993 unsigned char *out, unsigned int *outLen,
994 unsigned int maxLen,
995 const unsigned char *data, unsigned dataLen,
996 CK_MECHANISM_PTR mech, void *wincx)
997 {
998 PK11SlotInfo *slot;
999 CK_OBJECT_HANDLE id;
1000 CK_ULONG len = maxLen;
1001 PRBool owner = PR_TRUE;
1002 CK_SESSION_HANDLE session;
1003 CK_RV crv;
1004
1005 slot = PK11_GetBestSlotWithAttributes(mech->mechanism,CKF_ENCRYPT,0,wincx);
1006 if (slot == NULL) {
1007 PORT_SetError( SEC_ERROR_NO_MODULE );
1008 return SECFailure;
1009 }
1010
1011 id = PK11_ImportPublicKey(slot,key,PR_FALSE);
1012
1013 if (id == CK_INVALID_HANDLE) {
1014 PK11_FreeSlot(slot);
1015 PORT_SetError( SEC_ERROR_BAD_KEY );
1016 return SECFailure;
1017 }
1018
1019 session = pk11_GetNewSession(slot,&owner);
1020 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
1021 crv = PK11_GETTAB(slot)->C_EncryptInit(session, mech, id);
1022 if (crv != CKR_OK) {
1023 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
1024 pk11_CloseSession(slot,session,owner);
1025 PK11_FreeSlot(slot);
1026 PORT_SetError( PK11_MapError(crv) );
1027 return SECFailure;
1028 }
1029 crv = PK11_GETTAB(slot)->C_Encrypt(session,(unsigned char *)data,dataLen,
1030 out,&len);
1031 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
1032 pk11_CloseSession(slot,session,owner);
1033 PK11_FreeSlot(slot);
1034 *outLen = len;
1035 if (crv != CKR_OK) {
1036 PORT_SetError( PK11_MapError(crv) );
1037 return SECFailure;
1038 }
1039 return SECSuccess;
1040 }
1041
1042 SECStatus
1043 PK11_PubEncryptRaw(SECKEYPublicKey *key,
1044 unsigned char *enc,
1045 const unsigned char *data, unsigned dataLen,
1046 void *wincx)
1047 {
1048 CK_MECHANISM mech = {CKM_RSA_X_509, NULL, 0 };
1049 unsigned int outLen;
1050 if (!key || key->keyType != rsaKey) {
1051 PORT_SetError(SEC_ERROR_BAD_KEY);
1052 return SECFailure;
1053 }
1054 outLen = SECKEY_PublicKeyStrength(key);
1055 return pk11_PubEncryptRaw(key, enc, &outLen, outLen, data, dataLen, &mech,
1056 wincx);
1057 }
1058
1059 SECStatus
1060 PK11_PubEncryptPKCS1(SECKEYPublicKey *key,
1061 unsigned char *enc,
1062 const unsigned char *data, unsigned dataLen,
1063 void *wincx)
1064 {
1065 CK_MECHANISM mech = {CKM_RSA_PKCS, NULL, 0 };
1066 unsigned int outLen;
1067 if (!key || key->keyType != rsaKey) {
1068 PORT_SetError(SEC_ERROR_BAD_KEY);
1069 return SECFailure;
1070 }
1071 outLen = SECKEY_PublicKeyStrength(key);
1072 return pk11_PubEncryptRaw(key, enc, &outLen, outLen, data, dataLen, &mech,
1073 wincx);
1074 }
1075
1076 SECStatus
1077 PK11_PrivDecrypt(SECKEYPrivateKey *key,
1078 CK_MECHANISM_TYPE mechanism, SECItem *param,
1079 unsigned char *out, unsigned int *outLen,
1080 unsigned int maxLen,
1081 const unsigned char *enc, unsigned encLen)
1082 {
1083 CK_MECHANISM mech = { mechanism, NULL, 0 };
1084 if (param) {
1085 mech.pParameter = param->data;
1086 mech.ulParameterLen = param->len;
1087 }
1088 return pk11_PrivDecryptRaw(key, out, outLen, maxLen, enc, encLen, &mech);
1089 }
1090
1091 SECStatus
1092 PK11_PubEncrypt(SECKEYPublicKey *key,
1093 CK_MECHANISM_TYPE mechanism, SECItem *param,
1094 unsigned char *out, unsigned int *outLen,
1095 unsigned int maxLen,
1096 const unsigned char *data, unsigned dataLen,
1097 void *wincx)
1098 {
1099 CK_MECHANISM mech = { mechanism, NULL, 0 };
1100 if (param) {
1101 mech.pParameter = param->data;
1102 mech.ulParameterLen = param->len;
1103 }
1104 return pk11_PubEncryptRaw(key, out, outLen, maxLen, data, dataLen, &mech,
1105 wincx);
1106 }
1107
1108 SECKEYPrivateKey *
1109 PK11_UnwrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey,
1110 CK_MECHANISM_TYPE wrapType, SECItem *param,
1111 SECItem *wrappedKey, SECItem *label,
1112 SECItem *idValue, PRBool perm, PRBool sensitive,
1113 CK_KEY_TYPE keyType, CK_ATTRIBUTE_TYPE *usage,
1114 int usageCount, void *wincx)
1115 {
1116 CK_BBOOL cktrue = CK_TRUE;
1117 CK_BBOOL ckfalse = CK_FALSE;
1118 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
1119 CK_ATTRIBUTE keyTemplate[15] ;
1120 int templateCount = 0;
1121 CK_OBJECT_HANDLE privKeyID;
1122 CK_MECHANISM mechanism;
1123 CK_ATTRIBUTE *attrs = keyTemplate;
1124 SECItem *param_free = NULL, *ck_id = NULL;
1125 CK_RV crv;
1126 CK_SESSION_HANDLE rwsession;
1127 PK11SymKey *newKey = NULL;
1128 int i;
1129
1130 if(!slot || !wrappedKey || !idValue) {
1131 /* SET AN ERROR!!! */
1132 return NULL;
1133 }
1134
1135 ck_id = PK11_MakeIDFromPubKey(idValue);
1136 if(!ck_id) {
1137 return NULL;
1138 }
1139
1140 PK11_SETATTRS(attrs, CKA_TOKEN, perm ? &cktrue : &ckfalse,
1141 sizeof(cktrue)); attrs++;
1142 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); attrs++;
1143 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); attrs++;
1144 PK11_SETATTRS(attrs, CKA_PRIVATE, sensitive ? &cktrue : &ckfalse,
1145 sizeof(cktrue)); attrs++;
1146 PK11_SETATTRS(attrs, CKA_SENSITIVE, sensitive ? &cktrue : &ckfalse,
1147 sizeof(cktrue)); attrs++;
1148 if (label && label->data) {
1149 PK11_SETATTRS(attrs, CKA_LABEL, label->data, label->len); attrs++;
1150 }
1151 PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len); attrs++;
1152 for (i=0; i < usageCount; i++) {
1153 PK11_SETATTRS(attrs, usage[i], &cktrue, sizeof(cktrue)); attrs++;
1154 }
1155
1156 if (PK11_IsInternal(slot)) {
1157 PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, idValue->data,
1158 idValue->len); attrs++;
1159 }
1160
1161 templateCount = attrs - keyTemplate;
1162 PR_ASSERT(templateCount <= (sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)) );
1163
1164 mechanism.mechanism = wrapType;
1165 if(!param) param = param_free= PK11_ParamFromIV(wrapType, NULL);
1166 if(param) {
1167 mechanism.pParameter = param->data;
1168 mechanism.ulParameterLen = param->len;
1169 } else {
1170 mechanism.pParameter = NULL;
1171 mechanism.ulParameterLen = 0;
1172 }
1173
1174 if (wrappingKey->slot != slot) {
1175 newKey = pk11_CopyToSlot(slot,wrapType,CKA_UNWRAP,wrappingKey);
1176 } else {
1177 newKey = PK11_ReferenceSymKey(wrappingKey);
1178 }
1179
1180 if (newKey) {
1181 if (perm) {
1182 /* Get RW Session will either lock the monitor if necessary,
1183 * or return a thread safe session handle, or fail. */
1184 rwsession = PK11_GetRWSession(slot);
1185 } else {
1186 rwsession = slot->session;
1187 if (rwsession != CK_INVALID_SESSION)
1188 PK11_EnterSlotMonitor(slot);
1189 }
1190 /* This is a lot a work to deal with fussy PKCS #11 modules
1191 * that can't bother to return BAD_DATA when presented with an
1192 * invalid session! */
1193 if (rwsession == CK_INVALID_SESSION) {
1194 PORT_SetError(SEC_ERROR_BAD_DATA);
1195 goto loser;
1196 }
1197 crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession, &mechanism,
1198 newKey->objectID,
1199 wrappedKey->data,
1200 wrappedKey->len, keyTemplate,
1201 templateCount, &privKeyID);
1202
1203 if (perm) {
1204 PK11_RestoreROSession(slot, rwsession);
1205 } else {
1206 PK11_ExitSlotMonitor(slot);
1207 }
1208 PK11_FreeSymKey(newKey);
1209 newKey = NULL;
1210 } else {
1211 crv = CKR_FUNCTION_NOT_SUPPORTED;
1212 }
1213
1214 if (ck_id) {
1215 SECITEM_FreeItem(ck_id, PR_TRUE);
1216 ck_id = NULL;
1217 }
1218
1219 if (crv != CKR_OK) {
1220 /* we couldn't unwrap the key, use the internal module to do the
1221 * unwrap, then load the new key into the token */
1222 PK11SlotInfo *int_slot = PK11_GetInternalSlot();
1223
1224 if (int_slot && (slot != int_slot)) {
1225 SECKEYPrivateKey *privKey = PK11_UnwrapPrivKey(int_slot,
1226 wrappingKey, wrapType, param, wrappedKey, label,
1227 idValue, PR_FALSE, PR_FALSE,
1228 keyType, usage, usageCount, wincx);
1229 if (privKey) {
1230 SECKEYPrivateKey *newPrivKey = PK11_LoadPrivKey(slot,privKey,
1231 NULL,perm,sensitive);
1232 SECKEY_DestroyPrivateKey(privKey);
1233 PK11_FreeSlot(int_slot);
1234 return newPrivKey;
1235 }
1236 }
1237 if (int_slot) PK11_FreeSlot(int_slot);
1238 PORT_SetError( PK11_MapError(crv) );
1239 return NULL;
1240 }
1241 return PK11_MakePrivKey(slot, nullKey, PR_FALSE, privKeyID, wincx);
1242
1243 loser:
1244 if (newKey) {
1245 PK11_FreeSymKey(newKey);
1246 }
1247 if (ck_id) {
1248 SECITEM_FreeItem(ck_id, PR_TRUE);
1249 }
1250 return NULL;
1251 }
1252
1253 /*
1254 * Now we're going to wrap a SECKEYPrivateKey with a PK11SymKey
1255 * The strategy is to get both keys to reside in the same slot,
1256 * one that can perform the desired crypto mechanism and then
1257 * call C_WrapKey after all the setup has taken place.
1258 */
1259 SECStatus
1260 PK11_WrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey,
1261 SECKEYPrivateKey *privKey, CK_MECHANISM_TYPE wrapType,
1262 SECItem *param, SECItem *wrappedKey, void *wincx)
1263 {
1264 PK11SlotInfo *privSlot = privKey->pkcs11Slot; /* The slot where
1265 * the private key
1266 * we are going to
1267 * wrap lives.
1268 */
1269 PK11SymKey *newSymKey = NULL;
1270 SECKEYPrivateKey *newPrivKey = NULL;
1271 SECItem *param_free = NULL;
1272 CK_ULONG len = wrappedKey->len;
1273 CK_MECHANISM mech;
1274 CK_RV crv;
1275
1276 if (!privSlot || !PK11_DoesMechanism(privSlot, wrapType)) {
1277 /* Figure out a slot that does the mechanism and try to import
1278 * the private key onto that slot.
1279 */
1280 PK11SlotInfo *int_slot = PK11_GetInternalSlot();
1281
1282 privSlot = int_slot; /* The private key has a new home */
1283 newPrivKey = PK11_LoadPrivKey(privSlot,privKey,NULL,PR_FALSE,PR_FALSE);
1284 /* newPrivKey has allocated its own reference to the slot, so it's
1285 * safe until we destroy newPrivkey.
1286 */
1287 PK11_FreeSlot(int_slot);
1288 if (newPrivKey == NULL) {
1289 return SECFailure;
1290 }
1291 privKey = newPrivKey;
1292 }
1293
1294 if (privSlot != wrappingKey->slot) {
1295 newSymKey = pk11_CopyToSlot (privSlot, wrapType, CKA_WRAP,
1296 wrappingKey);
1297 wrappingKey = newSymKey;
1298 }
1299
1300 if (wrappingKey == NULL) {
1301 if (newPrivKey) {
1302 SECKEY_DestroyPrivateKey(newPrivKey);
1303 }
1304 return SECFailure;
1305 }
1306 mech.mechanism = wrapType;
1307 if (!param) {
1308 param = param_free = PK11_ParamFromIV(wrapType, NULL);
1309 }
1310 if (param) {
1311 mech.pParameter = param->data;
1312 mech.ulParameterLen = param->len;
1313 } else {
1314 mech.pParameter = NULL;
1315 mech.ulParameterLen = 0;
1316 }
1317
1318 PK11_EnterSlotMonitor(privSlot);
1319 crv = PK11_GETTAB(privSlot)->C_WrapKey(privSlot->session, &mech,
1320 wrappingKey->objectID,
1321 privKey->pkcs11ID,
1322 wrappedKey->data, &len);
1323 PK11_ExitSlotMonitor(privSlot);
1324
1325 if (newSymKey) {
1326 PK11_FreeSymKey(newSymKey);
1327 }
1328 if (newPrivKey) {
1329 SECKEY_DestroyPrivateKey(newPrivKey);
1330 }
1331 if (param_free) {
1332 SECITEM_FreeItem(param_free,PR_TRUE);
1333 }
1334
1335 if (crv != CKR_OK) {
1336 PORT_SetError( PK11_MapError(crv) );
1337 return SECFailure;
1338 }
1339
1340 wrappedKey->len = len;
1341 return SECSuccess;
1342 }
1343
1344 #if 0
1345 /*
1346 * Sample code relating to linked list returned by PK11_FindGenericObjects
1347 */
1348
1349 /*
1350 * You can walk the list with the following code:
1351 */
1352 firstObj = PK11_FindGenericObjects(slot, objClass);
1353 for (thisObj=firstObj;
1354 thisObj;
1355 thisObj=PK11_GetNextGenericObject(thisObj)) {
1356 /* operate on thisObj */
1357 }
1358 /*
1359 * If you want a particular object from the list...
1360 */
1361 firstObj = PK11_FindGenericObjects(slot, objClass);
1362 for (thisObj=firstObj;
1363 thisObj;
1364 thisObj=PK11_GetNextGenericObject(thisObj)) {
1365 if (isMyObj(thisObj)) {
1366 if ( thisObj == firstObj) {
1367 /* NOTE: firstObj could be NULL at this point */
1368 firstObj = PK11_GetNextGenericObject(thsObj);
1369 }
1370 PK11_UnlinkGenericObject(thisObj);
1371 myObj = thisObj;
1372 break;
1373 }
1374 }
1375
1376 PK11_DestroyGenericObjects(firstObj);
1377
1378 /* use myObj */
1379
1380 PK11_DestroyGenericObject(myObj);
1381 #endif /* sample code */
1382
1383 /*
1384 * return a linked, non-circular list of generic objects.
1385 * If you are only interested
1386 * in one object, just use the first object in the list. To find the
1387 * rest of the list use PK11_GetNextGenericObject() to return the next object.
1388 */
1389 PK11GenericObject *
1390 PK11_FindGenericObjects(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass)
1391 {
1392 CK_ATTRIBUTE template[1];
1393 CK_ATTRIBUTE *attrs = template;
1394 CK_OBJECT_HANDLE *objectIDs = NULL;
1395 PK11GenericObject *lastObj = NULL, *obj;
1396 PK11GenericObject *firstObj = NULL;
1397 int i, count = 0;
1398
1399
1400 PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); attrs++;
1401
1402 objectIDs = pk11_FindObjectsByTemplate(slot,template,1,&count);
1403 if (objectIDs == NULL) {
1404 return NULL;
1405 }
1406
1407 /* where we connect our object once we've created it.. */
1408 for (i=0; i < count; i++) {
1409 obj = PORT_New(PK11GenericObject);
1410 if ( !obj ) {
1411 if (firstObj) {
1412 PK11_DestroyGenericObjects(firstObj);
1413 }
1414 PORT_Free(objectIDs);
1415 return NULL;
1416 }
1417 /* initialize it */
1418 obj->slot = PK11_ReferenceSlot(slot);
1419 obj->objectID = objectIDs[i];
1420 obj->next = NULL;
1421 obj->prev = NULL;
1422
1423 /* link it in */
1424 if (firstObj == NULL) {
1425 firstObj = obj;
1426 } else {
1427 PK11_LinkGenericObject(lastObj, obj);
1428 }
1429 lastObj = obj;
1430 }
1431 PORT_Free(objectIDs);
1432 return firstObj;
1433 }
1434
1435 /*
1436 * get the Next Object in the list.
1437 */
1438 PK11GenericObject *
1439 PK11_GetNextGenericObject(PK11GenericObject *object)
1440 {
1441 return object->next;
1442 }
1443
1444 PK11GenericObject *
1445 PK11_GetPrevGenericObject(PK11GenericObject *object)
1446 {
1447 return object->prev;
1448 }
1449
1450 /*
1451 * Link a single object into a new list.
1452 * if the object is already in another list, remove it first.
1453 */
1454 SECStatus
1455 PK11_LinkGenericObject(PK11GenericObject *list, PK11GenericObject *object)
1456 {
1457 PK11_UnlinkGenericObject(object);
1458 object->prev = list;
1459 object->next = list->next;
1460 list->next = object;
1461 if (object->next != NULL) {
1462 object->next->prev = object;
1463 }
1464 return SECSuccess;
1465 }
1466
1467 /*
1468 * remove an object from the list. If the object isn't already in
1469 * a list unlink becomes a noop.
1470 */
1471 SECStatus
1472 PK11_UnlinkGenericObject(PK11GenericObject *object)
1473 {
1474 if (object->prev != NULL) {
1475 object->prev->next = object->next;
1476 }
1477 if (object->next != NULL) {
1478 object->next->prev = object->prev;
1479 }
1480
1481 object->next = NULL;
1482 object->prev = NULL;
1483 return SECSuccess;
1484 }
1485
1486 /*
1487 * This function removes a single object from the list and destroys it.
1488 * For an already unlinked object there is no difference between
1489 * PK11_DestroyGenericObject and PK11_DestroyGenericObjects
1490 */
1491 SECStatus
1492 PK11_DestroyGenericObject(PK11GenericObject *object)
1493 {
1494 if (object == NULL) {
1495 return SECSuccess;
1496 }
1497
1498 PK11_UnlinkGenericObject(object);
1499 if (object->slot) {
1500 PK11_FreeSlot(object->slot);
1501 }
1502 PORT_Free(object);
1503 return SECSuccess;
1504 }
1505
1506 /*
1507 * walk down a link list of generic objects destroying them.
1508 * This will destroy all objects in a list that the object is linked into.
1509 * (the list is traversed in both directions).
1510 */
1511 SECStatus
1512 PK11_DestroyGenericObjects(PK11GenericObject *objects)
1513 {
1514 PK11GenericObject *nextObject;
1515 PK11GenericObject *prevObject;
1516
1517 if (objects == NULL) {
1518 return SECSuccess;
1519 }
1520
1521 nextObject = objects->next;
1522 prevObject = objects->prev;
1523
1524 /* delete all the objects after it in the list */
1525 for (; objects; objects = nextObject) {
1526 nextObject = objects->next;
1527 PK11_DestroyGenericObject(objects);
1528 }
1529 /* delete all the objects before it in the list */
1530 for (objects = prevObject; objects; objects = prevObject) {
1531 prevObject = objects->prev;
1532 PK11_DestroyGenericObject(objects);
1533 }
1534 return SECSuccess;
1535 }
1536
1537
1538 /*
1539 * Hand Create a new object and return the Generic object for our new object.
1540 */
1541 PK11GenericObject *
1542 PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
1543 int count, PRBool token)
1544 {
1545 CK_OBJECT_HANDLE objectID;
1546 PK11GenericObject *obj;
1547 CK_RV crv;
1548
1549 PK11_EnterSlotMonitor(slot);
1550 crv = PK11_CreateNewObject(slot, slot->session, pTemplate, count,
1551 token, &objectID);
1552 PK11_ExitSlotMonitor(slot);
1553 if (crv != CKR_OK) {
1554 PORT_SetError(PK11_MapError(crv));
1555 return NULL;
1556 }
1557
1558 obj = PORT_New(PK11GenericObject);
1559 if ( !obj ) {
1560 /* error set by PORT_New */
1561 return NULL;
1562 }
1563
1564 /* initialize it */
1565 obj->slot = PK11_ReferenceSlot(slot);
1566 obj->objectID = objectID;
1567 obj->next = NULL;
1568 obj->prev = NULL;
1569 return obj;
1570 }
1571
1572 /*
1573 * Change an attribute on a raw object
1574 */
1575 SECStatus
1576 PK11_WriteRawAttribute(PK11ObjectType objType, void *objSpec,
1577 CK_ATTRIBUTE_TYPE attrType, SECItem *item)
1578 {
1579 PK11SlotInfo *slot = NULL;
1580 CK_OBJECT_HANDLE handle;
1581 CK_ATTRIBUTE setTemplate;
1582 CK_RV crv;
1583 CK_SESSION_HANDLE rwsession;
1584
1585 switch (objType) {
1586 case PK11_TypeGeneric:
1587 slot = ((PK11GenericObject *)objSpec)->slot;
1588 handle = ((PK11GenericObject *)objSpec)->objectID;
1589 break;
1590 case PK11_TypePrivKey:
1591 slot = ((SECKEYPrivateKey *)objSpec)->pkcs11Slot;
1592 handle = ((SECKEYPrivateKey *)objSpec)->pkcs11ID;
1593 break;
1594 case PK11_TypePubKey:
1595 slot = ((SECKEYPublicKey *)objSpec)->pkcs11Slot;
1596 handle = ((SECKEYPublicKey *)objSpec)->pkcs11ID;
1597 break;
1598 case PK11_TypeSymKey:
1599 slot = ((PK11SymKey *)objSpec)->slot;
1600 handle = ((PK11SymKey *)objSpec)->objectID;
1601 break;
1602 case PK11_TypeCert: /* don't handle cert case for now */
1603 default:
1604 break;
1605 }
1606 if (slot == NULL) {
1607 PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
1608 return SECFailure;
1609 }
1610
1611 PK11_SETATTRS(&setTemplate, attrType, (CK_CHAR *) item->data, item->len);
1612 rwsession = PK11_GetRWSession(slot);
1613 if (rwsession == CK_INVALID_SESSION) {
1614 PORT_SetError(SEC_ERROR_BAD_DATA);
1615 return SECFailure;
1616 }
1617 crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession, handle,
1618 &setTemplate, 1);
1619 PK11_RestoreROSession(slot, rwsession);
1620 if (crv != CKR_OK) {
1621 PORT_SetError(PK11_MapError(crv));
1622 return SECFailure;
1623 }
1624 return SECSuccess;
1625 }
1626
1627
1628 SECStatus
1629 PK11_ReadRawAttribute(PK11ObjectType objType, void *objSpec,
1630 CK_ATTRIBUTE_TYPE attrType, SECItem *item)
1631 {
1632 PK11SlotInfo *slot = NULL;
1633 CK_OBJECT_HANDLE handle;
1634
1635 switch (objType) {
1636 case PK11_TypeGeneric:
1637 slot = ((PK11GenericObject *)objSpec)->slot;
1638 handle = ((PK11GenericObject *)objSpec)->objectID;
1639 break;
1640 case PK11_TypePrivKey:
1641 slot = ((SECKEYPrivateKey *)objSpec)->pkcs11Slot;
1642 handle = ((SECKEYPrivateKey *)objSpec)->pkcs11ID;
1643 break;
1644 case PK11_TypePubKey:
1645 slot = ((SECKEYPublicKey *)objSpec)->pkcs11Slot;
1646 handle = ((SECKEYPublicKey *)objSpec)->pkcs11ID;
1647 break;
1648 case PK11_TypeSymKey:
1649 slot = ((PK11SymKey *)objSpec)->slot;
1650 handle = ((PK11SymKey *)objSpec)->objectID;
1651 break;
1652 case PK11_TypeCert: /* don't handle cert case for now */
1653 default:
1654 break;
1655 }
1656 if (slot == NULL) {
1657 PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
1658 return SECFailure;
1659 }
1660
1661 return PK11_ReadAttribute(slot, handle, attrType, NULL, item);
1662 }
1663
1664
1665 /*
1666 * return the object handle that matches the template
1667 */
1668 CK_OBJECT_HANDLE
1669 pk11_FindObjectByTemplate(PK11SlotInfo *slot,CK_ATTRIBUTE *theTemplate,int tsize)
1670 {
1671 CK_OBJECT_HANDLE object;
1672 CK_RV crv = CKR_SESSION_HANDLE_INVALID;
1673 CK_ULONG objectCount;
1674
1675 /*
1676 * issue the find
1677 */
1678 PK11_EnterSlotMonitor(slot);
1679 if (slot->session != CK_INVALID_SESSION) {
1680 crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session,
1681 theTemplate, tsize);
1682 }
1683 if (crv != CKR_OK) {
1684 PK11_ExitSlotMonitor(slot);
1685 PORT_SetError( PK11_MapError(crv) );
1686 return CK_INVALID_HANDLE;
1687 }
1688
1689 crv=PK11_GETTAB(slot)->C_FindObjects(slot->session,&object,1,&objectCount);
1690 PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
1691 PK11_ExitSlotMonitor(slot);
1692 if ((crv != CKR_OK) || (objectCount < 1)) {
1693 /* shouldn't use SSL_ERROR... here */
1694 PORT_SetError( crv != CKR_OK ? PK11_MapError(crv) :
1695 SSL_ERROR_NO_CERTIFICATE);
1696 return CK_INVALID_HANDLE;
1697 }
1698
1699 /* blow up if the PKCS #11 module returns us and invalid object handle */
1700 PORT_Assert(object != CK_INVALID_HANDLE);
1701 return object;
1702 }
1703
1704 /*
1705 * return all the object handles that matches the template
1706 */
1707 CK_OBJECT_HANDLE *
1708 pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
1709 int templCount, int *object_count)
1710 {
1711 CK_OBJECT_HANDLE *objID = NULL;
1712 CK_ULONG returned_count = 0;
1713 CK_RV crv = CKR_SESSION_HANDLE_INVALID;
1714
1715 PK11_EnterSlotMonitor(slot);
1716 if (slot->session != CK_INVALID_SESSION) {
1717 crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session,
1718 findTemplate, templCount);
1719 }
1720 if (crv != CKR_OK) {
1721 PK11_ExitSlotMonitor(slot);
1722 PORT_SetError( PK11_MapError(crv) );
1723 *object_count = -1;
1724 return NULL;
1725 }
1726
1727
1728 /*
1729 * collect all the Matching Objects
1730 */
1731 do {
1732 CK_OBJECT_HANDLE *oldObjID = objID;
1733
1734 if (objID == NULL) {
1735 objID = (CK_OBJECT_HANDLE *) PORT_Alloc(sizeof(CK_OBJECT_HANDLE)*
1736 (*object_count+ PK11_SEARCH_CHUNKSIZE));
1737 } else {
1738 objID = (CK_OBJECT_HANDLE *) PORT_Realloc(objID,
1739 sizeof(CK_OBJECT_HANDLE)*(*object_count+PK11_SEARCH_CHUNKSIZE));
1740 }
1741
1742 if (objID == NULL) {
1743 if (oldObjID) PORT_Free(oldObjID);
1744 break;
1745 }
1746 crv = PK11_GETTAB(slot)->C_FindObjects(slot->session,
1747 &objID[*object_count],PK11_SEARCH_CHUNKSIZE,&returned_count);
1748 if (crv != CKR_OK) {
1749 PORT_SetError( PK11_MapError(crv) );
1750 PORT_Free(objID);
1751 objID = NULL;
1752 break;
1753 }
1754 *object_count += returned_count;
1755 } while (returned_count == PK11_SEARCH_CHUNKSIZE);
1756
1757 PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
1758 PK11_ExitSlotMonitor(slot);
1759
1760 if (objID && (*object_count == 0)) {
1761 PORT_Free(objID);
1762 return NULL;
1763 }
1764 if (objID == NULL) *object_count = -1;
1765 return objID;
1766 }
1767 /*
1768 * given a PKCS #11 object, match it's peer based on the KeyID. searchID
1769 * is typically a privateKey or a certificate while the peer is the opposite
1770 */
1771 CK_OBJECT_HANDLE
1772 PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID,
1773 CK_OBJECT_CLASS matchclass)
1774 {
1775 CK_ATTRIBUTE theTemplate[] = {
1776 { CKA_ID, NULL, 0 },
1777 { CKA_CLASS, NULL, 0 }
1778 };
1779 /* if you change the array, change the variable below as well */
1780 CK_ATTRIBUTE *keyclass = &theTemplate[1];
1781 int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
1782 /* if you change the array, change the variable below as well */
1783 CK_OBJECT_HANDLE peerID;
1784 CK_OBJECT_HANDLE parent;
1785 PLArenaPool *arena;
1786 CK_RV crv;
1787
1788 /* now we need to create space for the public key */
1789 arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
1790 if (arena == NULL) return CK_INVALID_HANDLE;
1791
1792 crv = PK11_GetAttributes(arena,slot,searchID,theTemplate,tsize);
1793 if (crv != CKR_OK) {
1794 PORT_FreeArena(arena,PR_FALSE);
1795 PORT_SetError( PK11_MapError(crv) );
1796 return CK_INVALID_HANDLE;
1797 }
1798
1799 if ((theTemplate[0].ulValueLen == 0) || (theTemplate[0].ulValueLen == -1)) {
1800 PORT_FreeArena(arena,PR_FALSE);
1801 if (matchclass == CKO_CERTIFICATE)
1802 PORT_SetError(SEC_ERROR_BAD_KEY);
1803 else
1804 PORT_SetError(SEC_ERROR_NO_KEY);
1805 return CK_INVALID_HANDLE;
1806 }
1807
1808
1809
1810 /*
1811 * issue the find
1812 */
1813 parent = *(CK_OBJECT_CLASS *)(keyclass->pValue);
1814 *(CK_OBJECT_CLASS *)(keyclass->pValue) = matchclass;
1815
1816 peerID = pk11_FindObjectByTemplate(slot,theTemplate,tsize);
1817 PORT_FreeArena(arena,PR_FALSE);
1818
1819 return peerID;
1820 }
1821
1822 /*
1823 * count the number of objects that match the template.
1824 */
1825 int
1826 PK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
1827 int templCount)
1828 {
1829 CK_OBJECT_HANDLE objID[PK11_SEARCH_CHUNKSIZE];
1830 int object_count = 0;
1831 CK_ULONG returned_count = 0;
1832 CK_RV crv = CKR_SESSION_HANDLE_INVALID;
1833
1834 PK11_EnterSlotMonitor(slot);
1835 if (slot->session != CK_INVALID_SESSION) {
1836 crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session,
1837 findTemplate, templCount);
1838 }
1839 if (crv != CKR_OK) {
1840 PK11_ExitSlotMonitor(slot);
1841 PORT_SetError( PK11_MapError(crv) );
1842 return object_count;
1843 }
1844
1845 /*
1846 * collect all the Matching Objects
1847 */
1848 do {
1849 crv = PK11_GETTAB(slot)->C_FindObjects(slot->session, objID,
1850 PK11_SEARCH_CHUNKSIZE,
1851 &returned_count);
1852 if (crv != CKR_OK) {
1853 PORT_SetError( PK11_MapError(crv) );
1854 break;
1855 }
1856 object_count += returned_count;
1857 } while (returned_count == PK11_SEARCH_CHUNKSIZE);
1858
1859 PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
1860 PK11_ExitSlotMonitor(slot);
1861 return object_count;
1862 }
1863
1864 /*
1865 * Traverse all the objects in a given slot.
1866 */
1867 SECStatus
1868 PK11_TraverseSlot(PK11SlotInfo *slot, void *arg)
1869 {
1870 int i;
1871 CK_OBJECT_HANDLE *objID = NULL;
1872 int object_count = 0;
1873 pk11TraverseSlot *slotcb = (pk11TraverseSlot*) arg;
1874
1875 objID = pk11_FindObjectsByTemplate(slot,slotcb->findTemplate,
1876 slotcb->templateCount,&object_count);
1877
1878 /*Actually this isn't a failure... there just were no objs to be found*/
1879 if (object_count == 0) {
1880 return SECSuccess;
1881 }
1882
1883 if (objID == NULL) {
1884 return SECFailure;
1885 }
1886
1887 for (i=0; i < object_count; i++) {
1888 (*slotcb->callback)(slot,objID[i],slotcb->callbackArg);
1889 }
1890 PORT_Free(objID);
1891 return SECSuccess;
1892 }
1893
1894 /*
1895 * Traverse all the objects in all slots.
1896 */
1897 SECStatus
1898 pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *),
1899 void *arg, PRBool forceLogin, void *wincx) {
1900 PK11SlotList *list;
1901 PK11SlotListElement *le;
1902 SECStatus rv;
1903
1904 /* get them all! */
1905 list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,wincx);
1906 if (list == NULL) return SECFailure;
1907
1908 /* look at each slot and authenticate as necessary */
1909 for (le = list->head ; le; le = le->next) {
1910 if (forceLogin) {
1911 rv = pk11_AuthenticateUnfriendly(le->slot, PR_FALSE, wincx);
1912 if (rv != SECSuccess) {
1913 continue;
1914 }
1915 }
1916 if (callback) {
1917 (*callback)(le->slot,arg);
1918 }
1919 }
1920
1921 PK11_FreeSlotList(list);
1922
1923 return SECSuccess;
1924 }
1925
1926 CK_OBJECT_HANDLE *
1927 PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr,
1928 CK_OBJECT_CLASS objclass, int *returnCount, void *wincx)
1929 {
1930 char *tokenName;
1931 char *delimit;
1932 PK11SlotInfo *slot;
1933 CK_OBJECT_HANDLE *objID;
1934 CK_ATTRIBUTE findTemplate[] = {
1935 { CKA_LABEL, NULL, 0},
1936 { CKA_CLASS, NULL, 0},
1937 };
1938 int findCount = sizeof(findTemplate)/sizeof(findTemplate[0]);
1939 SECStatus rv;
1940 PK11_SETATTRS(&findTemplate[1], CKA_CLASS, &objclass, sizeof(objclass));
1941
1942 *slotptr = slot = NULL;
1943 *returnCount = 0;
1944 /* first find the slot associated with this nickname */
1945 if ((delimit = PORT_Strchr(nickname,':')) != NULL) {
1946 int len = delimit - nickname;
1947 tokenName = (char*)PORT_Alloc(len+1);
1948 PORT_Memcpy(tokenName,nickname,len);
1949 tokenName[len] = 0;
1950
1951 slot = *slotptr = PK11_FindSlotByName(tokenName);
1952 PORT_Free(tokenName);
1953 /* if we couldn't find a slot, assume the nickname is an internal cert
1954 * with no proceding slot name */
1955 if (slot == NULL) {
1956 slot = *slotptr = PK11_GetInternalKeySlot();
1957 } else {
1958 nickname = delimit+1;
1959 }
1960 } else {
1961 *slotptr = slot = PK11_GetInternalKeySlot();
1962 }
1963 if (slot == NULL) {
1964 return CK_INVALID_HANDLE;
1965 }
1966
1967 rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx);
1968 if (rv != SECSuccess) {
1969 PK11_FreeSlot(slot);
1970 *slotptr = NULL;
1971 return CK_INVALID_HANDLE;
1972 }
1973
1974 findTemplate[0].pValue = nickname;
1975 findTemplate[0].ulValueLen = PORT_Strlen(nickname);
1976 objID = pk11_FindObjectsByTemplate(slot,findTemplate,findCount,returnCount);
1977 if (objID == NULL) {
1978 /* PKCS #11 isn't clear on whether or not the NULL is
1979 * stored in the template.... try the find again with the
1980 * full null terminated string. */
1981 findTemplate[0].ulValueLen += 1;
1982 objID = pk11_FindObjectsByTemplate(slot,findTemplate,findCount,
1983 returnCount);
1984 if (objID == NULL) {
1985 /* Well that's the best we can do. It's just not here */
1986 /* what about faked nicknames? */
1987 PK11_FreeSlot(slot);
1988 *slotptr = NULL;
1989 *returnCount = 0;
1990 }
1991 }
1992
1993 return objID;
1994 }
1995
1996 SECItem *
1997 pk11_GetLowLevelKeyFromHandle(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle)
1998 {
1999 CK_ATTRIBUTE theTemplate[] = {
2000 { CKA_ID, NULL, 0 },
2001 };
2002 int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
2003 CK_RV crv;
2004 SECItem *item;
2005
2006 item = SECITEM_AllocItem(NULL, NULL, 0);
2007
2008 if (item == NULL) {
2009 return NULL;
2010 }
2011
2012 crv = PK11_GetAttributes(NULL,slot,handle,theTemplate,tsize);
2013 if (crv != CKR_OK) {
2014 SECITEM_FreeItem(item,PR_TRUE);
2015 PORT_SetError( PK11_MapError(crv) );
2016 return NULL;
2017 }
2018
2019 item->data = (unsigned char*) theTemplate[0].pValue;
2020 item->len =theTemplate[0].ulValueLen;
2021
2022 return item;
2023 }
2024
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)