Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: nss/lib/pk11wrap/pk11obj.c

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

Powered by Google App Engine
This is Rietveld 408576698