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