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

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

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

Powered by Google App Engine
This is Rietveld 408576698