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