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

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /*
5 * This file implements the Symkey wrapper and the PKCS context
6 * Interfaces.
7 */
8
9 #include "seccomon.h"
10 #include "secmod.h"
11 #include "nssilock.h"
12 #include "secmodi.h"
13 #include "secmodti.h"
14 #include "pkcs11.h"
15 #include "pk11func.h"
16 #include "secitem.h"
17 #include "secoid.h"
18 #include "secerr.h"
19 #include "hasht.h"
20
21 static void
22 pk11_EnterKeyMonitor(PK11SymKey *symKey) {
23 if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe))
24 PK11_EnterSlotMonitor(symKey->slot);
25 }
26
27 static void
28 pk11_ExitKeyMonitor(PK11SymKey *symKey) {
29 if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe))
30 PK11_ExitSlotMonitor(symKey->slot);
31 }
32
33 /*
34 * pk11_getKeyFromList returns a symKey that has a session (if needSession
35 * was specified), or explicitly does not have a session (if needSession
36 * was not specified).
37 */
38 static PK11SymKey *
39 pk11_getKeyFromList(PK11SlotInfo *slot, PRBool needSession) {
40 PK11SymKey *symKey = NULL;
41
42 PZ_Lock(slot->freeListLock);
43 /* own session list are symkeys with sessions that the symkey owns.
44 * 'most' symkeys will own their own session. */
45 if (needSession) {
46 if (slot->freeSymKeysWithSessionHead) {
47 symKey = slot->freeSymKeysWithSessionHead;
48 slot->freeSymKeysWithSessionHead = symKey->next;
49 slot->keyCount--;
50 }
51 }
52 /* if we don't need a symkey with its own session, or we couldn't find
53 * one on the owner list, get one from the non-owner free list. */
54 if (!symKey) {
55 if (slot->freeSymKeysHead) {
56 symKey = slot->freeSymKeysHead;
57 slot->freeSymKeysHead = symKey->next;
58 slot->keyCount--;
59 }
60 }
61 PZ_Unlock(slot->freeListLock);
62 if (symKey) {
63 symKey->next = NULL;
64 if (!needSession) {
65 return symKey;
66 }
67 /* if we are getting an owner key, make sure we have a valid session.
68 * session could be invalid if the token has been removed or because
69 * we got it from the non-owner free list */
70 if ((symKey->series != slot->series) ||
71 (symKey->session == CK_INVALID_SESSION)) {
72 symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner);
73 }
74 PORT_Assert(symKey->session != CK_INVALID_SESSION);
75 if (symKey->session != CK_INVALID_SESSION)
76 return symKey;
77 PK11_FreeSymKey(symKey);
78 /* if we are here, we need a session, but couldn't get one, it's
79 * unlikely we pk11_GetNewSession will succeed if we call it a second
80 * time. */
81 return NULL;
82 }
83
84 symKey = PORT_New(PK11SymKey);
85 if (symKey == NULL) {
86 return NULL;
87 }
88
89 symKey->next = NULL;
90 if (needSession) {
91 symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner);
92 PORT_Assert(symKey->session != CK_INVALID_SESSION);
93 if (symKey->session == CK_INVALID_SESSION) {
94 PK11_FreeSymKey(symKey);
95 symKey = NULL;
96 }
97 } else {
98 symKey->session = CK_INVALID_SESSION;
99 }
100 return symKey;
101 }
102
103 /* Caller MUST hold slot->freeListLock (or ref count == 0?) !! */
104 void
105 PK11_CleanKeyList(PK11SlotInfo *slot)
106 {
107 PK11SymKey *symKey = NULL;
108
109 while (slot->freeSymKeysWithSessionHead) {
110 symKey = slot->freeSymKeysWithSessionHead;
111 slot->freeSymKeysWithSessionHead = symKey->next;
112 pk11_CloseSession(slot, symKey->session, symKey->sessionOwner);
113 PORT_Free(symKey);
114 }
115 while (slot->freeSymKeysHead) {
116 symKey = slot->freeSymKeysHead;
117 slot->freeSymKeysHead = symKey->next;
118 pk11_CloseSession(slot, symKey->session, symKey->sessionOwner);
119 PORT_Free(symKey);
120 }
121 return;
122 }
123
124 /*
125 * create a symetric key:
126 * Slot is the slot to create the key in.
127 * type is the mechanism type
128 * owner is does this symKey structure own it's object handle (rare
129 * that this is false).
130 * needSession means the returned symKey will return with a valid session
131 * allocated already.
132 */
133 static PK11SymKey *
134 pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
135 PRBool owner, PRBool needSession, void *wincx)
136 {
137
138 PK11SymKey *symKey = pk11_getKeyFromList(slot, needSession);
139
140 if (symKey == NULL) {
141 return NULL;
142 }
143 /* if needSession was specified, make sure we have a valid session.
144 * callers which specify needSession as false should do their own
145 * check of the session before returning the symKey */
146 if (needSession && symKey->session == CK_INVALID_SESSION) {
147 PK11_FreeSymKey(symKey);
148 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
149 return NULL;
150 }
151
152 symKey->type = type;
153 symKey->data.type = siBuffer;
154 symKey->data.data = NULL;
155 symKey->data.len = 0;
156 symKey->owner = owner;
157 symKey->objectID = CK_INVALID_HANDLE;
158 symKey->slot = slot;
159 symKey->series = slot->series;
160 symKey->cx = wincx;
161 symKey->size = 0;
162 symKey->refCount = 1;
163 symKey->origin = PK11_OriginNULL;
164 symKey->parent = NULL;
165 symKey->freeFunc = NULL;
166 symKey->userData = NULL;
167 PK11_ReferenceSlot(slot);
168 return symKey;
169 }
170
171 /*
172 * destroy a symetric key
173 */
174 void
175 PK11_FreeSymKey(PK11SymKey *symKey)
176 {
177 PK11SlotInfo *slot;
178 PRBool freeit = PR_TRUE;
179
180 if (PR_ATOMIC_DECREMENT(&symKey->refCount) == 0) {
181 PK11SymKey *parent = symKey->parent;
182
183 symKey->parent = NULL;
184 if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) {
185 pk11_EnterKeyMonitor(symKey);
186 (void) PK11_GETTAB(symKey->slot)->
187 C_DestroyObject(symKey->session, symKey->objectID);
188 pk11_ExitKeyMonitor(symKey);
189 }
190 if (symKey->data.data) {
191 PORT_Memset(symKey->data.data, 0, symKey->data.len);
192 PORT_Free(symKey->data.data);
193 }
194 /* free any existing data */
195 if (symKey->userData && symKey->freeFunc) {
196 (*symKey->freeFunc)(symKey->userData);
197 }
198 slot = symKey->slot;
199 PZ_Lock(slot->freeListLock);
200 if (slot->keyCount < slot->maxKeyCount) {
201 /*
202 * freeSymkeysWithSessionHead contain a list of reusable
203 * SymKey structures with valid sessions.
204 * sessionOwner must be true.
205 * session must be valid.
206 * freeSymKeysHead contain a list of SymKey structures without
207 * valid session.
208 * session must be CK_INVALID_SESSION.
209 * though sessionOwner is false, callers should not depend on
210 * this fact.
211 */
212 if (symKey->sessionOwner) {
213 PORT_Assert (symKey->session != CK_INVALID_SESSION);
214 symKey->next = slot->freeSymKeysWithSessionHead;
215 slot->freeSymKeysWithSessionHead = symKey;
216 } else {
217 symKey->session = CK_INVALID_SESSION;
218 symKey->next = slot->freeSymKeysHead;
219 slot->freeSymKeysHead = symKey;
220 }
221 slot->keyCount++;
222 symKey->slot = NULL;
223 freeit = PR_FALSE;
224 }
225 PZ_Unlock(slot->freeListLock);
226 if (freeit) {
227 pk11_CloseSession(symKey->slot, symKey->session,
228 symKey->sessionOwner);
229 PORT_Free(symKey);
230 }
231 PK11_FreeSlot(slot);
232
233 if (parent) {
234 PK11_FreeSymKey(parent);
235 }
236 }
237 }
238
239 PK11SymKey *
240 PK11_ReferenceSymKey(PK11SymKey *symKey)
241 {
242 PR_ATOMIC_INCREMENT(&symKey->refCount);
243 return symKey;
244 }
245
246 /*
247 * Accessors
248 */
249 CK_MECHANISM_TYPE
250 PK11_GetMechanism(PK11SymKey *symKey)
251 {
252 return symKey->type;
253 }
254
255 /*
256 * return the slot associated with a symetric key
257 */
258 PK11SlotInfo *
259 PK11_GetSlotFromKey(PK11SymKey *symKey)
260 {
261 return PK11_ReferenceSlot(symKey->slot);
262 }
263
264 CK_KEY_TYPE PK11_GetSymKeyType(PK11SymKey *symKey)
265 {
266 return PK11_GetKeyType(symKey->type,symKey->size);
267 }
268
269 PK11SymKey *
270 PK11_GetNextSymKey(PK11SymKey *symKey)
271 {
272 return symKey ? symKey->next : NULL;
273 }
274
275 char *
276 PK11_GetSymKeyNickname(PK11SymKey *symKey)
277 {
278 return PK11_GetObjectNickname(symKey->slot,symKey->objectID);
279 }
280
281 SECStatus
282 PK11_SetSymKeyNickname(PK11SymKey *symKey, const char *nickname)
283 {
284 return PK11_SetObjectNickname(symKey->slot,symKey->objectID,nickname);
285 }
286
287 void *
288 PK11_GetSymKeyUserData(PK11SymKey *symKey)
289 {
290 return symKey->userData;
291 }
292
293 void
294 PK11_SetSymKeyUserData(PK11SymKey *symKey, void *userData,
295 PK11FreeDataFunc freeFunc)
296 {
297 /* free any existing data */
298 if (symKey->userData && symKey->freeFunc) {
299 (*symKey->freeFunc)(symKey->userData);
300 }
301 symKey->userData = userData;
302 symKey->freeFunc = freeFunc;
303 return;
304 }
305
306 /*
307 * turn key handle into an appropriate key object
308 */
309 PK11SymKey *
310 PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin,
311 CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID, PRBool owner, void *wincx)
312 {
313 PK11SymKey *symKey;
314 PRBool needSession = !(owner && parent);
315
316 if (keyID == CK_INVALID_HANDLE) {
317 return NULL;
318 }
319
320 symKey = pk11_CreateSymKey(slot, type, owner, needSession, wincx);
321 if (symKey == NULL) {
322 return NULL;
323 }
324
325 symKey->objectID = keyID;
326 symKey->origin = origin;
327
328 /* adopt the parent's session */
329 /* This is only used by SSL. What we really want here is a session
330 * structure with a ref count so the session goes away only after all the
331 * keys do. */
332 if (!needSession) {
333 symKey->sessionOwner = PR_FALSE;
334 symKey->session = parent->session;
335 symKey->parent = PK11_ReferenceSymKey(parent);
336 /* This is the only case where pk11_CreateSymKey does not explicitly
337 * check symKey->session. We need to assert here to make sure.
338 * the session isn't invalid. */
339 PORT_Assert(parent->session != CK_INVALID_SESSION);
340 if (parent->session == CK_INVALID_SESSION) {
341 PK11_FreeSymKey(symKey);
342 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
343 return NULL;
344 }
345 }
346
347 return symKey;
348 }
349
350 /*
351 * turn key handle into an appropriate key object
352 */
353 PK11SymKey *
354 PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type,
355 int series, void *wincx)
356 {
357 PK11SymKey *symKey = NULL;
358
359 if (slot->series != series) return NULL;
360 if (slot->refKeys[wrap] == CK_INVALID_HANDLE) return NULL;
361 if (type == CKM_INVALID_MECHANISM) type = slot->wrapMechanism;
362
363 symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive,
364 slot->wrapMechanism, slot->refKeys[wrap], PR_FALSE, wincx);
365 return symKey;
366 }
367
368 /*
369 * This function is not thread-safe because it sets wrapKey->sessionOwner
370 * without using a lock or atomic routine. It can only be called when
371 * only one thread has a reference to wrapKey.
372 */
373 void
374 PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey)
375 {
376 /* save the handle and mechanism for the wrapping key */
377 /* mark the key and session as not owned by us to they don't get freed
378 * when the key goes way... that lets us reuse the key later */
379 slot->refKeys[wrap] = wrapKey->objectID;
380 wrapKey->owner = PR_FALSE;
381 wrapKey->sessionOwner = PR_FALSE;
382 slot->wrapMechanism = wrapKey->type;
383 }
384
385
386 /*
387 * figure out if a key is still valid or if it is stale.
388 */
389 PRBool
390 PK11_VerifyKeyOK(PK11SymKey *key) {
391 if (!PK11_IsPresent(key->slot)) {
392 return PR_FALSE;
393 }
394 return (PRBool)(key->series == key->slot->series);
395 }
396
397 static PK11SymKey *
398 pk11_ImportSymKeyWithTempl(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
399 PK11Origin origin, PRBool isToken, CK_ATTRIBUTE *keyTemplate,
400 unsigned int templateCount, SECItem *key, void *wincx)
401 {
402 PK11SymKey * symKey;
403 SECStatus rv;
404
405 symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx);
406 if (symKey == NULL) {
407 return NULL;
408 }
409
410 symKey->size = key->len;
411
412 PK11_SETATTRS(&keyTemplate[templateCount], CKA_VALUE, key->data, key->len);
413 templateCount++;
414
415 if (SECITEM_CopyItem(NULL,&symKey->data,key) != SECSuccess) {
416 PK11_FreeSymKey(symKey);
417 return NULL;
418 }
419
420 symKey->origin = origin;
421
422 /* import the keys */
423 rv = PK11_CreateNewObject(slot, symKey->session, keyTemplate,
424 templateCount, isToken, &symKey->objectID);
425 if ( rv != SECSuccess) {
426 PK11_FreeSymKey(symKey);
427 return NULL;
428 }
429
430 return symKey;
431 }
432
433 /*
434 * turn key bits into an appropriate key object
435 */
436 PK11SymKey *
437 PK11_ImportSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
438 PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,void *wincx)
439 {
440 PK11SymKey * symKey;
441 unsigned int templateCount = 0;
442 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
443 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
444 CK_BBOOL cktrue = CK_TRUE; /* sigh */
445 CK_ATTRIBUTE keyTemplate[5];
446 CK_ATTRIBUTE * attrs = keyTemplate;
447
448 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;
449 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;
450 PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++;
451 templateCount = attrs - keyTemplate;
452 PR_ASSERT(templateCount+1 <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE));
453
454 keyType = PK11_GetKeyType(type,key->len);
455 symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, PR_FALSE,
456 keyTemplate, templateCount, key, wincx);
457 return symKey;
458 }
459
460
461 /*
462 * turn key bits into an appropriate key object
463 */
464 PK11SymKey *
465 PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
466 PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,
467 CK_FLAGS flags, PRBool isPerm, void *wincx)
468 {
469 PK11SymKey * symKey;
470 unsigned int templateCount = 0;
471 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
472 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
473 CK_BBOOL cktrue = CK_TRUE; /* sigh */
474 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
475 CK_ATTRIBUTE * attrs = keyTemplate;
476
477 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;
478 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;
479 if (isPerm) {
480 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue) ); attrs++;
481 /* sigh some tokens think CKA_PRIVATE = false is a reasonable
482 * default for secret keys */
483 PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue) ); attrs++;
484 }
485 attrs += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
486 if ((operation != CKA_FLAGS_ONLY) &&
487 !pk11_FindAttrInTemplate(keyTemplate, attrs-keyTemplate, operation)) {
488 PK11_SETATTRS(attrs, operation, &cktrue, sizeof(cktrue)); attrs++;
489 }
490 templateCount = attrs - keyTemplate;
491 PR_ASSERT(templateCount+1 <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE));
492
493 keyType = PK11_GetKeyType(type,key->len);
494 symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, isPerm,
495 keyTemplate, templateCount, key, wincx);
496 if (symKey && isPerm) {
497 symKey->owner = PR_FALSE;
498 }
499 return symKey;
500 }
501
502
503 PK11SymKey *
504 PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID,
505 void *wincx)
506 {
507 CK_ATTRIBUTE findTemp[4];
508 CK_ATTRIBUTE *attrs;
509 CK_BBOOL ckTrue = CK_TRUE;
510 CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY;
511 int tsize = 0;
512 CK_OBJECT_HANDLE key_id;
513
514 attrs = findTemp;
515 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
516 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
517 if (keyID) {
518 PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len); attrs++;
519 }
520 tsize = attrs - findTemp;
521 PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
522
523 key_id = pk11_FindObjectByTemplate(slot,findTemp,tsize);
524 if (key_id == CK_INVALID_HANDLE) {
525 return NULL;
526 }
527 return PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, type, key_id,
528 PR_FALSE, wincx);
529 }
530
531 PK11SymKey *
532 PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx)
533 {
534 CK_ATTRIBUTE findTemp[4];
535 CK_ATTRIBUTE *attrs;
536 CK_BBOOL ckTrue = CK_TRUE;
537 CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY;
538 int tsize = 0;
539 int objCount = 0;
540 CK_OBJECT_HANDLE *key_ids;
541 PK11SymKey *nextKey = NULL;
542 PK11SymKey *topKey = NULL;
543 int i,len;
544
545 attrs = findTemp;
546 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
547 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
548 if (nickname) {
549 len = PORT_Strlen(nickname);
550 PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
551 }
552 tsize = attrs - findTemp;
553 PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
554
555 key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
556 if (key_ids == NULL) {
557 return NULL;
558 }
559
560 for (i=0; i < objCount ; i++) {
561 SECItem typeData;
562 CK_KEY_TYPE type = CKK_GENERIC_SECRET;
563 SECStatus rv = PK11_ReadAttribute(slot, key_ids[i],
564 CKA_KEY_TYPE, NULL, &typeData);
565 if (rv == SECSuccess) {
566 if (typeData.len == sizeof(CK_KEY_TYPE)) {
567 type = *(CK_KEY_TYPE *)typeData.data;
568 }
569 PORT_Free(typeData.data);
570 }
571 nextKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive,
572 PK11_GetKeyMechanism(type), key_ids[i], PR_FALSE, wincx);
573 if (nextKey) {
574 nextKey->next = topKey;
575 topKey = nextKey;
576 }
577 }
578 PORT_Free(key_ids);
579 return topKey;
580 }
581
582 void *
583 PK11_GetWindow(PK11SymKey *key)
584 {
585 return key->cx;
586 }
587
588
589 /*
590 * extract a symetric key value. NOTE: if the key is sensitive, we will
591 * not be able to do this operation. This function is used to move
592 * keys from one token to another */
593 SECStatus
594 PK11_ExtractKeyValue(PK11SymKey *symKey)
595 {
596 SECStatus rv;
597
598 if (symKey->data.data != NULL) {
599 if (symKey->size == 0) {
600 symKey->size = symKey->data.len;
601 }
602 return SECSuccess;
603 }
604
605 if (symKey->slot == NULL) {
606 PORT_SetError( SEC_ERROR_INVALID_KEY );
607 return SECFailure;
608 }
609
610 rv = PK11_ReadAttribute(symKey->slot,symKey->objectID,CKA_VALUE,NULL,
611 &symKey->data);
612 if (rv == SECSuccess) {
613 symKey->size = symKey->data.len;
614 }
615 return rv;
616 }
617
618 SECStatus
619 PK11_DeleteTokenSymKey(PK11SymKey *symKey)
620 {
621 if (!PK11_IsPermObject(symKey->slot, symKey->objectID)) {
622 return SECFailure;
623 }
624 PK11_DestroyTokenObject(symKey->slot,symKey->objectID);
625 symKey->objectID = CK_INVALID_HANDLE;
626 return SECSuccess;
627 }
628
629 SECItem *
630 PK11_GetKeyData(PK11SymKey *symKey)
631 {
632 return &symKey->data;
633 }
634
635 /* This symbol is exported for backward compatibility. */
636 SECItem *
637 __PK11_GetKeyData(PK11SymKey *symKey)
638 {
639 return PK11_GetKeyData(symKey);
640 }
641
642
643 /*
644 * PKCS #11 key Types with predefined length
645 */
646 unsigned int
647 pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType)
648 {
649 int length = 0;
650 switch (keyType) {
651 case CKK_DES: length = 8; break;
652 case CKK_DES2: length = 16; break;
653 case CKK_DES3: length = 24; break;
654 case CKK_SKIPJACK: length = 10; break;
655 case CKK_BATON: length = 20; break;
656 case CKK_JUNIPER: length = 20; break;
657 default: break;
658 }
659 return length;
660 }
661
662 /* return the keylength if possible. '0' if not */
663 unsigned int
664 PK11_GetKeyLength(PK11SymKey *key)
665 {
666 CK_KEY_TYPE keyType;
667
668 if (key->size != 0) return key->size;
669
670 /* First try to figure out the key length from its type */
671 keyType = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_KEY_TYPE);
672 key->size = pk11_GetPredefinedKeyLength(keyType);
673 if ((keyType == CKK_GENERIC_SECRET) &&
674 (key->type == CKM_SSL3_PRE_MASTER_KEY_GEN)) {
675 key->size=48;
676 }
677
678 if( key->size != 0 ) return key->size;
679
680 if (key->data.data == NULL) {
681 PK11_ExtractKeyValue(key);
682 }
683 /* key is probably secret. Look up its length */
684 /* this is new PKCS #11 version 2.0 functionality. */
685 if (key->size == 0) {
686 CK_ULONG keyLength;
687
688 keyLength = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_VALUE_LEN);
689 if (keyLength != CK_UNAVAILABLE_INFORMATION) {
690 key->size = (unsigned int)keyLength;
691 }
692 }
693
694 return key->size;
695 }
696
697 /* return the strength of a key. This is different from length in that
698 * 1) it returns the size in bits, and 2) it returns only the secret portions
699 * of the key minus any checksums or parity.
700 */
701 unsigned int
702 PK11_GetKeyStrength(PK11SymKey *key, SECAlgorithmID *algid)
703 {
704 int size=0;
705 CK_MECHANISM_TYPE mechanism= CKM_INVALID_MECHANISM; /* RC2 only */
706 SECItem *param = NULL; /* RC2 only */
707 CK_RC2_CBC_PARAMS *rc2_params = NULL; /* RC2 ONLY */
708 unsigned int effectiveBits = 0; /* RC2 ONLY */
709
710 switch (PK11_GetKeyType(key->type,0)) {
711 case CKK_CDMF:
712 return 40;
713 case CKK_DES:
714 return 56;
715 case CKK_DES3:
716 case CKK_DES2:
717 size = PK11_GetKeyLength(key);
718 if (size == 16) {
719 /* double des */
720 return 112; /* 16*7 */
721 }
722 return 168;
723 /*
724 * RC2 has is different than other ciphers in that it allows the user
725 * to deprecating keysize while still requiring all the bits for the
726 * original key. The info
727 * on what the effective key strength is in the parameter for the key.
728 * In S/MIME this parameter is stored in the DER encoded algid. In Our
729 * other uses of RC2, effectiveBits == keyBits, so this code functions
730 * correctly without an algid.
731 */
732 case CKK_RC2:
733 /* if no algid was provided, fall through to default */
734 if (!algid) {
735 break;
736 }
737 /* verify that the algid is for RC2 */
738 mechanism = PK11_AlgtagToMechanism(SECOID_GetAlgorithmTag(algid));
739 if ((mechanism != CKM_RC2_CBC) && (mechanism != CKM_RC2_ECB)) {
740 break;
741 }
742
743 /* now get effective bits from the algorithm ID. */
744 param = PK11_ParamFromAlgid(algid);
745 /* if we couldn't get memory just use key length */
746 if (param == NULL) {
747 break;
748 }
749
750 rc2_params = (CK_RC2_CBC_PARAMS *) param->data;
751 /* paranoia... shouldn't happen */
752 PORT_Assert(param->data != NULL);
753 if (param->data == NULL) {
754 SECITEM_FreeItem(param,PR_TRUE);
755 break;
756 }
757 effectiveBits = (unsigned int)rc2_params->ulEffectiveBits;
758 SECITEM_FreeItem(param,PR_TRUE);
759 param = NULL; rc2_params=NULL; /* paranoia */
760
761 /* we have effective bits, is and allocated memory is free, now
762 * we need to return the smaller of effective bits and keysize */
763 size = PK11_GetKeyLength(key);
764 if ((unsigned int)size*8 > effectiveBits) {
765 return effectiveBits;
766 }
767
768 return size*8; /* the actual key is smaller, the strength can't be
769 * greater than the actual key size */
770
771 default:
772 break;
773 }
774 return PK11_GetKeyLength(key) * 8;
775 }
776
777 /*
778 * The next three utilities are to deal with the fact that a given operation
779 * may be a multi-slot affair. This creates a new key object that is copied
780 * into the new slot.
781 */
782 PK11SymKey *
783 pk11_CopyToSlotPerm(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
784 CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags,
785 PRBool isPerm, PK11SymKey *symKey)
786 {
787 SECStatus rv;
788 PK11SymKey *newKey = NULL;
789
790 /* Extract the raw key data if possible */
791 if (symKey->data.data == NULL) {
792 rv = PK11_ExtractKeyValue(symKey);
793 /* KEY is sensitive, we're try key exchanging it. */
794 if (rv != SECSuccess) {
795 return pk11_KeyExchange(slot, type, operation,
796 flags, isPerm, symKey);
797 }
798 }
799
800 newKey = PK11_ImportSymKeyWithFlags(slot, type, symKey->origin,
801 operation, &symKey->data, flags, isPerm, symKey->cx);
802 if (newKey == NULL) {
803 newKey = pk11_KeyExchange(slot, type, operation, flags, isPerm, symKey);
804 }
805 return newKey;
806 }
807
808 PK11SymKey *
809 pk11_CopyToSlot(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
810 CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey)
811 {
812 return pk11_CopyToSlotPerm(slot, type, operation, 0, PR_FALSE, symKey);
813 }
814
815 /*
816 * Make sure the slot we are in is the correct slot for the operation
817 * by verifying that it supports all of the specified mechanism types.
818 */
819 PK11SymKey *
820 pk11_ForceSlotMultiple(PK11SymKey *symKey, CK_MECHANISM_TYPE *type,
821 int mechCount, CK_ATTRIBUTE_TYPE operation)
822 {
823 PK11SlotInfo *slot = symKey->slot;
824 PK11SymKey *newKey = NULL;
825 PRBool needToCopy = PR_FALSE;
826 int i;
827
828 if (slot == NULL) {
829 needToCopy = PR_TRUE;
830 } else {
831 i = 0;
832 while ((i < mechCount) && (needToCopy == PR_FALSE)) {
833 if (!PK11_DoesMechanism(slot,type[i])) {
834 needToCopy = PR_TRUE;
835 }
836 i++;
837 }
838 }
839
840 if (needToCopy == PR_TRUE) {
841 slot = PK11_GetBestSlotMultiple(type,mechCount,symKey->cx);
842 if (slot == NULL) {
843 PORT_SetError( SEC_ERROR_NO_MODULE );
844 return NULL;
845 }
846 newKey = pk11_CopyToSlot(slot, type[0], operation, symKey);
847 PK11_FreeSlot(slot);
848 }
849 return newKey;
850 }
851
852 /*
853 * Make sure the slot we are in is the correct slot for the operation
854 */
855 PK11SymKey *
856 pk11_ForceSlot(PK11SymKey *symKey,CK_MECHANISM_TYPE type,
857 CK_ATTRIBUTE_TYPE operation)
858 {
859 return pk11_ForceSlotMultiple(symKey, &type, 1, operation);
860 }
861
862 PK11SymKey *
863 PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation,
864 CK_FLAGS flags, PRBool perm, PK11SymKey *symKey)
865 {
866 if (symKey->slot == slot) {
867 if (perm) {
868 return PK11_ConvertSessionSymKeyToTokenSymKey(symKey,symKey->cx);
869 } else {
870 return PK11_ReferenceSymKey(symKey);
871 }
872 }
873
874 return pk11_CopyToSlotPerm(slot, symKey->type,
875 operation, flags, perm, symKey);
876 }
877
878 /*
879 * Use the token to generate a key.
880 *
881 * keySize must be 'zero' for fixed key length algorithms. A nonzero
882 * keySize causes the CKA_VALUE_LEN attribute to be added to the template
883 * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN
884 * attribute for keys with fixed length. The exception is DES2. If you
885 * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN
886 * parameter and use the key size to determine which underlying DES keygen
887 * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN).
888 *
889 * keyType must be -1 for most algorithms. Some PBE algorthims cannot
890 * determine the correct key type from the mechanism or the parameters,
891 * so key type must be specified. Other PKCS #11 mechanisms may do so in
892 * the future. Currently there is no need to export this publically.
893 * Keep it private until there is a need in case we need to expand the
894 * keygen parameters again...
895 *
896 * CK_FLAGS flags: key operation flags
897 * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags
898 */
899 PK11SymKey *
900 pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
901 SECItem *param, CK_KEY_TYPE keyType, int keySize, SECItem *keyid,
902 CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx)
903 {
904 PK11SymKey *symKey;
905 CK_ATTRIBUTE genTemplate[MAX_TEMPL_ATTRS];
906 CK_ATTRIBUTE *attrs = genTemplate;
907 int count = sizeof(genTemplate)/sizeof(genTemplate[0]);
908 CK_MECHANISM_TYPE keyGenType;
909 CK_BBOOL cktrue = CK_TRUE;
910 CK_BBOOL ckfalse = CK_FALSE;
911 CK_ULONG ck_key_size; /* only used for variable-length keys */
912
913 if (pk11_BadAttrFlags(attrFlags)) {
914 PORT_SetError( SEC_ERROR_INVALID_ARGS );
915 return NULL;
916 }
917
918 if ((keySize != 0) && (type != CKM_DES3_CBC) &&
919 (type !=CKM_DES3_CBC_PAD) && (type != CKM_DES3_ECB)) {
920 ck_key_size = keySize; /* Convert to PK11 type */
921
922 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &ck_key_size, sizeof(ck_key_size));
923 attrs++;
924 }
925
926 if (keyType != -1) {
927 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE));
928 attrs++;
929 }
930
931 /* Include key id value if provided */
932 if (keyid) {
933 PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len); attrs++;
934 }
935
936 attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse);
937 attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue);
938
939 count = attrs - genTemplate;
940 PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE));
941
942 keyGenType = PK11_GetKeyGenWithSize(type, keySize);
943 if (keyGenType == CKM_FAKE_RANDOM) {
944 PORT_SetError( SEC_ERROR_NO_MODULE );
945 return NULL;
946 }
947 symKey = PK11_KeyGenWithTemplate(slot, type, keyGenType,
948 param, genTemplate, count, wincx);
949 if (symKey != NULL) {
950 symKey->size = keySize;
951 }
952 return symKey;
953 }
954
955 /*
956 * Use the token to generate a key. - Public
957 *
958 * keySize must be 'zero' for fixed key length algorithms. A nonzero
959 * keySize causes the CKA_VALUE_LEN attribute to be added to the template
960 * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN
961 * attribute for keys with fixed length. The exception is DES2. If you
962 * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN
963 * parameter and use the key size to determine which underlying DES keygen
964 * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN).
965 *
966 * CK_FLAGS flags: key operation flags
967 * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags
968 */
969 PK11SymKey *
970 PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
971 SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags,
972 PK11AttrFlags attrFlags, void *wincx)
973 {
974 return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, -1, keySize,
975 keyid, opFlags, attrFlags, wincx);
976 }
977
978 /*
979 * Use the token to generate a key. keySize must be 'zero' for fixed key
980 * length algorithms. A nonzero keySize causes the CKA_VALUE_LEN attribute
981 * to be added to the template for the key. PKCS #11 modules fail if you
982 * specify the CKA_VALUE_LEN attribute for keys with fixed length.
983 * NOTE: this means to generate a DES2 key from this interface you must
984 * specify CKM_DES2_KEY_GEN as the mechanism directly; specifying
985 * CKM_DES3_CBC as the mechanism and 16 as keySize currently doesn't work.
986 */
987 PK11SymKey *
988 PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
989 int keySize, SECItem *keyid, PRBool isToken, void *wincx)
990 {
991 PK11SymKey *symKey;
992 PRBool weird = PR_FALSE; /* hack for fortezza */
993 CK_FLAGS opFlags = CKF_SIGN;
994 PK11AttrFlags attrFlags = 0;
995
996 if ((keySize == -1) && (type == CKM_SKIPJACK_CBC64)) {
997 weird = PR_TRUE;
998 keySize = 0;
999 }
1000
1001 opFlags |= weird ? CKF_DECRYPT : CKF_ENCRYPT;
1002
1003 if (isToken) {
1004 attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE);
1005 }
1006
1007 symKey = pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param,
1008 -1, keySize, keyid, opFlags, attrFlags, wincx);
1009 if (symKey && weird) {
1010 PK11_SetFortezzaHack(symKey);
1011 }
1012
1013 return symKey;
1014 }
1015
1016 PK11SymKey *
1017 PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
1018 int keySize, void *wincx)
1019 {
1020 return PK11_TokenKeyGen(slot, type, param, keySize, 0, PR_FALSE, wincx);
1021 }
1022
1023 PK11SymKey *
1024 PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
1025 CK_MECHANISM_TYPE keyGenType,
1026 SECItem *param, CK_ATTRIBUTE * attrs,
1027 unsigned int attrsCount, void *wincx)
1028 {
1029 PK11SymKey *symKey;
1030 CK_SESSION_HANDLE session;
1031 CK_MECHANISM mechanism;
1032 CK_RV crv;
1033 PRBool isToken = CK_FALSE;
1034 CK_ULONG keySize = 0;
1035 unsigned i;
1036
1037 /* Extract the template's CKA_VALUE_LEN into keySize and CKA_TOKEN into
1038 isToken. */
1039 for (i = 0; i < attrsCount; ++i) {
1040 switch (attrs[i].type) {
1041 case CKA_VALUE_LEN:
1042 if (attrs[i].pValue == NULL ||
1043 attrs[i].ulValueLen != sizeof(CK_ULONG)) {
1044 PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT));
1045 return NULL;
1046 }
1047 keySize = * (CK_ULONG *) attrs[i].pValue;
1048 break;
1049 case CKA_TOKEN:
1050 if (attrs[i].pValue == NULL ||
1051 attrs[i].ulValueLen != sizeof(CK_BBOOL)) {
1052 PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT));
1053 return NULL;
1054 }
1055 isToken = (*(CK_BBOOL*)attrs[i].pValue) ? PR_TRUE : PR_FALSE;
1056 break;
1057 }
1058 }
1059
1060 /* find a slot to generate the key into */
1061 /* Only do slot management if this is not a token key */
1062 if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) {
1063 PK11SlotInfo *bestSlot = PK11_GetBestSlot(type,wincx);
1064 if (bestSlot == NULL) {
1065 PORT_SetError( SEC_ERROR_NO_MODULE );
1066 return NULL;
1067 }
1068 symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE, wincx);
1069 PK11_FreeSlot(bestSlot);
1070 } else {
1071 symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx);
1072 }
1073 if (symKey == NULL) return NULL;
1074
1075 symKey->size = keySize;
1076 symKey->origin = PK11_OriginGenerated;
1077
1078 /* Set the parameters for the key gen if provided */
1079 mechanism.mechanism = keyGenType;
1080 mechanism.pParameter = NULL;
1081 mechanism.ulParameterLen = 0;
1082 if (param) {
1083 mechanism.pParameter = param->data;
1084 mechanism.ulParameterLen = param->len;
1085 }
1086
1087 /* Get session and perform locking */
1088 if (isToken) {
1089 PK11_Authenticate(symKey->slot,PR_TRUE,wincx);
1090 /* Should always be original slot */
1091 session = PK11_GetRWSession(symKey->slot);
1092 symKey->owner = PR_FALSE;
1093 } else {
1094 session = symKey->session;
1095 if (session != CK_INVALID_SESSION)
1096 pk11_EnterKeyMonitor(symKey);
1097 }
1098 if (session == CK_INVALID_SESSION) {
1099 PK11_FreeSymKey(symKey);
1100 PORT_SetError(SEC_ERROR_BAD_DATA);
1101 return NULL;
1102 }
1103
1104 crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session,
1105 &mechanism, attrs, attrsCount, &symKey->objectID);
1106
1107 /* Release lock and session */
1108 if (isToken) {
1109 PK11_RestoreROSession(symKey->slot, session);
1110 } else {
1111 pk11_ExitKeyMonitor(symKey);
1112 }
1113
1114 if (crv != CKR_OK) {
1115 PK11_FreeSymKey(symKey);
1116 PORT_SetError( PK11_MapError(crv) );
1117 return NULL;
1118 }
1119
1120 return symKey;
1121 }
1122
1123
1124 /* --- */
1125 PK11SymKey *
1126 PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx)
1127 {
1128 return PK11_TokenKeyGen(slot, CKM_DES3_CBC, 0, 0, keyid, PR_TRUE, cx);
1129 }
1130
1131 PK11SymKey*
1132 PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk, void *wincx)
1133 {
1134 PK11SlotInfo* slot = symk->slot;
1135 CK_ATTRIBUTE template[1];
1136 CK_ATTRIBUTE *attrs = template;
1137 CK_BBOOL cktrue = CK_TRUE;
1138 CK_RV crv;
1139 CK_OBJECT_HANDLE newKeyID;
1140 CK_SESSION_HANDLE rwsession;
1141
1142 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++;
1143
1144 PK11_Authenticate(slot, PR_TRUE, wincx);
1145 rwsession = PK11_GetRWSession(slot);
1146 if (rwsession == CK_INVALID_SESSION) {
1147 PORT_SetError(SEC_ERROR_BAD_DATA);
1148 return NULL;
1149 }
1150 crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, symk->objectID,
1151 template, 1, &newKeyID);
1152 PK11_RestoreROSession(slot, rwsession);
1153
1154 if (crv != CKR_OK) {
1155 PORT_SetError( PK11_MapError(crv) );
1156 return NULL;
1157 }
1158
1159 return PK11_SymKeyFromHandle(slot, NULL /*parent*/, symk->origin,
1160 symk->type, newKeyID, PR_FALSE /*owner*/, NULL /*wincx*/);
1161 }
1162
1163 /*
1164 * This function does a straight public key wrap (which only RSA can do).
1165 * Use PK11_PubGenKey and PK11_WrapSymKey to implement the FORTEZZA and
1166 * Diffie-Hellman Ciphers. */
1167 SECStatus
1168 PK11_PubWrapSymKey(CK_MECHANISM_TYPE type, SECKEYPublicKey *pubKey,
1169 PK11SymKey *symKey, SECItem *wrappedKey)
1170 {
1171 PK11SlotInfo *slot;
1172 CK_ULONG len = wrappedKey->len;
1173 PK11SymKey *newKey = NULL;
1174 CK_OBJECT_HANDLE id;
1175 CK_MECHANISM mechanism;
1176 PRBool owner = PR_TRUE;
1177 CK_SESSION_HANDLE session;
1178 CK_RV crv;
1179
1180 if (symKey == NULL) {
1181 PORT_SetError( SEC_ERROR_INVALID_ARGS );
1182 return SECFailure;
1183 }
1184
1185 /* if this slot doesn't support the mechanism, go to a slot that does */
1186 newKey = pk11_ForceSlot(symKey,type,CKA_ENCRYPT);
1187 if (newKey != NULL) {
1188 symKey = newKey;
1189 }
1190
1191 if (symKey->slot == NULL) {
1192 PORT_SetError( SEC_ERROR_NO_MODULE );
1193 return SECFailure;
1194 }
1195
1196 slot = symKey->slot;
1197 mechanism.mechanism = pk11_mapWrapKeyType(pubKey->keyType);
1198 mechanism.pParameter = NULL;
1199 mechanism.ulParameterLen = 0;
1200
1201 id = PK11_ImportPublicKey(slot,pubKey,PR_FALSE);
1202 if (id == CK_INVALID_HANDLE) {
1203 if (newKey) {
1204 PK11_FreeSymKey(newKey);
1205 }
1206 return SECFailure; /* Error code has been set. */
1207 }
1208
1209 session = pk11_GetNewSession(slot,&owner);
1210 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
1211 crv = PK11_GETTAB(slot)->C_WrapKey(session,&mechanism,
1212 id,symKey->objectID,wrappedKey->data,&len);
1213 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
1214 pk11_CloseSession(slot,session,owner);
1215 if (newKey) {
1216 PK11_FreeSymKey(newKey);
1217 }
1218
1219 if (crv != CKR_OK) {
1220 PORT_SetError( PK11_MapError(crv) );
1221 return SECFailure;
1222 }
1223 wrappedKey->len = len;
1224 return SECSuccess;
1225 }
1226
1227 /*
1228 * this little function uses the Encrypt function to wrap a key, just in
1229 * case we have problems with the wrap implementation for a token.
1230 */
1231 static SECStatus
1232 pk11_HandWrap(PK11SymKey *wrappingKey, SECItem *param, CK_MECHANISM_TYPE type,
1233 SECItem *inKey, SECItem *outKey)
1234 {
1235 PK11SlotInfo *slot;
1236 CK_ULONG len;
1237 SECItem *data;
1238 CK_MECHANISM mech;
1239 PRBool owner = PR_TRUE;
1240 CK_SESSION_HANDLE session;
1241 CK_RV crv;
1242
1243 slot = wrappingKey->slot;
1244 /* use NULL IV's for wrapping */
1245 mech.mechanism = type;
1246 if (param) {
1247 mech.pParameter = param->data;
1248 mech.ulParameterLen = param->len;
1249 } else {
1250 mech.pParameter = NULL;
1251 mech.ulParameterLen = 0;
1252 }
1253 session = pk11_GetNewSession(slot,&owner);
1254 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
1255 crv = PK11_GETTAB(slot)->C_EncryptInit(session,&mech,
1256 wrappingKey->objectID);
1257 if (crv != CKR_OK) {
1258 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
1259 pk11_CloseSession(slot,session,owner);
1260 PORT_SetError( PK11_MapError(crv) );
1261 return SECFailure;
1262 }
1263
1264 /* keys are almost always aligned, but if we get this far,
1265 * we've gone above and beyond anyway... */
1266 data = PK11_BlockData(inKey,PK11_GetBlockSize(type,param));
1267 if (data == NULL) {
1268 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
1269 pk11_CloseSession(slot,session,owner);
1270 PORT_SetError(SEC_ERROR_NO_MEMORY);
1271 return SECFailure;
1272 }
1273 len = outKey->len;
1274 crv = PK11_GETTAB(slot)->C_Encrypt(session,data->data,data->len,
1275 outKey->data, &len);
1276 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
1277 pk11_CloseSession(slot,session,owner);
1278 SECITEM_FreeItem(data,PR_TRUE);
1279 outKey->len = len;
1280 if (crv != CKR_OK) {
1281 PORT_SetError( PK11_MapError(crv) );
1282 return SECFailure;
1283 }
1284 return SECSuccess;
1285 }
1286
1287 /*
1288 * This function does a symetric based wrap.
1289 */
1290 SECStatus
1291 PK11_WrapSymKey(CK_MECHANISM_TYPE type, SECItem *param,
1292 PK11SymKey *wrappingKey, PK11SymKey *symKey, SECItem *wrappedKey)
1293 {
1294 PK11SlotInfo *slot;
1295 CK_ULONG len = wrappedKey->len;
1296 PK11SymKey *newKey = NULL;
1297 SECItem *param_save = NULL;
1298 CK_MECHANISM mechanism;
1299 PRBool owner = PR_TRUE;
1300 CK_SESSION_HANDLE session;
1301 CK_RV crv;
1302 SECStatus rv;
1303
1304 /* if this slot doesn't support the mechanism, go to a slot that does */
1305 /* Force symKey and wrappingKey into the same slot */
1306 if ((wrappingKey->slot == NULL) || (symKey->slot != wrappingKey->slot)) {
1307 /* first try copying the wrapping Key to the symKey slot */
1308 if (symKey->slot && PK11_DoesMechanism(symKey->slot,type)) {
1309 newKey = pk11_CopyToSlot(symKey->slot,type,CKA_WRAP,wrappingKey);
1310 }
1311 /* Nope, try it the other way */
1312 if (newKey == NULL) {
1313 if (wrappingKey->slot) {
1314 newKey = pk11_CopyToSlot(wrappingKey->slot,
1315 symKey->type, CKA_ENCRYPT, symKey);
1316 }
1317 /* just not playing... one last thing, can we get symKey's data?
1318 * If it's possible, we it should already be in the
1319 * symKey->data.data pointer because pk11_CopyToSlot would have
1320 * tried to put it there. */
1321 if (newKey == NULL) {
1322 /* Can't get symKey's data: Game Over */
1323 if (symKey->data.data == NULL) {
1324 PORT_SetError( SEC_ERROR_NO_MODULE );
1325 return SECFailure;
1326 }
1327 if (param == NULL) {
1328 param_save = param = PK11_ParamFromIV(type,NULL);
1329 }
1330 rv = pk11_HandWrap(wrappingKey, param, type,
1331 &symKey->data,wrappedKey);
1332 if (param_save) SECITEM_FreeItem(param_save,PR_TRUE);
1333 return rv;
1334 }
1335 /* we successfully moved the sym Key */
1336 symKey = newKey;
1337 } else {
1338 /* we successfully moved the wrapping Key */
1339 wrappingKey = newKey;
1340 }
1341 }
1342
1343 /* at this point both keys are in the same token */
1344 slot = wrappingKey->slot;
1345 mechanism.mechanism = type;
1346 /* use NULL IV's for wrapping */
1347 if (param == NULL) {
1348 param_save = param = PK11_ParamFromIV(type,NULL);
1349 }
1350 if (param) {
1351 mechanism.pParameter = param->data;
1352 mechanism.ulParameterLen = param->len;
1353 } else {
1354 mechanism.pParameter = NULL;
1355 mechanism.ulParameterLen = 0;
1356 }
1357
1358 len = wrappedKey->len;
1359
1360 session = pk11_GetNewSession(slot,&owner);
1361 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
1362 crv = PK11_GETTAB(slot)->C_WrapKey(session, &mechanism,
1363 wrappingKey->objectID, symKey->objectID,
1364 wrappedKey->data, &len);
1365 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
1366 pk11_CloseSession(slot,session,owner);
1367 rv = SECSuccess;
1368 if (crv != CKR_OK) {
1369 /* can't wrap it? try hand wrapping it... */
1370 do {
1371 if (symKey->data.data == NULL) {
1372 rv = PK11_ExtractKeyValue(symKey);
1373 if (rv != SECSuccess) break;
1374 }
1375 rv = pk11_HandWrap(wrappingKey, param, type, &symKey->data,
1376 wrappedKey);
1377 } while (PR_FALSE);
1378 } else {
1379 wrappedKey->len = len;
1380 }
1381 if (newKey) PK11_FreeSymKey(newKey);
1382 if (param_save) SECITEM_FreeItem(param_save,PR_TRUE);
1383 return rv;
1384 }
1385
1386 /*
1387 * This Generates a new key based on a symetricKey
1388 */
1389 PK11SymKey *
1390 PK11_Derive( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, SECItem *param,
1391 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1392 int keySize)
1393 {
1394 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
1395 keySize, NULL, 0, PR_FALSE);
1396 }
1397
1398
1399 PK11SymKey *
1400 PK11_DeriveWithFlags( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
1401 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1402 int keySize, CK_FLAGS flags)
1403 {
1404 CK_BBOOL ckTrue = CK_TRUE;
1405 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
1406 unsigned int templateCount;
1407
1408 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
1409 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
1410 keySize, keyTemplate, templateCount, PR_FALSE);
1411 }
1412
1413 PK11SymKey *
1414 PK11_DeriveWithFlagsPerm( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
1415 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1416 int keySize, CK_FLAGS flags, PRBool isPerm)
1417 {
1418 CK_BBOOL cktrue = CK_TRUE;
1419 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
1420 CK_ATTRIBUTE *attrs;
1421 unsigned int templateCount = 0;
1422
1423 attrs = keyTemplate;
1424 if (isPerm) {
1425 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++;
1426 }
1427 templateCount = attrs - keyTemplate;
1428 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
1429 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
1430 keySize, keyTemplate, templateCount, isPerm);
1431 }
1432
1433 PK11SymKey *
1434 PK11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
1435 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1436 int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs,
1437 PRBool isPerm)
1438 {
1439 PK11SlotInfo * slot = baseKey->slot;
1440 PK11SymKey * symKey;
1441 PK11SymKey * newBaseKey = NULL;
1442 CK_BBOOL cktrue = CK_TRUE;
1443 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
1444 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
1445 CK_ULONG valueLen = 0;
1446 CK_MECHANISM mechanism;
1447 CK_RV crv;
1448 #define MAX_ADD_ATTRS 4
1449 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS];
1450 #undef MAX_ADD_ATTRS
1451 CK_ATTRIBUTE * attrs = keyTemplate;
1452 CK_SESSION_HANDLE session;
1453 unsigned int templateCount;
1454
1455 if (numAttrs > MAX_TEMPL_ATTRS) {
1456 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1457 return NULL;
1458 }
1459
1460 /* first copy caller attributes in. */
1461 for (templateCount = 0; templateCount < numAttrs; ++templateCount) {
1462 *attrs++ = *userAttr++;
1463 }
1464
1465 /* We only add the following attributes to the template if the caller
1466 ** didn't already supply them.
1467 */
1468 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) {
1469 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass);
1470 attrs++;
1471 }
1472 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) {
1473 keyType = PK11_GetKeyType(target, keySize);
1474 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType );
1475 attrs++;
1476 }
1477 if (keySize > 0 &&
1478 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) {
1479 valueLen = (CK_ULONG)keySize;
1480 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen);
1481 attrs++;
1482 }
1483 if ((operation != CKA_FLAGS_ONLY) &&
1484 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) {
1485 PK11_SETATTRS(attrs, operation, &cktrue, sizeof cktrue); attrs++;
1486 }
1487
1488 templateCount = attrs - keyTemplate;
1489 PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE));
1490
1491 /* move the key to a slot that can do the function */
1492 if (!PK11_DoesMechanism(slot,derive)) {
1493 /* get a new base key & slot */
1494 PK11SlotInfo *newSlot = PK11_GetBestSlot(derive, baseKey->cx);
1495
1496 if (newSlot == NULL) return NULL;
1497
1498 newBaseKey = pk11_CopyToSlot (newSlot, derive, CKA_DERIVE,
1499 baseKey);
1500 PK11_FreeSlot(newSlot);
1501 if (newBaseKey == NULL)
1502 return NULL;
1503 baseKey = newBaseKey;
1504 slot = baseKey->slot;
1505 }
1506
1507
1508 /* get our key Structure */
1509 symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, baseKey->cx);
1510 if (symKey == NULL) {
1511 return NULL;
1512 }
1513
1514 symKey->size = keySize;
1515
1516 mechanism.mechanism = derive;
1517 if (param) {
1518 mechanism.pParameter = param->data;
1519 mechanism.ulParameterLen = param->len;
1520 } else {
1521 mechanism.pParameter = NULL;
1522 mechanism.ulParameterLen = 0;
1523 }
1524 symKey->origin=PK11_OriginDerive;
1525
1526 if (isPerm) {
1527 session = PK11_GetRWSession(slot);
1528 } else {
1529 pk11_EnterKeyMonitor(symKey);
1530 session = symKey->session;
1531 }
1532 if (session == CK_INVALID_SESSION) {
1533 if (!isPerm)
1534 pk11_ExitKeyMonitor(symKey);
1535 crv = CKR_SESSION_HANDLE_INVALID;
1536 } else {
1537 crv = PK11_GETTAB(slot)->C_DeriveKey(session, &mechanism,
1538 baseKey->objectID, keyTemplate, templateCount, &symKey->objectID);
1539 if (isPerm) {
1540 PK11_RestoreROSession(slot, session);
1541 } else {
1542 pk11_ExitKeyMonitor(symKey);
1543 }
1544 }
1545 if (newBaseKey)
1546 PK11_FreeSymKey(newBaseKey);
1547 if (crv != CKR_OK) {
1548 PK11_FreeSymKey(symKey);
1549 return NULL;
1550 }
1551 return symKey;
1552 }
1553
1554 /* Create a new key by concatenating base and data
1555 */
1556 static PK11SymKey *pk11_ConcatenateBaseAndData(PK11SymKey *base,
1557 CK_BYTE *data, CK_ULONG dataLen, CK_MECHANISM_TYPE target,
1558 CK_ATTRIBUTE_TYPE operation)
1559 {
1560 CK_KEY_DERIVATION_STRING_DATA mechParams;
1561 SECItem param;
1562
1563 if (base == NULL) {
1564 PORT_SetError( SEC_ERROR_INVALID_ARGS );
1565 return NULL;
1566 }
1567
1568 mechParams.pData = data;
1569 mechParams.ulLen = dataLen;
1570 param.data = (unsigned char *)&mechParams;
1571 param.len = sizeof(CK_KEY_DERIVATION_STRING_DATA);
1572
1573 return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_DATA,
1574 &param, target, operation, 0);
1575 }
1576
1577 /* Create a new key by concatenating base and key
1578 */
1579 static PK11SymKey *pk11_ConcatenateBaseAndKey(PK11SymKey *base,
1580 PK11SymKey *key, CK_MECHANISM_TYPE target,
1581 CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize)
1582 {
1583 SECItem param;
1584
1585 if ((base == NULL) || (key == NULL)) {
1586 PORT_SetError( SEC_ERROR_INVALID_ARGS );
1587 return NULL;
1588 }
1589
1590 param.data = (unsigned char *)&(key->objectID);
1591 param.len = sizeof(CK_OBJECT_HANDLE);
1592
1593 return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_KEY,
1594 &param, target, operation, keySize);
1595 }
1596
1597 /* Create a new key whose value is the hash of tobehashed.
1598 * type is the mechanism for the derived key.
1599 */
1600 static PK11SymKey *pk11_HashKeyDerivation(PK11SymKey *toBeHashed,
1601 CK_MECHANISM_TYPE hashMechanism, CK_MECHANISM_TYPE target,
1602 CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize)
1603 {
1604 return PK11_Derive(toBeHashed, hashMechanism, NULL, target, operation, keySize);
1605 }
1606
1607 /* This function implements the ANSI X9.63 key derivation function
1608 */
1609 static PK11SymKey *pk11_ANSIX963Derive(PK11SymKey *sharedSecret,
1610 CK_EC_KDF_TYPE kdf, SECItem *sharedData,
1611 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1612 CK_ULONG keySize)
1613 {
1614 CK_KEY_TYPE keyType;
1615 CK_MECHANISM_TYPE hashMechanism, mechanismArray[4];
1616 CK_ULONG derivedKeySize, HashLen, counter, maxCounter, bufferLen;
1617 CK_ULONG SharedInfoLen;
1618 CK_BYTE *buffer = NULL;
1619 PK11SymKey *toBeHashed, *hashOutput;
1620 PK11SymKey *newSharedSecret = NULL;
1621 PK11SymKey *oldIntermediateResult, *intermediateResult = NULL;
1622
1623 if (sharedSecret == NULL) {
1624 PORT_SetError( SEC_ERROR_INVALID_ARGS );
1625 return NULL;
1626 }
1627
1628 switch (kdf) {
1629 case CKD_SHA1_KDF:
1630 HashLen = SHA1_LENGTH;
1631 hashMechanism = CKM_SHA1_KEY_DERIVATION;
1632 break;
1633 case CKD_SHA224_KDF:
1634 HashLen = SHA224_LENGTH;
1635 hashMechanism = CKM_SHA224_KEY_DERIVATION;
1636 break;
1637 case CKD_SHA256_KDF:
1638 HashLen = SHA256_LENGTH;
1639 hashMechanism = CKM_SHA256_KEY_DERIVATION;
1640 break;
1641 case CKD_SHA384_KDF:
1642 HashLen = SHA384_LENGTH;
1643 hashMechanism = CKM_SHA384_KEY_DERIVATION;
1644 break;
1645 case CKD_SHA512_KDF:
1646 HashLen = SHA512_LENGTH;
1647 hashMechanism = CKM_SHA512_KEY_DERIVATION;
1648 break;
1649 default:
1650 PORT_SetError( SEC_ERROR_INVALID_ARGS );
1651 return NULL;
1652 }
1653
1654 derivedKeySize = keySize;
1655 if (derivedKeySize == 0) {
1656 keyType = PK11_GetKeyType(target,keySize);
1657 derivedKeySize = pk11_GetPredefinedKeyLength(keyType);
1658 if (derivedKeySize == 0) {
1659 derivedKeySize = HashLen;
1660 }
1661 }
1662
1663 /* Check that key_len isn't too long. The maximum key length could be
1664 * greatly increased if the code below did not limit the 4-byte counter
1665 * to a maximum value of 255. */
1666 if (derivedKeySize > 254 * HashLen) {
1667 PORT_SetError( SEC_ERROR_INVALID_ARGS );
1668 return NULL;
1669 }
1670
1671 maxCounter = derivedKeySize / HashLen;
1672 if (derivedKeySize > maxCounter * HashLen)
1673 maxCounter++;
1674
1675 if ((sharedData == NULL) || (sharedData->data == NULL))
1676 SharedInfoLen = 0;
1677 else
1678 SharedInfoLen = sharedData->len;
1679
1680 bufferLen = SharedInfoLen + 4;
1681
1682 /* Populate buffer with Counter || sharedData
1683 * where Counter is 0x00000001. */
1684 buffer = (unsigned char *)PORT_Alloc(bufferLen);
1685 if (buffer == NULL) {
1686 PORT_SetError(SEC_ERROR_NO_MEMORY);
1687 return NULL;
1688 }
1689
1690 buffer[0] = 0;
1691 buffer[1] = 0;
1692 buffer[2] = 0;
1693 buffer[3] = 1;
1694 if (SharedInfoLen > 0) {
1695 PORT_Memcpy(&buffer[4], sharedData->data, SharedInfoLen);
1696 }
1697
1698 /* Look for a slot that supports the mechanisms needed
1699 * to implement the ANSI X9.63 KDF as well as the
1700 * target mechanism.
1701 */
1702 mechanismArray[0] = CKM_CONCATENATE_BASE_AND_DATA;
1703 mechanismArray[1] = hashMechanism;
1704 mechanismArray[2] = CKM_CONCATENATE_BASE_AND_KEY;
1705 mechanismArray[3] = target;
1706
1707 newSharedSecret = pk11_ForceSlotMultiple(sharedSecret,
1708 mechanismArray, 4, operation);
1709 if (newSharedSecret != NULL) {
1710 sharedSecret = newSharedSecret;
1711 }
1712
1713 for(counter=1; counter <= maxCounter; counter++) {
1714 /* Concatenate shared_secret and buffer */
1715 toBeHashed = pk11_ConcatenateBaseAndData(sharedSecret, buffer,
1716 bufferLen, hashMechanism, operation);
1717 if (toBeHashed == NULL) {
1718 goto loser;
1719 }
1720
1721 /* Hash value */
1722 if (maxCounter == 1) {
1723 /* In this case the length of the key to be derived is
1724 * less than or equal to the length of the hash output.
1725 * So, the output of the hash operation will be the
1726 * dervied key. */
1727 hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism,
1728 target, operation, keySize);
1729 } else {
1730 /* In this case, the output of the hash operation will be
1731 * concatenated with other data to create the derived key. */
1732 hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism,
1733 CKM_CONCATENATE_BASE_AND_KEY, operation, 0);
1734 }
1735 PK11_FreeSymKey(toBeHashed);
1736 if (hashOutput == NULL) {
1737 goto loser;
1738 }
1739
1740 /* Append result to intermediate result, if necessary */
1741 oldIntermediateResult = intermediateResult;
1742
1743 if (oldIntermediateResult == NULL) {
1744 intermediateResult = hashOutput;
1745 } else {
1746 if (counter == maxCounter) {
1747 /* This is the final concatenation, and so the output
1748 * will be the derived key. */
1749 intermediateResult =
1750 pk11_ConcatenateBaseAndKey(oldIntermediateResult,
1751 hashOutput, target, operation, keySize);
1752 } else {
1753 /* The output of this concatenation will be concatenated
1754 * with other data to create the derived key. */
1755 intermediateResult =
1756 pk11_ConcatenateBaseAndKey(oldIntermediateResult,
1757 hashOutput, CKM_CONCATENATE_BASE_AND_KEY,
1758 operation, 0);
1759 }
1760
1761 PK11_FreeSymKey(hashOutput);
1762 PK11_FreeSymKey(oldIntermediateResult);
1763 if (intermediateResult == NULL) {
1764 goto loser;
1765 }
1766 }
1767
1768 /* Increment counter (assumes maxCounter < 255) */
1769 buffer[3]++;
1770 }
1771
1772 PORT_ZFree(buffer, bufferLen);
1773 if (newSharedSecret != NULL)
1774 PK11_FreeSymKey(newSharedSecret);
1775 return intermediateResult;
1776
1777 loser:
1778 if (buffer != NULL)
1779 PORT_ZFree(buffer, bufferLen);
1780 if (newSharedSecret != NULL)
1781 PK11_FreeSymKey(newSharedSecret);
1782 if (intermediateResult != NULL)
1783 PK11_FreeSymKey(intermediateResult);
1784 return NULL;
1785 }
1786
1787 /*
1788 * This Generates a wrapping key based on a privateKey, publicKey, and two
1789 * random numbers. For Mail usage RandomB should be NULL. In the Sender's
1790 * case RandomA is generate, outherwize it is passed.
1791 */
1792 static unsigned char *rb_email = NULL;
1793
1794 PK11SymKey *
1795 PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
1796 PRBool isSender, SECItem *randomA, SECItem *randomB,
1797 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
1798 CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx)
1799 {
1800 PK11SlotInfo *slot = privKey->pkcs11Slot;
1801 CK_MECHANISM mechanism;
1802 PK11SymKey *symKey;
1803 CK_RV crv;
1804
1805
1806 if (rb_email == NULL) {
1807 rb_email = PORT_ZAlloc(128);
1808 if (rb_email == NULL) {
1809 return NULL;
1810 }
1811 rb_email[127] = 1;
1812 }
1813
1814 /* get our key Structure */
1815 symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx);
1816 if (symKey == NULL) {
1817 return NULL;
1818 }
1819
1820 symKey->origin = PK11_OriginDerive;
1821
1822 switch (privKey->keyType) {
1823 case rsaKey:
1824 case nullKey:
1825 PORT_SetError(SEC_ERROR_BAD_KEY);
1826 break;
1827 case dsaKey:
1828 case keaKey:
1829 case fortezzaKey:
1830 {
1831 CK_KEA_DERIVE_PARAMS param;
1832 param.isSender = (CK_BBOOL) isSender;
1833 param.ulRandomLen = randomA->len;
1834 param.pRandomA = randomA->data;
1835 param.pRandomB = rb_email;
1836 if (randomB)
1837 param.pRandomB = randomB->data;
1838 if (pubKey->keyType == fortezzaKey) {
1839 param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len;
1840 param.pPublicData = pubKey->u.fortezza.KEAKey.data;
1841 } else {
1842 /* assert type == keaKey */
1843 /* XXX change to match key key types */
1844 param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len;
1845 param.pPublicData = pubKey->u.fortezza.KEAKey.data;
1846 }
1847
1848 mechanism.mechanism = derive;
1849 mechanism.pParameter = &param;
1850 mechanism.ulParameterLen = sizeof(param);
1851
1852 /* get a new symKey structure */
1853 pk11_EnterKeyMonitor(symKey);
1854 crv=PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism,
1855 privKey->pkcs11ID, NULL, 0, &symKey->objectID);
1856 pk11_ExitKeyMonitor(symKey);
1857 if (crv == CKR_OK) return symKey;
1858 PORT_SetError( PK11_MapError(crv) );
1859 }
1860 break;
1861 case dhKey:
1862 {
1863 CK_BBOOL cktrue = CK_TRUE;
1864 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
1865 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
1866 CK_ULONG key_size = 0;
1867 CK_ATTRIBUTE keyTemplate[4];
1868 int templateCount;
1869 CK_ATTRIBUTE *attrs = keyTemplate;
1870
1871 if (pubKey->keyType != dhKey) {
1872 PORT_SetError(SEC_ERROR_BAD_KEY);
1873 break;
1874 }
1875
1876 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
1877 attrs++;
1878 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
1879 attrs++;
1880 PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++;
1881 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size));
1882 attrs++;
1883 templateCount = attrs - keyTemplate;
1884 PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE));
1885
1886 keyType = PK11_GetKeyType(target,keySize);
1887 key_size = keySize;
1888 symKey->size = keySize;
1889 if (key_size == 0) templateCount--;
1890
1891 mechanism.mechanism = derive;
1892
1893 /* we can undefine these when we define diffie-helman keys */
1894
1895 mechanism.pParameter = pubKey->u.dh.publicValue.data;
1896 mechanism.ulParameterLen = pubKey->u.dh.publicValue.len;
1897
1898 pk11_EnterKeyMonitor(symKey);
1899 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism,
1900 privKey->pkcs11ID, keyTemplate, templateCount, &symKey->objectID);
1901 pk11_ExitKeyMonitor(symKey);
1902 if (crv == CKR_OK) return symKey;
1903 PORT_SetError( PK11_MapError(crv) );
1904 }
1905 break;
1906 case ecKey:
1907 {
1908 CK_BBOOL cktrue = CK_TRUE;
1909 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
1910 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
1911 CK_ULONG key_size = 0;
1912 CK_ATTRIBUTE keyTemplate[4];
1913 int templateCount;
1914 CK_ATTRIBUTE *attrs = keyTemplate;
1915 CK_ECDH1_DERIVE_PARAMS *mechParams = NULL;
1916
1917 if (pubKey->keyType != ecKey) {
1918 PORT_SetError(SEC_ERROR_BAD_KEY);
1919 break;
1920 }
1921
1922 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
1923 attrs++;
1924 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
1925 attrs++;
1926 PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++;
1927 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size));
1928 attrs++;
1929 templateCount = attrs - keyTemplate;
1930 PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE));
1931
1932 keyType = PK11_GetKeyType(target,keySize);
1933 key_size = keySize;
1934 if (key_size == 0) {
1935 if ((key_size = pk11_GetPredefinedKeyLength(keyType))) {
1936 templateCount --;
1937 } else {
1938 /* sigh, some tokens can't figure this out and require
1939 * CKA_VALUE_LEN to be set */
1940 key_size = SHA1_LENGTH;
1941 }
1942 }
1943 symKey->size = key_size;
1944
1945 mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS);
1946 mechParams->kdf = CKD_SHA1_KDF;
1947 mechParams->ulSharedDataLen = 0;
1948 mechParams->pSharedData = NULL;
1949 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len;
1950 mechParams->pPublicData = pubKey->u.ec.publicValue.data;
1951
1952 mechanism.mechanism = derive;
1953 mechanism.pParameter = mechParams;
1954 mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
1955
1956 pk11_EnterKeyMonitor(symKey);
1957 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session,
1958 &mechanism, privKey->pkcs11ID, keyTemplate,
1959 templateCount, &symKey->objectID);
1960 pk11_ExitKeyMonitor(symKey);
1961
1962 /* old PKCS #11 spec was ambiguous on what needed to be passed,
1963 * try this again with and encoded public key */
1964 if (crv != CKR_OK) {
1965 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
1966 &pubKey->u.ec.publicValue,
1967 SEC_ASN1_GET(SEC_OctetStringTemplate));
1968 if (pubValue == NULL) {
1969 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
1970 break;
1971 }
1972 mechParams->ulPublicDataLen = pubValue->len;
1973 mechParams->pPublicData = pubValue->data;
1974
1975 pk11_EnterKeyMonitor(symKey);
1976 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session,
1977 &mechanism, privKey->pkcs11ID, keyTemplate,
1978 templateCount, &symKey->objectID);
1979 pk11_ExitKeyMonitor(symKey);
1980
1981 SECITEM_FreeItem(pubValue,PR_TRUE);
1982 }
1983
1984 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
1985
1986 if (crv == CKR_OK) return symKey;
1987 PORT_SetError( PK11_MapError(crv) );
1988 }
1989 }
1990
1991 PK11_FreeSymKey(symKey);
1992 return NULL;
1993 }
1994
1995 /* Returns the size of the public key, or 0 if there
1996 * is an error. */
1997 static CK_ULONG
1998 pk11_ECPubKeySize(SECItem *publicValue)
1999 {
2000 if (publicValue->data[0] == 0x04) {
2001 /* key encoded in uncompressed form */
2002 return((publicValue->len - 1)/2);
2003 } else if ( (publicValue->data[0] == 0x02) ||
2004 (publicValue->data[0] == 0x03)) {
2005 /* key encoded in compressed form */
2006 return(publicValue->len - 1);
2007 }
2008 /* key encoding not recognized */
2009 return(0);
2010 }
2011
2012 static PK11SymKey *
2013 pk11_PubDeriveECKeyWithKDF(
2014 SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
2015 PRBool isSender, SECItem *randomA, SECItem *randomB,
2016 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
2017 CK_ATTRIBUTE_TYPE operation, int keySize,
2018 CK_ULONG kdf, SECItem *sharedData, void *wincx)
2019 {
2020 PK11SlotInfo *slot = privKey->pkcs11Slot;
2021 PK11SymKey *symKey;
2022 PK11SymKey *SharedSecret;
2023 CK_MECHANISM mechanism;
2024 CK_RV crv;
2025 CK_BBOOL cktrue = CK_TRUE;
2026 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
2027 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
2028 CK_ULONG key_size = 0;
2029 CK_ATTRIBUTE keyTemplate[4];
2030 int templateCount;
2031 CK_ATTRIBUTE *attrs = keyTemplate;
2032 CK_ECDH1_DERIVE_PARAMS *mechParams = NULL;
2033
2034 if (pubKey->keyType != ecKey) {
2035 PORT_SetError(SEC_ERROR_BAD_KEY);
2036 return NULL;
2037 }
2038 if ((kdf != CKD_NULL) && (kdf != CKD_SHA1_KDF) &&
2039 (kdf != CKD_SHA224_KDF) && (kdf != CKD_SHA256_KDF) &&
2040 (kdf != CKD_SHA384_KDF) && (kdf != CKD_SHA512_KDF)) {
2041 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
2042 return NULL;
2043 }
2044
2045 /* get our key Structure */
2046 symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx);
2047 if (symKey == NULL) {
2048 return NULL;
2049 }
2050
2051 symKey->origin = PK11_OriginDerive;
2052
2053 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); attrs++;
2054 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); attrs++;
2055 PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++;
2056 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); attrs++;
2057 templateCount = attrs - keyTemplate;
2058 PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE));
2059
2060 keyType = PK11_GetKeyType(target,keySize);
2061 key_size = keySize;
2062 if (key_size == 0) {
2063 if ((key_size = pk11_GetPredefinedKeyLength(keyType))) {
2064 templateCount --;
2065 } else {
2066 /* sigh, some tokens can't figure this out and require
2067 * CKA_VALUE_LEN to be set */
2068 switch (kdf) {
2069 case CKD_NULL:
2070 key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue);
2071 if (key_size == 0) {
2072 PK11_FreeSymKey(symKey);
2073 return NULL;
2074 }
2075 break;
2076 case CKD_SHA1_KDF:
2077 key_size = SHA1_LENGTH;
2078 break;
2079 case CKD_SHA224_KDF:
2080 key_size = SHA224_LENGTH;
2081 break;
2082 case CKD_SHA256_KDF:
2083 key_size = SHA256_LENGTH;
2084 break;
2085 case CKD_SHA384_KDF:
2086 key_size = SHA384_LENGTH;
2087 break;
2088 case CKD_SHA512_KDF:
2089 key_size = SHA512_LENGTH;
2090 break;
2091 default:
2092 PORT_Assert(!"Invalid CKD");
2093 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
2094 return NULL;
2095 }
2096 }
2097 }
2098 symKey->size = key_size;
2099
2100 mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS);
2101 if (!mechParams) {
2102 PK11_FreeSymKey(symKey);
2103 return NULL;
2104 }
2105 mechParams->kdf = kdf;
2106 if (sharedData == NULL) {
2107 mechParams->ulSharedDataLen = 0;
2108 mechParams->pSharedData = NULL;
2109 } else {
2110 mechParams->ulSharedDataLen = sharedData->len;
2111 mechParams->pSharedData = sharedData->data;
2112 }
2113 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len;
2114 mechParams->pPublicData = pubKey->u.ec.publicValue.data;
2115
2116 mechanism.mechanism = derive;
2117 mechanism.pParameter = mechParams;
2118 mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
2119
2120 pk11_EnterKeyMonitor(symKey);
2121 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism,
2122 privKey->pkcs11ID, keyTemplate, templateCount, &symKey->objectID);
2123 pk11_ExitKeyMonitor(symKey);
2124
2125 /* old PKCS #11 spec was ambiguous on what needed to be passed,
2126 * try this again with an encoded public key */
2127 if (crv != CKR_OK) {
2128 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
2129 &pubKey->u.ec.publicValue,
2130 SEC_ASN1_GET(SEC_OctetStringTemplate));
2131 if (pubValue == NULL) {
2132 goto loser;
2133 }
2134 mechParams->ulPublicDataLen = pubValue->len;
2135 mechParams->pPublicData = pubValue->data;
2136
2137 pk11_EnterKeyMonitor(symKey);
2138 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session,
2139 &mechanism, privKey->pkcs11ID, keyTemplate,
2140 templateCount, &symKey->objectID);
2141 pk11_ExitKeyMonitor(symKey);
2142
2143 if ((crv != CKR_OK) && (kdf != CKD_NULL)) {
2144 /* Some PKCS #11 libraries cannot perform the key derivation
2145 * function. So, try calling C_DeriveKey with CKD_NULL and then
2146 * performing the KDF separately.
2147 */
2148 CK_ULONG derivedKeySize = key_size;
2149
2150 keyType = CKK_GENERIC_SECRET;
2151 key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue);
2152 if (key_size == 0) {
2153 SECITEM_FreeItem(pubValue,PR_TRUE);
2154 goto loser;
2155 }
2156 SharedSecret = symKey;
2157 SharedSecret->size = key_size;
2158
2159 mechParams->kdf = CKD_NULL;
2160 mechParams->ulSharedDataLen = 0;
2161 mechParams->pSharedData = NULL;
2162 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len;
2163 mechParams->pPublicData = pubKey->u.ec.publicValue.data;
2164
2165 pk11_EnterKeyMonitor(SharedSecret);
2166 crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session,
2167 &mechanism, privKey->pkcs11ID, keyTemplate,
2168 templateCount, &SharedSecret->objectID);
2169 pk11_ExitKeyMonitor(SharedSecret);
2170
2171 if (crv != CKR_OK) {
2172 /* old PKCS #11 spec was ambiguous on what needed to be passed,
2173 * try this one final time with an encoded public key */
2174 mechParams->ulPublicDataLen = pubValue->len;
2175 mechParams->pPublicData = pubValue->data;
2176
2177 pk11_EnterKeyMonitor(SharedSecret);
2178 crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session,
2179 &mechanism, privKey->pkcs11ID, keyTemplate,
2180 templateCount, &SharedSecret->objectID);
2181 pk11_ExitKeyMonitor(SharedSecret);
2182 }
2183
2184 /* Perform KDF. */
2185 if (crv == CKR_OK) {
2186 symKey = pk11_ANSIX963Derive(SharedSecret, kdf,
2187 sharedData, target, operation,
2188 derivedKeySize);
2189 PK11_FreeSymKey(SharedSecret);
2190 if (symKey == NULL) {
2191 SECITEM_FreeItem(pubValue,PR_TRUE);
2192 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
2193 return NULL;
2194 }
2195 }
2196 }
2197 SECITEM_FreeItem(pubValue,PR_TRUE);
2198 }
2199
2200 loser:
2201 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
2202
2203 if (crv != CKR_OK) {
2204 PK11_FreeSymKey(symKey);
2205 symKey = NULL;
2206 PORT_SetError( PK11_MapError(crv) );
2207 }
2208 return symKey;
2209 }
2210
2211 PK11SymKey *
2212 PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
2213 PRBool isSender, SECItem *randomA, SECItem *randomB,
2214 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
2215 CK_ATTRIBUTE_TYPE operation, int keySize,
2216 CK_ULONG kdf, SECItem *sharedData, void *wincx)
2217 {
2218
2219 switch (privKey->keyType) {
2220 case rsaKey:
2221 case nullKey:
2222 case dsaKey:
2223 case keaKey:
2224 case fortezzaKey:
2225 case dhKey:
2226 return PK11_PubDerive(privKey, pubKey, isSender, randomA, randomB,
2227 derive, target, operation, keySize, wincx);
2228 case ecKey:
2229 return pk11_PubDeriveECKeyWithKDF( privKey, pubKey, isSender,
2230 randomA, randomB, derive, target, operation, keySize,
2231 kdf, sharedData, wincx);
2232 default:
2233 PORT_SetError(SEC_ERROR_BAD_KEY);
2234 break;
2235 }
2236
2237 return NULL;
2238 }
2239
2240 /*
2241 * this little function uses the Decrypt function to unwrap a key, just in
2242 * case we are having problem with unwrap. NOTE: The key size may
2243 * not be preserved properly for some algorithms!
2244 */
2245 static PK11SymKey *
2246 pk11_HandUnwrap(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey,
2247 CK_MECHANISM *mech, SECItem *inKey, CK_MECHANISM_TYPE target,
2248 CK_ATTRIBUTE *keyTemplate, unsigned int templateCount,
2249 int key_size, void * wincx, CK_RV *crvp, PRBool isPerm)
2250 {
2251 CK_ULONG len;
2252 SECItem outKey;
2253 PK11SymKey *symKey;
2254 CK_RV crv;
2255 PRBool owner = PR_TRUE;
2256 CK_SESSION_HANDLE session;
2257
2258 /* remove any VALUE_LEN parameters */
2259 if (keyTemplate[templateCount-1].type == CKA_VALUE_LEN) {
2260 templateCount--;
2261 }
2262
2263 /* keys are almost always aligned, but if we get this far,
2264 * we've gone above and beyond anyway... */
2265 outKey.data = (unsigned char*)PORT_Alloc(inKey->len);
2266 if (outKey.data == NULL) {
2267 PORT_SetError( SEC_ERROR_NO_MEMORY );
2268 if (crvp) *crvp = CKR_HOST_MEMORY;
2269 return NULL;
2270 }
2271 len = inKey->len;
2272
2273 /* use NULL IV's for wrapping */
2274 session = pk11_GetNewSession(slot,&owner);
2275 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
2276 crv = PK11_GETTAB(slot)->C_DecryptInit(session,mech,wrappingKey);
2277 if (crv != CKR_OK) {
2278 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
2279 pk11_CloseSession(slot,session,owner);
2280 PORT_Free(outKey.data);
2281 PORT_SetError( PK11_MapError(crv) );
2282 if (crvp) *crvp =crv;
2283 return NULL;
2284 }
2285 crv = PK11_GETTAB(slot)->C_Decrypt(session,inKey->data,inKey->len,
2286 outKey.data, &len);
2287 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
2288 pk11_CloseSession(slot,session,owner);
2289 if (crv != CKR_OK) {
2290 PORT_Free(outKey.data);
2291 PORT_SetError( PK11_MapError(crv) );
2292 if (crvp) *crvp =crv;
2293 return NULL;
2294 }
2295
2296 outKey.len = (key_size == 0) ? len : key_size;
2297 outKey.type = siBuffer;
2298
2299 if (PK11_DoesMechanism(slot,target)) {
2300 symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap,
2301 isPerm, keyTemplate,
2302 templateCount, &outKey, wincx);
2303 } else {
2304 slot = PK11_GetBestSlot(target,wincx);
2305 if (slot == NULL) {
2306 PORT_SetError( SEC_ERROR_NO_MODULE );
2307 PORT_Free(outKey.data);
2308 if (crvp) *crvp = CKR_DEVICE_ERROR;
2309 return NULL;
2310 }
2311 symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap,
2312 isPerm, keyTemplate,
2313 templateCount, &outKey, wincx);
2314 PK11_FreeSlot(slot);
2315 }
2316 PORT_Free(outKey.data);
2317
2318 if (crvp) *crvp = symKey? CKR_OK : CKR_DEVICE_ERROR;
2319 return symKey;
2320 }
2321
2322 /*
2323 * The wrap/unwrap function is pretty much the same for private and
2324 * public keys. It's just getting the Object ID and slot right. This is
2325 * the combined unwrap function.
2326 */
2327 static PK11SymKey *
2328 pk11_AnyUnwrapKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey,
2329 CK_MECHANISM_TYPE wrapType, SECItem *param, SECItem *wrappedKey,
2330 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize,
2331 void *wincx, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, PRBool isPerm)
2332 {
2333 PK11SymKey * symKey;
2334 SECItem * param_free = NULL;
2335 CK_BBOOL cktrue = CK_TRUE;
2336 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
2337 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
2338 CK_ULONG valueLen = 0;
2339 CK_MECHANISM mechanism;
2340 CK_SESSION_HANDLE rwsession;
2341 CK_RV crv;
2342 CK_MECHANISM_INFO mechanism_info;
2343 #define MAX_ADD_ATTRS 4
2344 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS];
2345 #undef MAX_ADD_ATTRS
2346 CK_ATTRIBUTE * attrs = keyTemplate;
2347 unsigned int templateCount;
2348
2349 if (numAttrs > MAX_TEMPL_ATTRS) {
2350 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2351 return NULL;
2352 }
2353
2354 /* first copy caller attributes in. */
2355 for (templateCount = 0; templateCount < numAttrs; ++templateCount) {
2356 *attrs++ = *userAttr++;
2357 }
2358
2359 /* We only add the following attributes to the template if the caller
2360 ** didn't already supply them.
2361 */
2362 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) {
2363 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass);
2364 attrs++;
2365 }
2366 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) {
2367 keyType = PK11_GetKeyType(target, keySize);
2368 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType );
2369 attrs++;
2370 }
2371 if ((operation != CKA_FLAGS_ONLY) &&
2372 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) {
2373 PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++;
2374 }
2375
2376 /*
2377 * must be last in case we need to use this template to import the key
2378 */
2379 if (keySize > 0 &&
2380 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) {
2381 valueLen = (CK_ULONG)keySize;
2382 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen);
2383 attrs++;
2384 }
2385
2386 templateCount = attrs - keyTemplate;
2387 PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE));
2388
2389
2390 /* find out if we can do wrap directly. Because the RSA case if *very*
2391 * common, cache the results for it. */
2392 if ((wrapType == CKM_RSA_PKCS) && (slot->hasRSAInfo)) {
2393 mechanism_info.flags = slot->RSAInfoFlags;
2394 } else {
2395 if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
2396 crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,wrapType,
2397 &mechanism_info);
2398 if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
2399 if (crv != CKR_OK) {
2400 mechanism_info.flags = 0;
2401 }
2402 if (wrapType == CKM_RSA_PKCS) {
2403 slot->RSAInfoFlags = mechanism_info.flags;
2404 slot->hasRSAInfo = PR_TRUE;
2405 }
2406 }
2407
2408 /* initialize the mechanism structure */
2409 mechanism.mechanism = wrapType;
2410 /* use NULL IV's for wrapping */
2411 if (param == NULL)
2412 param = param_free = PK11_ParamFromIV(wrapType,NULL);
2413 if (param) {
2414 mechanism.pParameter = param->data;
2415 mechanism.ulParameterLen = param->len;
2416 } else {
2417 mechanism.pParameter = NULL;
2418 mechanism.ulParameterLen = 0;
2419 }
2420
2421 if ((mechanism_info.flags & CKF_DECRYPT)
2422 && !PK11_DoesMechanism(slot,target)) {
2423 symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey,
2424 target, keyTemplate, templateCount, keySize,
2425 wincx, &crv, isPerm);
2426 if (symKey) {
2427 if (param_free) SECITEM_FreeItem(param_free,PR_TRUE);
2428 return symKey;
2429 }
2430 /*
2431 * if the RSA OP simply failed, don't try to unwrap again
2432 * with this module.
2433 */
2434 if (crv == CKR_DEVICE_ERROR){
2435 if (param_free) SECITEM_FreeItem(param_free,PR_TRUE);
2436 return NULL;
2437 }
2438 /* fall through, maybe they incorrectly set CKF_DECRYPT */
2439 }
2440
2441 /* get our key Structure */
2442 symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, wincx);
2443 if (symKey == NULL) {
2444 if (param_free) SECITEM_FreeItem(param_free,PR_TRUE);
2445 return NULL;
2446 }
2447
2448 symKey->size = keySize;
2449 symKey->origin = PK11_OriginUnwrap;
2450
2451 if (isPerm) {
2452 rwsession = PK11_GetRWSession(slot);
2453 } else {
2454 pk11_EnterKeyMonitor(symKey);
2455 rwsession = symKey->session;
2456 }
2457 PORT_Assert(rwsession != CK_INVALID_SESSION);
2458 if (rwsession == CK_INVALID_SESSION)
2459 crv = CKR_SESSION_HANDLE_INVALID;
2460 else
2461 crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession,&mechanism,wrappingKey,
2462 wrappedKey->data, wrappedKey->len, keyTemplate, templateCount,
2463 &symKey->objectID);
2464 if (isPerm) {
2465 if (rwsession != CK_INVALID_SESSION)
2466 PK11_RestoreROSession(slot, rwsession);
2467 } else {
2468 pk11_ExitKeyMonitor(symKey);
2469 }
2470 if (param_free) SECITEM_FreeItem(param_free,PR_TRUE);
2471 if (crv != CKR_OK) {
2472 PK11_FreeSymKey(symKey);
2473 symKey = NULL;
2474 if (crv != CKR_DEVICE_ERROR) {
2475 /* try hand Unwrapping */
2476 symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey,
2477 target, keyTemplate, templateCount,
2478 keySize, wincx, NULL, isPerm);
2479 }
2480 }
2481
2482 return symKey;
2483 }
2484
2485 /* use a symetric key to unwrap another symetric key */
2486 PK11SymKey *
2487 PK11_UnwrapSymKey( PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType,
2488 SECItem *param, SECItem *wrappedKey,
2489 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
2490 int keySize)
2491 {
2492 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
2493 wrapType, param, wrappedKey, target, operation, keySize,
2494 wrappingKey->cx, NULL, 0, PR_FALSE);
2495 }
2496
2497 /* use a symetric key to unwrap another symetric key */
2498 PK11SymKey *
2499 PK11_UnwrapSymKeyWithFlags(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType,
2500 SECItem *param, SECItem *wrappedKey,
2501 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
2502 int keySize, CK_FLAGS flags)
2503 {
2504 CK_BBOOL ckTrue = CK_TRUE;
2505 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
2506 unsigned int templateCount;
2507
2508 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
2509 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
2510 wrapType, param, wrappedKey, target, operation, keySize,
2511 wrappingKey->cx, keyTemplate, templateCount, PR_FALSE);
2512 }
2513
2514 PK11SymKey *
2515 PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey,
2516 CK_MECHANISM_TYPE wrapType,
2517 SECItem *param, SECItem *wrappedKey,
2518 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
2519 int keySize, CK_FLAGS flags, PRBool isPerm)
2520 {
2521 CK_BBOOL cktrue = CK_TRUE;
2522 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
2523 CK_ATTRIBUTE *attrs;
2524 unsigned int templateCount;
2525
2526 attrs = keyTemplate;
2527 if (isPerm) {
2528 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++;
2529 }
2530 templateCount = attrs-keyTemplate;
2531 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
2532
2533 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
2534 wrapType, param, wrappedKey, target, operation, keySize,
2535 wrappingKey->cx, keyTemplate, templateCount, isPerm);
2536 }
2537
2538
2539 /* unwrap a symetric key with a private key. */
2540 PK11SymKey *
2541 PK11_PubUnwrapSymKey(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey,
2542 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize)
2543 {
2544 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType);
2545 PK11SlotInfo *slot = wrappingKey->pkcs11Slot;
2546
2547 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) {
2548 PK11_HandlePasswordCheck(slot,wrappingKey->wincx);
2549 }
2550
2551 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID,
2552 wrapType, NULL, wrappedKey, target, operation, keySize,
2553 wrappingKey->wincx, NULL, 0, PR_FALSE);
2554 }
2555
2556 /* unwrap a symetric key with a private key. */
2557 PK11SymKey *
2558 PK11_PubUnwrapSymKeyWithFlags(SECKEYPrivateKey *wrappingKey,
2559 SECItem *wrappedKey, CK_MECHANISM_TYPE target,
2560 CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags)
2561 {
2562 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType);
2563 CK_BBOOL ckTrue = CK_TRUE;
2564 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
2565 unsigned int templateCount;
2566 PK11SlotInfo *slot = wrappingKey->pkcs11Slot;
2567
2568 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
2569
2570 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) {
2571 PK11_HandlePasswordCheck(slot,wrappingKey->wincx);
2572 }
2573
2574 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID,
2575 wrapType, NULL, wrappedKey, target, operation, keySize,
2576 wrappingKey->wincx, keyTemplate, templateCount, PR_FALSE);
2577 }
2578
2579 PK11SymKey *
2580 PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey,
2581 SECItem *wrappedKey, CK_MECHANISM_TYPE target,
2582 CK_ATTRIBUTE_TYPE operation, int keySize,
2583 CK_FLAGS flags, PRBool isPerm)
2584 {
2585 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType);
2586 CK_BBOOL cktrue = CK_TRUE;
2587 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
2588 CK_ATTRIBUTE *attrs;
2589 unsigned int templateCount;
2590 PK11SlotInfo *slot = wrappingKey->pkcs11Slot;
2591
2592 attrs = keyTemplate;
2593 if (isPerm) {
2594 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++;
2595 }
2596 templateCount = attrs-keyTemplate;
2597
2598 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
2599
2600 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) {
2601 PK11_HandlePasswordCheck(slot,wrappingKey->wincx);
2602 }
2603
2604 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID,
2605 wrapType, NULL, wrappedKey, target, operation, keySize,
2606 wrappingKey->wincx, keyTemplate, templateCount, isPerm);
2607 }
2608
2609 PK11SymKey*
2610 PK11_CopySymKeyForSigning(PK11SymKey *originalKey, CK_MECHANISM_TYPE mech)
2611 {
2612 CK_RV crv;
2613 CK_ATTRIBUTE setTemplate;
2614 CK_BBOOL ckTrue = CK_TRUE;
2615 PK11SlotInfo *slot = originalKey->slot;
2616
2617 /* first just try to set this key up for signing */
2618 PK11_SETATTRS(&setTemplate, CKA_SIGN, &ckTrue, sizeof(ckTrue));
2619 pk11_EnterKeyMonitor(originalKey);
2620 crv = PK11_GETTAB(slot)-> C_SetAttributeValue(originalKey->session,
2621 originalKey->objectID, &setTemplate, 1);
2622 pk11_ExitKeyMonitor(originalKey);
2623 if (crv == CKR_OK) {
2624 return PK11_ReferenceSymKey(originalKey);
2625 }
2626
2627 /* nope, doesn't like it, use the pk11 copy object command */
2628 return pk11_CopyToSlot(slot, mech, CKA_SIGN, originalKey);
2629 }
2630
2631 void
2632 PK11_SetFortezzaHack(PK11SymKey *symKey) {
2633 symKey->origin = PK11_OriginFortezzaHack;
2634 }
2635
2636 /*
2637 * This is required to allow FORTEZZA_NULL and FORTEZZA_RC4
2638 * working. This function simply gets a valid IV for the keys.
2639 */
2640 SECStatus
2641 PK11_GenerateFortezzaIV(PK11SymKey *symKey,unsigned char *iv,int len)
2642 {
2643 CK_MECHANISM mech_info;
2644 CK_ULONG count = 0;
2645 CK_RV crv;
2646 SECStatus rv = SECFailure;
2647
2648 mech_info.mechanism = CKM_SKIPJACK_CBC64;
2649 mech_info.pParameter = iv;
2650 mech_info.ulParameterLen = len;
2651
2652 /* generate the IV for fortezza */
2653 PK11_EnterSlotMonitor(symKey->slot);
2654 crv=PK11_GETTAB(symKey->slot)->C_EncryptInit(symKey->slot->session,
2655 &mech_info, symKey->objectID);
2656 if (crv == CKR_OK) {
2657 PK11_GETTAB(symKey->slot)->C_EncryptFinal(symKey->slot->session,
2658 NULL, &count);
2659 rv = SECSuccess;
2660 }
2661 PK11_ExitSlotMonitor(symKey->slot);
2662 return rv;
2663 }
2664
2665 CK_OBJECT_HANDLE
2666 PK11_GetSymKeyHandle(PK11SymKey *symKey)
2667 {
2668 return symKey->objectID;
2669 }
2670
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)