Bug Summary

File:s/lib/pk11wrap/pk11skey.c
Warning:line 382, column 9
Value stored to 'type' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pk11skey.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/pk11wrap -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/pk11wrap -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D SHLIB_SUFFIX="so" -D SHLIB_PREFIX="lib" -D NSS_SHLIB_VERSION="3" -D SOFTOKEN_SHLIB_VERSION="3" -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c pk11skey.c
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 <stddef.h>
10#include <limits.h>
11
12#include "seccomon.h"
13#include "secmod.h"
14#include "nssilock.h"
15#include "secmodi.h"
16#include "secmodti.h"
17#include "pkcs11.h"
18#include "pk11func.h"
19#include "secitem.h"
20#include "secoid.h"
21#include "secerr.h"
22#include "hasht.h"
23
24static ECPointEncoding pk11_ECGetPubkeyEncoding(const SECKEYPublicKey *pubKey);
25
26static void
27pk11_EnterKeyMonitor(PK11SymKey *symKey)
28{
29 if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe))
30 PK11_EnterSlotMonitor(symKey->slot);
31}
32
33static void
34pk11_ExitKeyMonitor(PK11SymKey *symKey)
35{
36 if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe))
37 PK11_ExitSlotMonitor(symKey->slot);
38}
39
40/*
41 * pk11_getKeyFromList returns a symKey that has a session (if needSession
42 * was specified), or explicitly does not have a session (if needSession
43 * was not specified).
44 */
45static PK11SymKey *
46pk11_getKeyFromList(PK11SlotInfo *slot, PRBool needSession)
47{
48 PK11SymKey *symKey = NULL((void*)0);
49
50 PZ_Lock(slot->freeListLock)PR_Lock((slot->freeListLock));
51 /* own session list are symkeys with sessions that the symkey owns.
52 * 'most' symkeys will own their own session. */
53 if (needSession) {
54 if (slot->freeSymKeysWithSessionHead) {
55 symKey = slot->freeSymKeysWithSessionHead;
56 slot->freeSymKeysWithSessionHead = symKey->next;
57 slot->keyCount--;
58 }
59 }
60 /* if we don't need a symkey with its own session, or we couldn't find
61 * one on the owner list, get one from the non-owner free list. */
62 if (!symKey) {
63 if (slot->freeSymKeysHead) {
64 symKey = slot->freeSymKeysHead;
65 slot->freeSymKeysHead = symKey->next;
66 slot->keyCount--;
67 }
68 }
69 PZ_Unlock(slot->freeListLock)PR_Unlock((slot->freeListLock));
70 if (symKey) {
71 symKey->next = NULL((void*)0);
72 if (!needSession) {
73 return symKey;
74 }
75 /* if we are getting an owner key, make sure we have a valid session.
76 * session could be invalid if the token has been removed or because
77 * we got it from the non-owner free list */
78 if ((symKey->series != slot->series) ||
79 (symKey->session == CK_INVALID_HANDLE0)) {
80 symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner);
81 }
82 PORT_Assert(symKey->session != CK_INVALID_HANDLE)((symKey->session != 0)?((void)0):PR_Assert("symKey->session != CK_INVALID_HANDLE"
,"pk11skey.c",82))
;
83 if (symKey->session != CK_INVALID_HANDLE0)
84 return symKey;
85 PK11_FreeSymKey(symKey);
86 /* if we are here, we need a session, but couldn't get one, it's
87 * unlikely we pk11_GetNewSession will succeed if we call it a second
88 * time. */
89 return NULL((void*)0);
90 }
91
92 symKey = PORT_New(PK11SymKey)(PK11SymKey *)PORT_Alloc_Util(sizeof(PK11SymKey));
93 if (symKey == NULL((void*)0)) {
94 return NULL((void*)0);
95 }
96
97 symKey->next = NULL((void*)0);
98 if (needSession) {
99 symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner);
100 PORT_Assert(symKey->session != CK_INVALID_HANDLE)((symKey->session != 0)?((void)0):PR_Assert("symKey->session != CK_INVALID_HANDLE"
,"pk11skey.c",100))
;
101 if (symKey->session == CK_INVALID_HANDLE0) {
102 PK11_FreeSymKey(symKey);
103 symKey = NULL((void*)0);
104 }
105 } else {
106 symKey->session = CK_INVALID_HANDLE0;
107 }
108 return symKey;
109}
110
111/* Caller MUST hold slot->freeListLock (or ref count == 0?) !! */
112void
113PK11_CleanKeyList(PK11SlotInfo *slot)
114{
115 PK11SymKey *symKey = NULL((void*)0);
116
117 while (slot->freeSymKeysWithSessionHead) {
118 symKey = slot->freeSymKeysWithSessionHead;
119 slot->freeSymKeysWithSessionHead = symKey->next;
120 pk11_CloseSession(slot, symKey->session, symKey->sessionOwner);
121 PORT_FreePORT_Free_Util(symKey);
122 }
123 while (slot->freeSymKeysHead) {
124 symKey = slot->freeSymKeysHead;
125 slot->freeSymKeysHead = symKey->next;
126 pk11_CloseSession(slot, symKey->session, symKey->sessionOwner);
127 PORT_FreePORT_Free_Util(symKey);
128 }
129 return;
130}
131
132/*
133 * create a symetric key:
134 * Slot is the slot to create the key in.
135 * type is the mechanism type
136 * owner is does this symKey structure own it's object handle (rare
137 * that this is false).
138 * needSession means the returned symKey will return with a valid session
139 * allocated already.
140 */
141static PK11SymKey *
142pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
143 PRBool owner, PRBool needSession, void *wincx)
144{
145
146 PK11SymKey *symKey = pk11_getKeyFromList(slot, needSession);
147
148 if (symKey == NULL((void*)0)) {
149 return NULL((void*)0);
150 }
151 /* if needSession was specified, make sure we have a valid session.
152 * callers which specify needSession as false should do their own
153 * check of the session before returning the symKey */
154 if (needSession && symKey->session == CK_INVALID_HANDLE0) {
155 PK11_FreeSymKey(symKey);
156 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
157 return NULL((void*)0);
158 }
159
160 symKey->type = type;
161 symKey->data.type = siBuffer;
162 symKey->data.data = NULL((void*)0);
163 symKey->data.len = 0;
164 symKey->owner = owner;
165 symKey->objectID = CK_INVALID_HANDLE0;
166 symKey->slot = slot;
167 symKey->series = slot->series;
168 symKey->cx = wincx;
169 symKey->size = 0;
170 symKey->refCount = 1;
171 symKey->origin = PK11_OriginNULL;
172 symKey->parent = NULL((void*)0);
173 symKey->freeFunc = NULL((void*)0);
174 symKey->userData = NULL((void*)0);
175 PK11_ReferenceSlot(slot);
176 return symKey;
177}
178
179/*
180 * destroy a symetric key
181 */
182void
183PK11_FreeSymKey(PK11SymKey *symKey)
184{
185 PK11SlotInfo *slot;
186 PRBool freeit = PR_TRUE1;
187
188 if (!symKey) {
189 return;
190 }
191
192 if (PR_ATOMIC_DECREMENT(&symKey->refCount)__sync_sub_and_fetch(&symKey->refCount, 1) == 0) {
193 PK11SymKey *parent = symKey->parent;
194
195 symKey->parent = NULL((void*)0);
196 if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE0) {
197 pk11_EnterKeyMonitor(symKey);
198 (void)PK11_GETTAB(symKey->slot)((CK_FUNCTION_LIST_3_0_PTR)((symKey->slot)->functionList
))
->C_DestroyObject(symKey->session, symKey->objectID);
199 pk11_ExitKeyMonitor(symKey);
200 }
201 if (symKey->data.data) {
202 PORT_Memsetmemset(symKey->data.data, 0, symKey->data.len);
203 PORT_FreePORT_Free_Util(symKey->data.data);
204 }
205 /* free any existing data */
206 if (symKey->userData && symKey->freeFunc) {
207 (*symKey->freeFunc)(symKey->userData);
208 }
209 slot = symKey->slot;
210 PZ_Lock(slot->freeListLock)PR_Lock((slot->freeListLock));
211 if (slot->keyCount < slot->maxKeyCount) {
212 /*
213 * freeSymkeysWithSessionHead contain a list of reusable
214 * SymKey structures with valid sessions.
215 * sessionOwner must be true.
216 * session must be valid.
217 * freeSymKeysHead contain a list of SymKey structures without
218 * valid session.
219 * session must be CK_INVALID_HANDLE.
220 * though sessionOwner is false, callers should not depend on
221 * this fact.
222 */
223 if (symKey->sessionOwner) {
224 PORT_Assert(symKey->session != CK_INVALID_HANDLE)((symKey->session != 0)?((void)0):PR_Assert("symKey->session != CK_INVALID_HANDLE"
,"pk11skey.c",224))
;
225 symKey->next = slot->freeSymKeysWithSessionHead;
226 slot->freeSymKeysWithSessionHead = symKey;
227 } else {
228 symKey->session = CK_INVALID_HANDLE0;
229 symKey->next = slot->freeSymKeysHead;
230 slot->freeSymKeysHead = symKey;
231 }
232 slot->keyCount++;
233 symKey->slot = NULL((void*)0);
234 freeit = PR_FALSE0;
235 }
236 PZ_Unlock(slot->freeListLock)PR_Unlock((slot->freeListLock));
237 if (freeit) {
238 pk11_CloseSession(symKey->slot, symKey->session,
239 symKey->sessionOwner);
240 PORT_FreePORT_Free_Util(symKey);
241 }
242 PK11_FreeSlot(slot);
243
244 if (parent) {
245 PK11_FreeSymKey(parent);
246 }
247 }
248}
249
250PK11SymKey *
251PK11_ReferenceSymKey(PK11SymKey *symKey)
252{
253 PR_ATOMIC_INCREMENT(&symKey->refCount)__sync_add_and_fetch(&symKey->refCount, 1);
254 return symKey;
255}
256
257/*
258 * Accessors
259 */
260CK_MECHANISM_TYPE
261PK11_GetMechanism(PK11SymKey *symKey)
262{
263 return symKey->type;
264}
265
266/*
267 * return the slot associated with a symetric key
268 */
269PK11SlotInfo *
270PK11_GetSlotFromKey(PK11SymKey *symKey)
271{
272 return PK11_ReferenceSlot(symKey->slot);
273}
274
275CK_KEY_TYPE
276PK11_GetSymKeyType(PK11SymKey *symKey)
277{
278 return PK11_GetKeyType(symKey->type, symKey->size);
279}
280
281PK11SymKey *
282PK11_GetNextSymKey(PK11SymKey *symKey)
283{
284 return symKey ? symKey->next : NULL((void*)0);
285}
286
287char *
288PK11_GetSymKeyNickname(PK11SymKey *symKey)
289{
290 return PK11_GetObjectNickname(symKey->slot, symKey->objectID);
291}
292
293SECStatus
294PK11_SetSymKeyNickname(PK11SymKey *symKey, const char *nickname)
295{
296 return PK11_SetObjectNickname(symKey->slot, symKey->objectID, nickname);
297}
298
299void *
300PK11_GetSymKeyUserData(PK11SymKey *symKey)
301{
302 return symKey->userData;
303}
304
305void
306PK11_SetSymKeyUserData(PK11SymKey *symKey, void *userData,
307 PK11FreeDataFunc freeFunc)
308{
309 /* free any existing data */
310 if (symKey->userData && symKey->freeFunc) {
311 (*symKey->freeFunc)(symKey->userData);
312 }
313 symKey->userData = userData;
314 symKey->freeFunc = freeFunc;
315 return;
316}
317
318/*
319 * turn key handle into an appropriate key object
320 */
321PK11SymKey *
322PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin,
323 CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID, PRBool owner, void *wincx)
324{
325 PK11SymKey *symKey;
326 PRBool needSession = !(owner && parent);
327
328 if (keyID == CK_INVALID_HANDLE0) {
329 return NULL((void*)0);
330 }
331
332 symKey = pk11_CreateSymKey(slot, type, owner, needSession, wincx);
333 if (symKey == NULL((void*)0)) {
334 return NULL((void*)0);
335 }
336
337 symKey->objectID = keyID;
338 symKey->origin = origin;
339
340 /* adopt the parent's session */
341 /* This is only used by SSL. What we really want here is a session
342 * structure with a ref count so the session goes away only after all the
343 * keys do. */
344 if (!needSession) {
345 symKey->sessionOwner = PR_FALSE0;
346 symKey->session = parent->session;
347 symKey->parent = PK11_ReferenceSymKey(parent);
348 /* This is the only case where pk11_CreateSymKey does not explicitly
349 * check symKey->session. We need to assert here to make sure.
350 * the session isn't invalid. */
351 PORT_Assert(parent->session != CK_INVALID_HANDLE)((parent->session != 0)?((void)0):PR_Assert("parent->session != CK_INVALID_HANDLE"
,"pk11skey.c",351))
;
352 if (parent->session == CK_INVALID_HANDLE0) {
353 PK11_FreeSymKey(symKey);
354 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
355 return NULL((void*)0);
356 }
357 }
358
359 return symKey;
360}
361
362/*
363 * Restore a symmetric wrapping key that was saved using PK11_SetWrapKey.
364 *
365 * This function is provided for ABI compatibility; see PK11_SetWrapKey below.
366 */
367PK11SymKey *
368PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type,
369 int series, void *wincx)
370{
371 PK11SymKey *symKey = NULL((void*)0);
372 CK_OBJECT_HANDLE keyHandle;
373
374 PK11_EnterSlotMonitor(slot);
375 if (slot->series != series ||
376 slot->refKeys[wrap] == CK_INVALID_HANDLE0) {
377 PK11_ExitSlotMonitor(slot);
378 return NULL((void*)0);
379 }
380
381 if (type == CKM_INVALID_MECHANISM0xffffffffUL) {
382 type = slot->wrapMechanism;
Value stored to 'type' is never read
383 }
384
385 keyHandle = slot->refKeys[wrap];
386 PK11_ExitSlotMonitor(slot);
387 symKey = PK11_SymKeyFromHandle(slot, NULL((void*)0), PK11_OriginDerive,
388 slot->wrapMechanism, keyHandle, PR_FALSE0, wincx);
389 return symKey;
390}
391
392/*
393 * This function sets an attribute on the current slot with a wrapping key. The
394 * data saved is ephemeral; it needs to be run every time the program is
395 * invoked.
396 *
397 * Since NSS 3.45, this function is marginally more thread safe. It uses the
398 * slot lock (if present) and fails silently if a value is already set. Use
399 * PK11_GetWrapKey() after calling this function to get the current wrapping key
400 * in case there was an update on another thread.
401 *
402 * Either way, using this function is inadvisable. It's provided for ABI
403 * compatibility only.
404 */
405void
406PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey)
407{
408 PK11_EnterSlotMonitor(slot);
409 if (wrap >= 0) {
410 size_t uwrap = (size_t)wrap;
411 if (uwrap < PR_ARRAY_SIZE(slot->refKeys)(sizeof(slot->refKeys)/sizeof((slot->refKeys)[0])) &&
412 slot->refKeys[uwrap] == CK_INVALID_HANDLE0) {
413 /* save the handle and mechanism for the wrapping key */
414 /* mark the key and session as not owned by us so they don't get
415 * freed when the key goes way... that lets us reuse the key
416 * later */
417 slot->refKeys[uwrap] = wrapKey->objectID;
418 wrapKey->owner = PR_FALSE0;
419 wrapKey->sessionOwner = PR_FALSE0;
420 slot->wrapMechanism = wrapKey->type;
421 }
422 }
423 PK11_ExitSlotMonitor(slot);
424}
425
426/*
427 * figure out if a key is still valid or if it is stale.
428 */
429PRBool
430PK11_VerifyKeyOK(PK11SymKey *key)
431{
432 if (!PK11_IsPresent(key->slot)) {
433 return PR_FALSE0;
434 }
435 return (PRBool)(key->series == key->slot->series);
436}
437
438static PK11SymKey *
439pk11_ImportSymKeyWithTempl(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
440 PK11Origin origin, PRBool isToken, CK_ATTRIBUTE *keyTemplate,
441 unsigned int templateCount, SECItem *key, void *wincx)
442{
443 PK11SymKey *symKey;
444 SECStatus rv;
445
446 symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE1, wincx);
447 if (symKey == NULL((void*)0)) {
448 return NULL((void*)0);
449 }
450
451 symKey->size = key->len;
452
453 PK11_SETATTRS(&keyTemplate[templateCount], CKA_VALUE, key->data, key->len)(&keyTemplate[templateCount])->type = (0x00000011UL); (
&keyTemplate[templateCount])->pValue = (key->data);
(&keyTemplate[templateCount])->ulValueLen = (key->
len);
;
454 templateCount++;
455
456 if (SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), &symKey->data, key) != SECSuccess) {
457 PK11_FreeSymKey(symKey);
458 return NULL((void*)0);
459 }
460
461 symKey->origin = origin;
462
463 /* import the keys */
464 rv = PK11_CreateNewObject(slot, symKey->session, keyTemplate,
465 templateCount, isToken, &symKey->objectID);
466 if (rv != SECSuccess) {
467 PK11_FreeSymKey(symKey);
468 return NULL((void*)0);
469 }
470
471 return symKey;
472}
473
474/*
475 * turn key bits into an appropriate key object
476 */
477PK11SymKey *
478PK11_ImportSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
479 PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key, void *wincx)
480{
481 PK11SymKey *symKey;
482 unsigned int templateCount = 0;
483 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY0x00000004UL;
484 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET0x00000010UL;
485 CK_BBOOL cktrue = CK_TRUE1; /* sigh */
486 CK_ATTRIBUTE keyTemplate[5];
487 CK_ATTRIBUTE *attrs = keyTemplate;
488
489 /* CKA_NSS_MESSAGE is a fake operation to distinguish between
490 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set
491 * it as a real attribute */
492 if ((operation & CKA_NSS_MESSAGE_MASK0xff000000L) == CKA_NSS_MESSAGE0x82000000L) {
493 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT),
494 * etc. Strip out the real attribute here */
495 operation &= ~CKA_NSS_MESSAGE_MASK0xff000000L;
496 }
497
498 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyClass); (attrs)->ulValueLen = (sizeof(keyClass));
;
499 attrs++;
500 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType))(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof(keyType));
;
501 attrs++;
502 PK11_SETATTRS(attrs, operation, &cktrue, 1)(attrs)->type = (operation); (attrs)->pValue = (&cktrue
); (attrs)->ulValueLen = (1);
;
503 attrs++;
504 templateCount = attrs - keyTemplate;
505 PR_ASSERT(templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE))((templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE
))?((void)0):PR_Assert("templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",505))
;
506
507 keyType = PK11_GetKeyType(type, key->len);
508 symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, PR_FALSE0,
509 keyTemplate, templateCount, key, wincx);
510 return symKey;
511}
512/* Import a PKCS #11 data object and return it as a key. This key is
513 * only useful in a limited number of mechanisms, such as HKDF. */
514PK11SymKey *
515PK11_ImportDataKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11Origin origin,
516 CK_ATTRIBUTE_TYPE operation, SECItem *key, void *wincx)
517{
518 CK_OBJECT_CLASS ckoData = CKO_DATA0x00000000UL;
519 CK_ATTRIBUTE template[2] = { { CKA_CLASS0x00000000UL, (CK_BYTE_PTR)&ckoData, sizeof(ckoData) },
520 { CKA_VALUE0x00000011UL, (CK_BYTE_PTR)key->data, key->len } };
521 CK_OBJECT_HANDLE handle;
522 PK11GenericObject *genObject;
523
524 genObject = PK11_CreateGenericObject(slot, template, PR_ARRAY_SIZE(template)(sizeof(template)/sizeof((template)[0])), PR_FALSE0);
525 if (genObject == NULL((void*)0)) {
526 return NULL((void*)0);
527 }
528 handle = PK11_GetObjectHandle(PK11_TypeGeneric, genObject, NULL((void*)0));
529 /* A note about ownership of the PKCS #11 handle:
530 * PK11_CreateGenericObject() will not destroy the object it creates
531 * on Free, For that you want PK11_CreateManagedGenericObject().
532 * Below we import the handle into the symKey structure. We pass
533 * PR_TRUE as the owner so that the symKey will destroy the object
534 * once it's freed. This is why it's safe to destroy genObject now. */
535 PK11_DestroyGenericObject(genObject);
536 if (handle == CK_INVALID_HANDLE0) {
537 return NULL((void*)0);
538 }
539 return PK11_SymKeyFromHandle(slot, NULL((void*)0), origin, type, handle, PR_TRUE1, wincx);
540}
541
542/* turn key bits into an appropriate key object */
543PK11SymKey *
544PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
545 PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,
546 CK_FLAGS flags, PRBool isPerm, void *wincx)
547{
548 PK11SymKey *symKey;
549 unsigned int templateCount = 0;
550 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY0x00000004UL;
551 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET0x00000010UL;
552 CK_BBOOL cktrue = CK_TRUE1; /* sigh */
553 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16];
554 CK_ATTRIBUTE *attrs = keyTemplate;
555
556 /* CKA_NSS_MESSAGE is a fake operation to distinguish between
557 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set
558 * it as a real attribute */
559 if ((operation & CKA_NSS_MESSAGE_MASK0xff000000L) == CKA_NSS_MESSAGE0x82000000L) {
560 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT),
561 * etc. Strip out the real attribute here */
562 operation &= ~CKA_NSS_MESSAGE_MASK0xff000000L;
563 }
564
565 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyClass); (attrs)->ulValueLen = (sizeof(keyClass));
;
566 attrs++;
567 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType))(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof(keyType));
;
568 attrs++;
569 if (isPerm) {
570 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue))(attrs)->type = (0x00000001UL); (attrs)->pValue = (&
cktrue); (attrs)->ulValueLen = (sizeof(cktrue));
;
571 attrs++;
572 /* sigh some tokens think CKA_PRIVATE = false is a reasonable
573 * default for secret keys */
574 PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue))(attrs)->type = (0x00000002UL); (attrs)->pValue = (&
cktrue); (attrs)->ulValueLen = (sizeof(cktrue));
;
575 attrs++;
576 }
577 attrs += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
578 if ((operation != CKA_FLAGS_ONLY0) &&
579 !pk11_FindAttrInTemplate(keyTemplate, attrs - keyTemplate, operation)) {
580 PK11_SETATTRS(attrs, operation, &cktrue, sizeof(cktrue))(attrs)->type = (operation); (attrs)->pValue = (&cktrue
); (attrs)->ulValueLen = (sizeof(cktrue));
;
581 attrs++;
582 }
583 templateCount = attrs - keyTemplate;
584 PR_ASSERT(templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE))((templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE
))?((void)0):PR_Assert("templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",584))
;
585
586 keyType = PK11_GetKeyType(type, key->len);
587 symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, isPerm,
588 keyTemplate, templateCount, key, wincx);
589 if (symKey && isPerm) {
590 symKey->owner = PR_FALSE0;
591 }
592 return symKey;
593}
594
595PK11SymKey *
596PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID,
597 void *wincx)
598{
599 CK_ATTRIBUTE findTemp[4];
600 CK_ATTRIBUTE *attrs;
601 CK_BBOOL ckTrue = CK_TRUE1;
602 CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY0x00000004UL;
603 size_t tsize = 0;
604 CK_OBJECT_HANDLE key_id;
605
606 attrs = findTemp;
607 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyclass); (attrs)->ulValueLen = (sizeof(keyclass));
;
608 attrs++;
609 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue))(attrs)->type = (0x00000001UL); (attrs)->pValue = (&
ckTrue); (attrs)->ulValueLen = (sizeof(ckTrue));
;
610 attrs++;
611 if (keyID) {
612 PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len)(attrs)->type = (0x00000102UL); (attrs)->pValue = (keyID
->data); (attrs)->ulValueLen = (keyID->len);
;
613 attrs++;
614 }
615 tsize = attrs - findTemp;
616 PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE))((tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE))?((void
)0):PR_Assert("tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",616))
;
617
618 key_id = pk11_FindObjectByTemplate(slot, findTemp, tsize);
619 if (key_id == CK_INVALID_HANDLE0) {
620 return NULL((void*)0);
621 }
622 return PK11_SymKeyFromHandle(slot, NULL((void*)0), PK11_OriginDerive, type, key_id,
623 PR_FALSE0, wincx);
624}
625
626PK11SymKey *
627PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx)
628{
629 CK_ATTRIBUTE findTemp[4];
630 CK_ATTRIBUTE *attrs;
631 CK_BBOOL ckTrue = CK_TRUE1;
632 CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY0x00000004UL;
633 int tsize = 0;
634 int objCount = 0;
635 CK_OBJECT_HANDLE *key_ids;
636 PK11SymKey *nextKey = NULL((void*)0);
637 PK11SymKey *topKey = NULL((void*)0);
638 int i, len;
639
640 attrs = findTemp;
641 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyclass); (attrs)->ulValueLen = (sizeof(keyclass));
;
642 attrs++;
643 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue))(attrs)->type = (0x00000001UL); (attrs)->pValue = (&
ckTrue); (attrs)->ulValueLen = (sizeof(ckTrue));
;
644 attrs++;
645 if (nickname) {
646 len = PORT_Strlen(nickname)strlen(nickname);
647 PK11_SETATTRS(attrs, CKA_LABEL, nickname, len)(attrs)->type = (0x00000003UL); (attrs)->pValue = (nickname
); (attrs)->ulValueLen = (len);
;
648 attrs++;
649 }
650 tsize = attrs - findTemp;
651 PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE))((tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE))?((void
)0):PR_Assert("tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",651))
;
652
653 key_ids = pk11_FindObjectsByTemplate(slot, findTemp, tsize, &objCount);
654 if (key_ids == NULL((void*)0)) {
655 return NULL((void*)0);
656 }
657
658 for (i = 0; i < objCount; i++) {
659 SECItem typeData;
660 CK_KEY_TYPE type = CKK_GENERIC_SECRET0x00000010UL;
661 SECStatus rv = PK11_ReadAttribute(slot, key_ids[i],
662 CKA_KEY_TYPE0x00000100UL, NULL((void*)0), &typeData);
663 if (rv == SECSuccess) {
664 if (typeData.len == sizeof(CK_KEY_TYPE)) {
665 type = *(CK_KEY_TYPE *)typeData.data;
666 }
667 PORT_FreePORT_Free_Util(typeData.data);
668 }
669 nextKey = PK11_SymKeyFromHandle(slot, NULL((void*)0), PK11_OriginDerive,
670 PK11_GetKeyMechanism(type), key_ids[i], PR_FALSE0, wincx);
671 if (nextKey) {
672 nextKey->next = topKey;
673 topKey = nextKey;
674 }
675 }
676 PORT_FreePORT_Free_Util(key_ids);
677 return topKey;
678}
679
680void *
681PK11_GetWindow(PK11SymKey *key)
682{
683 return key->cx;
684}
685
686/*
687 * extract a symmetric key value. NOTE: if the key is sensitive, we will
688 * not be able to do this operation. This function is used to move
689 * keys from one token to another */
690SECStatus
691PK11_ExtractKeyValue(PK11SymKey *symKey)
692{
693 SECStatus rv;
694
695 if (symKey == NULL((void*)0)) {
696 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
697 return SECFailure;
698 }
699
700 if (symKey->data.data != NULL((void*)0)) {
701 if (symKey->size == 0) {
702 symKey->size = symKey->data.len;
703 }
704 return SECSuccess;
705 }
706
707 if (symKey->slot == NULL((void*)0)) {
708 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_KEY);
709 return SECFailure;
710 }
711
712 rv = PK11_ReadAttribute(symKey->slot, symKey->objectID, CKA_VALUE0x00000011UL, NULL((void*)0),
713 &symKey->data);
714 if (rv == SECSuccess) {
715 symKey->size = symKey->data.len;
716 }
717 return rv;
718}
719
720SECStatus
721PK11_DeleteTokenSymKey(PK11SymKey *symKey)
722{
723 if (!PK11_IsPermObject(symKey->slot, symKey->objectID)) {
724 return SECFailure;
725 }
726 PK11_DestroyTokenObject(symKey->slot, symKey->objectID);
727 symKey->objectID = CK_INVALID_HANDLE0;
728 return SECSuccess;
729}
730
731SECItem *
732PK11_GetKeyData(PK11SymKey *symKey)
733{
734 return &symKey->data;
735}
736
737/* This symbol is exported for backward compatibility. */
738SECItem *
739__PK11_GetKeyData(PK11SymKey *symKey)
740{
741 return PK11_GetKeyData(symKey);
742}
743
744/*
745 * PKCS #11 key Types with predefined length
746 */
747unsigned int
748pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType)
749{
750 int length = 0;
751 switch (keyType) {
752 case CKK_DES0x00000013UL:
753 length = 8;
754 break;
755 case CKK_DES20x00000014UL:
756 length = 16;
757 break;
758 case CKK_DES30x00000015UL:
759 length = 24;
760 break;
761 case CKK_SKIPJACK0x0000001BUL:
762 length = 10;
763 break;
764 case CKK_BATON0x0000001CUL:
765 length = 20;
766 break;
767 case CKK_JUNIPER0x0000001DUL:
768 length = 20;
769 break;
770 default:
771 break;
772 }
773 return length;
774}
775
776/* return the keylength if possible. '0' if not */
777unsigned int
778PK11_GetKeyLength(PK11SymKey *key)
779{
780 CK_KEY_TYPE keyType;
781
782 if (key->size != 0)
783 return key->size;
784
785 /* First try to figure out the key length from its type */
786 keyType = PK11_ReadULongAttribute(key->slot, key->objectID, CKA_KEY_TYPE0x00000100UL);
787 key->size = pk11_GetPredefinedKeyLength(keyType);
788 if ((keyType == CKK_GENERIC_SECRET0x00000010UL) &&
789 (key->type == CKM_SSL3_PRE_MASTER_KEY_GEN0x00000370UL)) {
790 key->size = 48;
791 }
792
793 if (key->size != 0)
794 return key->size;
795
796 if (key->data.data == NULL((void*)0)) {
797 PK11_ExtractKeyValue(key);
798 }
799 /* key is probably secret. Look up its length */
800 /* this is new PKCS #11 version 2.0 functionality. */
801 if (key->size == 0) {
802 CK_ULONG keyLength;
803
804 keyLength = PK11_ReadULongAttribute(key->slot, key->objectID, CKA_VALUE_LEN0x00000161UL);
805 if (keyLength != CK_UNAVAILABLE_INFORMATION(~0UL)) {
806 key->size = (unsigned int)keyLength;
807 }
808 }
809
810 return key->size;
811}
812
813/* return the strength of a key. This is different from length in that
814 * 1) it returns the size in bits, and 2) it returns only the secret portions
815 * of the key minus any checksums or parity.
816 */
817unsigned int
818PK11_GetKeyStrength(PK11SymKey *key, SECAlgorithmID *algid)
819{
820 int size = 0;
821 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM0xffffffffUL; /* RC2 only */
822 SECItem *param = NULL((void*)0); /* RC2 only */
823 CK_RC2_CBC_PARAMS *rc2_params = NULL((void*)0); /* RC2 ONLY */
824 unsigned int effectiveBits = 0; /* RC2 ONLY */
825
826 switch (PK11_GetKeyType(key->type, 0)) {
827 case CKK_CDMF0x0000001EUL:
828 return 40;
829 case CKK_DES0x00000013UL:
830 return 56;
831 case CKK_DES30x00000015UL:
832 case CKK_DES20x00000014UL:
833 size = PK11_GetKeyLength(key);
834 if (size == 16) {
835 /* double des */
836 return 112; /* 16*7 */
837 }
838 return 168;
839 /*
840 * RC2 has is different than other ciphers in that it allows the user
841 * to deprecating keysize while still requiring all the bits for the
842 * original key. The info
843 * on what the effective key strength is in the parameter for the key.
844 * In S/MIME this parameter is stored in the DER encoded algid. In Our
845 * other uses of RC2, effectiveBits == keyBits, so this code functions
846 * correctly without an algid.
847 */
848 case CKK_RC20x00000011UL:
849 /* if no algid was provided, fall through to default */
850 if (!algid) {
851 break;
852 }
853 /* verify that the algid is for RC2 */
854 mechanism = PK11_AlgtagToMechanism(SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(algid));
855 if ((mechanism != CKM_RC2_CBC0x00000102UL) && (mechanism != CKM_RC2_ECB0x00000101UL)) {
856 break;
857 }
858
859 /* now get effective bits from the algorithm ID. */
860 param = PK11_ParamFromAlgid(algid);
861 /* if we couldn't get memory just use key length */
862 if (param == NULL((void*)0)) {
863 break;
864 }
865
866 rc2_params = (CK_RC2_CBC_PARAMS *)param->data;
867 /* paranoia... shouldn't happen */
868 PORT_Assert(param->data != NULL)((param->data != ((void*)0))?((void)0):PR_Assert("param->data != NULL"
,"pk11skey.c",868))
;
869 if (param->data == NULL((void*)0)) {
870 SECITEM_FreeItemSECITEM_FreeItem_Util(param, PR_TRUE1);
871 break;
872 }
873 effectiveBits = (unsigned int)rc2_params->ulEffectiveBits;
874 SECITEM_FreeItemSECITEM_FreeItem_Util(param, PR_TRUE1);
875 param = NULL((void*)0);
876 rc2_params = NULL((void*)0); /* paranoia */
877
878 /* we have effective bits, is and allocated memory is free, now
879 * we need to return the smaller of effective bits and keysize */
880 size = PK11_GetKeyLength(key);
881 if ((unsigned int)size * 8 > effectiveBits) {
882 return effectiveBits;
883 }
884
885 return size * 8; /* the actual key is smaller, the strength can't be
886 * greater than the actual key size */
887
888 default:
889 break;
890 }
891 return PK11_GetKeyLength(key) * 8;
892}
893
894/*
895 * The next three utilities are to deal with the fact that a given operation
896 * may be a multi-slot affair. This creates a new key object that is copied
897 * into the new slot.
898 */
899PK11SymKey *
900pk11_CopyToSlotPerm(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
901 CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags,
902 PRBool isPerm, PK11SymKey *symKey)
903{
904 SECStatus rv;
905 PK11SymKey *newKey = NULL((void*)0);
906
907 /* Extract the raw key data if possible */
908 if (symKey->data.data == NULL((void*)0)) {
909 rv = PK11_ExtractKeyValue(symKey);
910 /* KEY is sensitive, we're try key exchanging it. */
911 if (rv != SECSuccess) {
912 return pk11_KeyExchange(slot, type, operation,
913 flags, isPerm, symKey);
914 }
915 }
916
917 newKey = PK11_ImportSymKeyWithFlags(slot, type, symKey->origin,
918 operation, &symKey->data, flags, isPerm, symKey->cx);
919 if (newKey == NULL((void*)0)) {
920 newKey = pk11_KeyExchange(slot, type, operation, flags, isPerm, symKey);
921 }
922 return newKey;
923}
924
925PK11SymKey *
926pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
927 CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey)
928{
929 return pk11_CopyToSlotPerm(slot, type, operation, 0, PR_FALSE0, symKey);
930}
931
932/*
933 * Make sure the slot we are in is the correct slot for the operation
934 * by verifying that it supports all of the specified mechanism types.
935 */
936PK11SymKey *
937pk11_ForceSlotMultiple(PK11SymKey *symKey, CK_MECHANISM_TYPE *type,
938 int mechCount, CK_ATTRIBUTE_TYPE operation)
939{
940 PK11SlotInfo *slot = symKey->slot;
941 PK11SymKey *newKey = NULL((void*)0);
942 PRBool needToCopy = PR_FALSE0;
943 int i;
944
945 if (slot == NULL((void*)0)) {
946 needToCopy = PR_TRUE1;
947 } else {
948 i = 0;
949 while ((i < mechCount) && (needToCopy == PR_FALSE0)) {
950 if (!PK11_DoesMechanism(slot, type[i])) {
951 needToCopy = PR_TRUE1;
952 }
953 i++;
954 }
955 }
956
957 if (needToCopy == PR_TRUE1) {
958 slot = PK11_GetBestSlotMultiple(type, mechCount, symKey->cx);
959 if (slot == NULL((void*)0)) {
960 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
961 return NULL((void*)0);
962 }
963 newKey = pk11_CopyToSlot(slot, type[0], operation, symKey);
964 PK11_FreeSlot(slot);
965 }
966 return newKey;
967}
968
969/*
970 * Make sure the slot we are in is the correct slot for the operation
971 */
972PK11SymKey *
973pk11_ForceSlot(PK11SymKey *symKey, CK_MECHANISM_TYPE type,
974 CK_ATTRIBUTE_TYPE operation)
975{
976 return pk11_ForceSlotMultiple(symKey, &type, 1, operation);
977}
978
979PK11SymKey *
980PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation,
981 CK_FLAGS flags, PRBool perm, PK11SymKey *symKey)
982{
983 if (symKey->slot == slot) {
984 if (perm) {
985 return PK11_ConvertSessionSymKeyToTokenSymKey(symKey, symKey->cx);
986 } else {
987 return PK11_ReferenceSymKey(symKey);
988 }
989 }
990
991 return pk11_CopyToSlotPerm(slot, symKey->type,
992 operation, flags, perm, symKey);
993}
994
995/*
996 * Use the token to generate a key.
997 *
998 * keySize must be 'zero' for fixed key length algorithms. A nonzero
999 * keySize causes the CKA_VALUE_LEN attribute to be added to the template
1000 * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN
1001 * attribute for keys with fixed length. The exception is DES2. If you
1002 * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN
1003 * parameter and use the key size to determine which underlying DES keygen
1004 * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN).
1005 *
1006 * keyType must be -1 for most algorithms. Some PBE algorthims cannot
1007 * determine the correct key type from the mechanism or the parameters,
1008 * so key type must be specified. Other PKCS #11 mechanisms may do so in
1009 * the future. Currently there is no need to export this publically.
1010 * Keep it private until there is a need in case we need to expand the
1011 * keygen parameters again...
1012 *
1013 * CK_FLAGS flags: key operation flags
1014 * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags
1015 */
1016PK11SymKey *
1017pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
1018 SECItem *param, CK_KEY_TYPE keyType, int keySize, SECItem *keyid,
1019 CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx)
1020{
1021 PK11SymKey *symKey;
1022 CK_ATTRIBUTE genTemplate[MAX_TEMPL_ATTRS16];
1023 CK_ATTRIBUTE *attrs = genTemplate;
1024 int count = sizeof(genTemplate) / sizeof(genTemplate[0]);
1025 CK_MECHANISM_TYPE keyGenType;
1026 CK_BBOOL cktrue = CK_TRUE1;
1027 CK_BBOOL ckfalse = CK_FALSE0;
1028 CK_ULONG ck_key_size; /* only used for variable-length keys */
1029
1030 if (pk11_BadAttrFlags(attrFlags)) {
1031 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1032 return NULL((void*)0);
1033 }
1034
1035 if ((keySize != 0) && (type != CKM_DES3_CBC0x00000133UL) &&
1036 (type != CKM_DES3_CBC_PAD0x00000136UL) && (type != CKM_DES3_ECB0x00000132UL)) {
1037 ck_key_size = keySize; /* Convert to PK11 type */
1038
1039 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &ck_key_size, sizeof(ck_key_size))(attrs)->type = (0x00000161UL); (attrs)->pValue = (&
ck_key_size); (attrs)->ulValueLen = (sizeof(ck_key_size));
;
1040 attrs++;
1041 }
1042
1043 if (keyType != -1) {
1044 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE))(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof(CK_KEY_TYPE));
;
1045 attrs++;
1046 }
1047
1048 /* Include key id value if provided */
1049 if (keyid) {
1050 PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len)(attrs)->type = (0x00000102UL); (attrs)->pValue = (keyid
->data); (attrs)->ulValueLen = (keyid->len);
;
1051 attrs++;
1052 }
1053
1054 attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse);
1055 attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue);
1056
1057 count = attrs - genTemplate;
1058 PR_ASSERT(count <= sizeof(genTemplate) / sizeof(CK_ATTRIBUTE))((count <= sizeof(genTemplate) / sizeof(CK_ATTRIBUTE))?((void
)0):PR_Assert("count <= sizeof(genTemplate) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",1058))
;
1059
1060 keyGenType = PK11_GetKeyGenWithSize(type, keySize);
1061 if (keyGenType == CKM_FAKE_RANDOM0x80000efeUL) {
1062 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
1063 return NULL((void*)0);
1064 }
1065 symKey = PK11_KeyGenWithTemplate(slot, type, keyGenType,
1066 param, genTemplate, count, wincx);
1067 if (symKey != NULL((void*)0)) {
1068 symKey->size = keySize;
1069 }
1070 return symKey;
1071}
1072
1073/*
1074 * Use the token to generate a key. - Public
1075 *
1076 * keySize must be 'zero' for fixed key length algorithms. A nonzero
1077 * keySize causes the CKA_VALUE_LEN attribute to be added to the template
1078 * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN
1079 * attribute for keys with fixed length. The exception is DES2. If you
1080 * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN
1081 * parameter and use the key size to determine which underlying DES keygen
1082 * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN).
1083 *
1084 * CK_FLAGS flags: key operation flags
1085 * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags
1086 */
1087PK11SymKey *
1088PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
1089 SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags,
1090 PK11AttrFlags attrFlags, void *wincx)
1091{
1092 return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, -1, keySize,
1093 keyid, opFlags, attrFlags, wincx);
1094}
1095
1096/*
1097 * Use the token to generate a key. keySize must be 'zero' for fixed key
1098 * length algorithms. A nonzero keySize causes the CKA_VALUE_LEN attribute
1099 * to be added to the template for the key. PKCS #11 modules fail if you
1100 * specify the CKA_VALUE_LEN attribute for keys with fixed length.
1101 * NOTE: this means to generate a DES2 key from this interface you must
1102 * specify CKM_DES2_KEY_GEN as the mechanism directly; specifying
1103 * CKM_DES3_CBC as the mechanism and 16 as keySize currently doesn't work.
1104 */
1105PK11SymKey *
1106PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
1107 int keySize, SECItem *keyid, PRBool isToken, void *wincx)
1108{
1109 PK11SymKey *symKey;
1110 PRBool weird = PR_FALSE0; /* hack for fortezza */
1111 CK_FLAGS opFlags = CKF_SIGN0x00000800UL;
1112 PK11AttrFlags attrFlags = 0;
1113
1114 if ((keySize == -1) && (type == CKM_SKIPJACK_CBC640x00001002UL)) {
1115 weird = PR_TRUE1;
1116 keySize = 0;
1117 }
1118
1119 opFlags |= weird ? CKF_DECRYPT0x00000200UL : CKF_ENCRYPT0x00000100UL;
1120
1121 if (isToken) {
1122 attrFlags |= (PK11_ATTR_TOKEN0x00000001L | PK11_ATTR_PRIVATE0x00000004L);
1123 }
1124
1125 symKey = pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param,
1126 -1, keySize, keyid, opFlags, attrFlags, wincx);
1127 if (symKey && weird) {
1128 PK11_SetFortezzaHack(symKey);
1129 }
1130
1131 return symKey;
1132}
1133
1134PK11SymKey *
1135PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
1136 int keySize, void *wincx)
1137{
1138 return PK11_TokenKeyGen(slot, type, param, keySize, 0, PR_FALSE0, wincx);
1139}
1140
1141PK11SymKey *
1142PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
1143 CK_MECHANISM_TYPE keyGenType,
1144 SECItem *param, CK_ATTRIBUTE *attrs,
1145 unsigned int attrsCount, void *wincx)
1146{
1147 PK11SymKey *symKey;
1148 CK_SESSION_HANDLE session;
1149 CK_MECHANISM mechanism;
1150 CK_RV crv;
1151 PRBool isToken = CK_FALSE0;
1152 CK_ULONG keySize = 0;
1153 unsigned i;
1154
1155 /* Extract the template's CKA_VALUE_LEN into keySize and CKA_TOKEN into
1156 isToken. */
1157 for (i = 0; i < attrsCount; ++i) {
1158 switch (attrs[i].type) {
1159 case CKA_VALUE_LEN0x00000161UL:
1160 if (attrs[i].pValue == NULL((void*)0) ||
1161 attrs[i].ulValueLen != sizeof(CK_ULONG)) {
1162 PORT_SetErrorPORT_SetError_Util(PK11_MapError(CKR_TEMPLATE_INCONSISTENT0x000000D1UL));
1163 return NULL((void*)0);
1164 }
1165 keySize = *(CK_ULONG *)attrs[i].pValue;
1166 break;
1167 case CKA_TOKEN0x00000001UL:
1168 if (attrs[i].pValue == NULL((void*)0) ||
1169 attrs[i].ulValueLen != sizeof(CK_BBOOL)) {
1170 PORT_SetErrorPORT_SetError_Util(PK11_MapError(CKR_TEMPLATE_INCONSISTENT0x000000D1UL));
1171 return NULL((void*)0);
1172 }
1173 isToken = (*(CK_BBOOL *)attrs[i].pValue) ? PR_TRUE1 : PR_FALSE0;
1174 break;
1175 }
1176 }
1177
1178 /* find a slot to generate the key into */
1179 /* Only do slot management if this is not a token key */
1180 if (!isToken && (slot == NULL((void*)0) || !PK11_DoesMechanism(slot, type))) {
1181 PK11SlotInfo *bestSlot = PK11_GetBestSlot(type, wincx);
1182 if (bestSlot == NULL((void*)0)) {
1183 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
1184 return NULL((void*)0);
1185 }
1186 symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE1, wincx);
1187 PK11_FreeSlot(bestSlot);
1188 } else {
1189 symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE1, wincx);
1190 }
1191 if (symKey == NULL((void*)0))
1192 return NULL((void*)0);
1193
1194 symKey->size = keySize;
1195 symKey->origin = PK11_OriginGenerated;
1196
1197 /* Set the parameters for the key gen if provided */
1198 mechanism.mechanism = keyGenType;
1199 mechanism.pParameter = NULL((void*)0);
1200 mechanism.ulParameterLen = 0;
1201 if (param) {
1202 mechanism.pParameter = param->data;
1203 mechanism.ulParameterLen = param->len;
1204 }
1205
1206 /* Get session and perform locking */
1207 if (isToken) {
1208 PK11_Authenticate(symKey->slot, PR_TRUE1, wincx);
1209 /* Should always be original slot */
1210 session = PK11_GetRWSession(symKey->slot);
1211 symKey->owner = PR_FALSE0;
1212 } else {
1213 session = symKey->session;
1214 if (session != CK_INVALID_HANDLE0)
1215 pk11_EnterKeyMonitor(symKey);
1216 }
1217 if (session == CK_INVALID_HANDLE0) {
1218 PK11_FreeSymKey(symKey);
1219 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA);
1220 return NULL((void*)0);
1221 }
1222
1223 crv = PK11_GETTAB(symKey->slot)((CK_FUNCTION_LIST_3_0_PTR)((symKey->slot)->functionList
))
->C_GenerateKey(session, &mechanism, attrs, attrsCount, &symKey->objectID);
1224
1225 /* Release lock and session */
1226 if (isToken) {
1227 PK11_RestoreROSession(symKey->slot, session);
1228 } else {
1229 pk11_ExitKeyMonitor(symKey);
1230 }
1231
1232 if (crv != CKR_OK0x00000000UL) {
1233 PK11_FreeSymKey(symKey);
1234 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1235 return NULL((void*)0);
1236 }
1237
1238 return symKey;
1239}
1240
1241/* --- */
1242PK11SymKey *
1243PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx)
1244{
1245 return PK11_TokenKeyGen(slot, CKM_DES3_CBC0x00000133UL, 0, 0, keyid, PR_TRUE1, cx);
1246}
1247
1248PK11SymKey *
1249PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk, void *wincx)
1250{
1251 PK11SlotInfo *slot = symk->slot;
1252 CK_ATTRIBUTE template[1];
1253 CK_ATTRIBUTE *attrs = template;
1254 CK_BBOOL cktrue = CK_TRUE1;
1255 CK_RV crv;
1256 CK_OBJECT_HANDLE newKeyID;
1257 CK_SESSION_HANDLE rwsession;
1258
1259 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue))(attrs)->type = (0x00000001UL); (attrs)->pValue = (&
cktrue); (attrs)->ulValueLen = (sizeof(cktrue));
;
1260 attrs++;
1261
1262 PK11_Authenticate(slot, PR_TRUE1, wincx);
1263 rwsession = PK11_GetRWSession(slot);
1264 if (rwsession == CK_INVALID_HANDLE0) {
1265 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA);
1266 return NULL((void*)0);
1267 }
1268 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_CopyObject(rwsession, symk->objectID,
1269 template, 1, &newKeyID);
1270 PK11_RestoreROSession(slot, rwsession);
1271
1272 if (crv != CKR_OK0x00000000UL) {
1273 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1274 return NULL((void*)0);
1275 }
1276
1277 return PK11_SymKeyFromHandle(slot, NULL((void*)0) /*parent*/, symk->origin,
1278 symk->type, newKeyID, PR_FALSE0 /*owner*/, NULL((void*)0) /*wincx*/);
1279}
1280
1281/* This function does a straight public key wrap with the CKM_RSA_PKCS
1282 * mechanism. */
1283SECStatus
1284PK11_PubWrapSymKey(CK_MECHANISM_TYPE type, SECKEYPublicKey *pubKey,
1285 PK11SymKey *symKey, SECItem *wrappedKey)
1286{
1287 CK_MECHANISM_TYPE inferred = pk11_mapWrapKeyType(pubKey->keyType);
1288 return PK11_PubWrapSymKeyWithMechanism(pubKey, inferred, NULL((void*)0), symKey,
1289 wrappedKey);
1290}
1291
1292/* This function wraps a symmetric key with a public key, such as with the
1293 * CKM_RSA_PKCS and CKM_RSA_PKCS_OAEP mechanisms. */
1294SECStatus
1295PK11_PubWrapSymKeyWithMechanism(SECKEYPublicKey *pubKey,
1296 CK_MECHANISM_TYPE mechType, SECItem *param,
1297 PK11SymKey *symKey, SECItem *wrappedKey)
1298{
1299 PK11SlotInfo *slot;
1300 CK_ULONG len = wrappedKey->len;
1301 PK11SymKey *newKey = NULL((void*)0);
1302 CK_OBJECT_HANDLE id;
1303 CK_MECHANISM mechanism;
1304 PRBool owner = PR_TRUE1;
1305 CK_SESSION_HANDLE session;
1306 CK_RV crv;
1307
1308 if (symKey == NULL((void*)0)) {
1309 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1310 return SECFailure;
1311 }
1312
1313 /* if this slot doesn't support the mechanism, go to a slot that does */
1314 newKey = pk11_ForceSlot(symKey, mechType, CKA_ENCRYPT0x00000104UL);
1315 if (newKey != NULL((void*)0)) {
1316 symKey = newKey;
1317 }
1318
1319 if (symKey->slot == NULL((void*)0)) {
1320 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
1321 return SECFailure;
1322 }
1323
1324 slot = symKey->slot;
1325
1326 mechanism.mechanism = mechType;
1327 if (param == NULL((void*)0)) {
1328 mechanism.pParameter = NULL((void*)0);
1329 mechanism.ulParameterLen = 0;
1330 } else {
1331 mechanism.pParameter = param->data;
1332 mechanism.ulParameterLen = param->len;
1333 }
1334
1335 id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE0);
1336 if (id == CK_INVALID_HANDLE0) {
1337 if (newKey) {
1338 PK11_FreeSymKey(newKey);
1339 }
1340 return SECFailure; /* Error code has been set. */
1341 }
1342
1343 session = pk11_GetNewSession(slot, &owner);
1344 if (!owner || !(slot->isThreadSafe))
1345 PK11_EnterSlotMonitor(slot);
1346 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_WrapKey(session, &mechanism,
1347 id, symKey->objectID, wrappedKey->data, &len);
1348 if (!owner || !(slot->isThreadSafe))
1349 PK11_ExitSlotMonitor(slot);
1350 pk11_CloseSession(slot, session, owner);
1351 if (newKey) {
1352 PK11_FreeSymKey(newKey);
1353 }
1354
1355 if (crv != CKR_OK0x00000000UL) {
1356 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1357 return SECFailure;
1358 }
1359 wrappedKey->len = len;
1360 return SECSuccess;
1361}
1362
1363/*
1364 * this little function uses the Encrypt function to wrap a key, just in
1365 * case we have problems with the wrap implementation for a token.
1366 */
1367static SECStatus
1368pk11_HandWrap(PK11SymKey *wrappingKey, SECItem *param, CK_MECHANISM_TYPE type,
1369 SECItem *inKey, SECItem *outKey)
1370{
1371 PK11SlotInfo *slot;
1372 CK_ULONG len;
1373 SECItem *data;
1374 CK_MECHANISM mech;
1375 PRBool owner = PR_TRUE1;
1376 CK_SESSION_HANDLE session;
1377 CK_RV crv;
1378
1379 slot = wrappingKey->slot;
1380 /* use NULL IV's for wrapping */
1381 mech.mechanism = type;
1382 if (param) {
1383 mech.pParameter = param->data;
1384 mech.ulParameterLen = param->len;
1385 } else {
1386 mech.pParameter = NULL((void*)0);
1387 mech.ulParameterLen = 0;
1388 }
1389 session = pk11_GetNewSession(slot, &owner);
1390 if (!owner || !(slot->isThreadSafe))
1391 PK11_EnterSlotMonitor(slot);
1392 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_EncryptInit(session, &mech,
1393 wrappingKey->objectID);
1394 if (crv != CKR_OK0x00000000UL) {
1395 if (!owner || !(slot->isThreadSafe))
1396 PK11_ExitSlotMonitor(slot);
1397 pk11_CloseSession(slot, session, owner);
1398 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1399 return SECFailure;
1400 }
1401
1402 /* keys are almost always aligned, but if we get this far,
1403 * we've gone above and beyond anyway... */
1404 data = PK11_BlockData(inKey, PK11_GetBlockSize(type, param));
1405 if (data == NULL((void*)0)) {
1406 if (!owner || !(slot->isThreadSafe))
1407 PK11_ExitSlotMonitor(slot);
1408 pk11_CloseSession(slot, session, owner);
1409 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
1410 return SECFailure;
1411 }
1412 len = outKey->len;
1413 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_Encrypt(session, data->data, data->len,
1414 outKey->data, &len);
1415 if (!owner || !(slot->isThreadSafe))
1416 PK11_ExitSlotMonitor(slot);
1417 pk11_CloseSession(slot, session, owner);
1418 SECITEM_FreeItemSECITEM_FreeItem_Util(data, PR_TRUE1);
1419 outKey->len = len;
1420 if (crv != CKR_OK0x00000000UL) {
1421 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1422 return SECFailure;
1423 }
1424 return SECSuccess;
1425}
1426
1427/*
1428 * helper function which moves two keys into a new slot based on the
1429 * desired mechanism.
1430 */
1431static SECStatus
1432pk11_moveTwoKeys(CK_MECHANISM_TYPE mech,
1433 CK_ATTRIBUTE_TYPE preferedOperation,
1434 CK_ATTRIBUTE_TYPE movingOperation,
1435 PK11SymKey *preferedKey, PK11SymKey *movingKey,
1436 PK11SymKey **newPreferedKey, PK11SymKey **newMovingKey)
1437{
1438 PK11SlotInfo *newSlot;
1439 *newMovingKey = NULL((void*)0);
1440 *newPreferedKey = NULL((void*)0);
1441
1442 newSlot = PK11_GetBestSlot(mech, preferedKey->cx);
1443 if (newSlot == NULL((void*)0)) {
1444 return SECFailure;
1445 }
1446 *newMovingKey = pk11_CopyToSlot(newSlot, movingKey->type,
1447 movingOperation, movingKey);
1448 if (*newMovingKey == NULL((void*)0)) {
1449 goto loser;
1450 }
1451 *newPreferedKey = pk11_CopyToSlot(newSlot, preferedKey->type,
1452 preferedOperation, preferedKey);
1453 if (*newPreferedKey == NULL((void*)0)) {
1454 goto loser;
1455 }
1456
1457 PK11_FreeSlot(newSlot);
1458 return SECSuccess;
1459loser:
1460 PK11_FreeSlot(newSlot);
1461 PK11_FreeSymKey(*newMovingKey);
1462 PK11_FreeSymKey(*newPreferedKey);
1463 *newMovingKey = NULL((void*)0);
1464 *newPreferedKey = NULL((void*)0);
1465 return SECFailure;
1466}
1467
1468/*
1469 * To do joint operations, we often need two keys in the same slot.
1470 * Usually the PKCS #11 wrappers handle this correctly (like for PK11_WrapKey),
1471 * but sometimes the wrappers don't know about mechanism specific keys in
1472 * the Mechanism params. This function makes sure the two keys are in the
1473 * same slot by copying one or both of the keys into a common slot. This
1474 * functions makes sure the slot can handle the target mechanism. If the copy
1475 * is warranted, this function will prefer to move the movingKey first, then
1476 * the preferedKey. If the keys are moved, the new keys are returned in
1477 * newMovingKey and/or newPreferedKey. The application is responsible
1478 * for freeing those keys once the operation is complete.
1479 */
1480SECStatus
1481PK11_SymKeysToSameSlot(CK_MECHANISM_TYPE mech,
1482 CK_ATTRIBUTE_TYPE preferedOperation,
1483 CK_ATTRIBUTE_TYPE movingOperation,
1484 PK11SymKey *preferedKey, PK11SymKey *movingKey,
1485 PK11SymKey **newPreferedKey, PK11SymKey **newMovingKey)
1486{
1487 /* usually don't return new keys */
1488 *newMovingKey = NULL((void*)0);
1489 *newPreferedKey = NULL((void*)0);
1490 if (movingKey->slot == preferedKey->slot) {
1491
1492 /* this should be the most common case */
1493 if ((preferedKey->slot != NULL((void*)0)) &&
1494 PK11_DoesMechanism(preferedKey->slot, mech)) {
1495 return SECSuccess;
1496 }
1497
1498 /* we are in the same slot, but it doesn't do the operation,
1499 * move both keys to an appropriate target slot */
1500 return pk11_moveTwoKeys(mech, preferedOperation, movingOperation,
1501 preferedKey, movingKey,
1502 newPreferedKey, newMovingKey);
1503 }
1504
1505 /* keys are in different slot, try moving the moving key to the prefered
1506 * key's slot */
1507 if ((preferedKey->slot != NULL((void*)0)) &&
1508 PK11_DoesMechanism(preferedKey->slot, mech)) {
1509 *newMovingKey = pk11_CopyToSlot(preferedKey->slot, movingKey->type,
1510 movingOperation, movingKey);
1511 if (*newMovingKey != NULL((void*)0)) {
1512 return SECSuccess;
1513 }
1514 }
1515 /* couldn't moving the moving key to the prefered slot, try moving
1516 * the prefered key */
1517 if ((movingKey->slot != NULL((void*)0)) &&
1518 PK11_DoesMechanism(movingKey->slot, mech)) {
1519 *newPreferedKey = pk11_CopyToSlot(movingKey->slot, preferedKey->type,
1520 preferedOperation, preferedKey);
1521 if (*newPreferedKey != NULL((void*)0)) {
1522 return SECSuccess;
1523 }
1524 }
1525 /* Neither succeeded, but that could be that they were not in slots that
1526 * supported the operation, try moving both keys into a common slot that
1527 * can do the operation. */
1528 return pk11_moveTwoKeys(mech, preferedOperation, movingOperation,
1529 preferedKey, movingKey,
1530 newPreferedKey, newMovingKey);
1531}
1532
1533/*
1534 * This function does a symetric based wrap.
1535 */
1536SECStatus
1537PK11_WrapSymKey(CK_MECHANISM_TYPE type, SECItem *param,
1538 PK11SymKey *wrappingKey, PK11SymKey *symKey,
1539 SECItem *wrappedKey)
1540{
1541 PK11SlotInfo *slot;
1542 CK_ULONG len = wrappedKey->len;
1543 PK11SymKey *newSymKey = NULL((void*)0);
1544 PK11SymKey *newWrappingKey = NULL((void*)0);
1545 SECItem *param_save = NULL((void*)0);
1546 CK_MECHANISM mechanism;
1547 PRBool owner = PR_TRUE1;
1548 CK_SESSION_HANDLE session;
1549 CK_RV crv;
1550 SECStatus rv;
1551
1552 /* force the keys into same slot */
1553 rv = PK11_SymKeysToSameSlot(type, CKA_ENCRYPT0x00000104UL, CKA_WRAP0x00000106UL,
1554 symKey, wrappingKey,
1555 &newSymKey, &newWrappingKey);
1556 if (rv != SECSuccess) {
1557 /* Couldn't move the keys as desired, try to hand unwrap if possible */
1558 if (symKey->data.data == NULL((void*)0)) {
1559 rv = PK11_ExtractKeyValue(symKey);
1560 if (rv != SECSuccess) {
1561 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
1562 return SECFailure;
1563 }
1564 }
1565 if (param == NULL((void*)0)) {
1566 param_save = param = PK11_ParamFromIV(type, NULL((void*)0));
1567 }
1568 rv = pk11_HandWrap(wrappingKey, param, type, &symKey->data, wrappedKey);
1569 if (param_save)
1570 SECITEM_FreeItemSECITEM_FreeItem_Util(param_save, PR_TRUE1);
1571 return rv;
1572 }
1573 if (newSymKey) {
1574 symKey = newSymKey;
1575 }
1576 if (newWrappingKey) {
1577 wrappingKey = newWrappingKey;
1578 }
1579
1580 /* at this point both keys are in the same token */
1581 slot = wrappingKey->slot;
1582 mechanism.mechanism = type;
1583 /* use NULL IV's for wrapping */
1584 if (param == NULL((void*)0)) {
1585 param_save = param = PK11_ParamFromIV(type, NULL((void*)0));
1586 }
1587 if (param) {
1588 mechanism.pParameter = param->data;
1589 mechanism.ulParameterLen = param->len;
1590 } else {
1591 mechanism.pParameter = NULL((void*)0);
1592 mechanism.ulParameterLen = 0;
1593 }
1594
1595 len = wrappedKey->len;
1596
1597 session = pk11_GetNewSession(slot, &owner);
1598 if (!owner || !(slot->isThreadSafe))
1599 PK11_EnterSlotMonitor(slot);
1600 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_WrapKey(session, &mechanism,
1601 wrappingKey->objectID, symKey->objectID,
1602 wrappedKey->data, &len);
1603 if (!owner || !(slot->isThreadSafe))
1604 PK11_ExitSlotMonitor(slot);
1605 pk11_CloseSession(slot, session, owner);
1606 rv = SECSuccess;
1607 if (crv != CKR_OK0x00000000UL) {
1608 /* can't wrap it? try hand wrapping it... */
1609 do {
1610 if (symKey->data.data == NULL((void*)0)) {
1611 rv = PK11_ExtractKeyValue(symKey);
1612 if (rv != SECSuccess)
1613 break;
1614 }
1615 rv = pk11_HandWrap(wrappingKey, param, type, &symKey->data,
1616 wrappedKey);
1617 } while (PR_FALSE0);
1618 } else {
1619 wrappedKey->len = len;
1620 }
1621 PK11_FreeSymKey(newSymKey);
1622 PK11_FreeSymKey(newWrappingKey);
1623 if (param_save)
1624 SECITEM_FreeItemSECITEM_FreeItem_Util(param_save, PR_TRUE1);
1625 return rv;
1626}
1627
1628/*
1629 * This Generates a new key based on a symetricKey
1630 */
1631PK11SymKey *
1632PK11_Derive(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, SECItem *param,
1633 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1634 int keySize)
1635{
1636 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
1637 keySize, NULL((void*)0), 0, PR_FALSE0);
1638}
1639
1640PK11SymKey *
1641PK11_DeriveWithFlags(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
1642 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1643 int keySize, CK_FLAGS flags)
1644{
1645 CK_BBOOL ckTrue = CK_TRUE1;
1646 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16];
1647 unsigned int templateCount;
1648
1649 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
1650 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
1651 keySize, keyTemplate, templateCount, PR_FALSE0);
1652}
1653
1654PK11SymKey *
1655PK11_DeriveWithFlagsPerm(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
1656 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1657 int keySize, CK_FLAGS flags, PRBool isPerm)
1658{
1659 CK_BBOOL cktrue = CK_TRUE1;
1660 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16];
1661 CK_ATTRIBUTE *attrs;
1662 unsigned int templateCount = 0;
1663
1664 attrs = keyTemplate;
1665 if (isPerm) {
1666 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL))(attrs)->type = (0x00000001UL); (attrs)->pValue = (&
cktrue); (attrs)->ulValueLen = (sizeof(CK_BBOOL));
;
1667 attrs++;
1668 }
1669 templateCount = attrs - keyTemplate;
1670 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
1671 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
1672 keySize, keyTemplate, templateCount, isPerm);
1673}
1674
1675PK11SymKey *
1676PK11_DeriveWithTemplate(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
1677 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1678 int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs,
1679 PRBool isPerm)
1680{
1681 PK11SlotInfo *slot = baseKey->slot;
1682 PK11SymKey *symKey;
1683 PK11SymKey *newBaseKey = NULL((void*)0);
1684 CK_BBOOL cktrue = CK_TRUE1;
1685 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY0x00000004UL;
1686 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET0x00000010UL;
1687 CK_ULONG valueLen = 0;
1688 CK_MECHANISM mechanism;
1689 CK_RV crv;
1690#define MAX_ADD_ATTRS 4
1691 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16 + MAX_ADD_ATTRS];
1692#undef MAX_ADD_ATTRS
1693 CK_ATTRIBUTE *attrs = keyTemplate;
1694 CK_SESSION_HANDLE session;
1695 unsigned int templateCount;
1696
1697 if (numAttrs > MAX_TEMPL_ATTRS16) {
1698 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1699 return NULL((void*)0);
1700 }
1701 /* CKA_NSS_MESSAGE is a fake operation to distinguish between
1702 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set
1703 * it as a real attribute */
1704 if ((operation & CKA_NSS_MESSAGE_MASK0xff000000L) == CKA_NSS_MESSAGE0x82000000L) {
1705 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT),
1706 * etc. Strip out the real attribute here */
1707 operation &= ~CKA_NSS_MESSAGE_MASK0xff000000L;
1708 }
1709
1710 /* first copy caller attributes in. */
1711 for (templateCount = 0; templateCount < numAttrs; ++templateCount) {
1712 *attrs++ = *userAttr++;
1713 }
1714
1715 /* We only add the following attributes to the template if the caller
1716 ** didn't already supply them.
1717 */
1718 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS0x00000000UL)) {
1719 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass)(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyClass); (attrs)->ulValueLen = (sizeof keyClass);
;
1720 attrs++;
1721 }
1722 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE0x00000100UL)) {
1723 keyType = PK11_GetKeyType(target, keySize);
1724 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType)(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof keyType);
;
1725 attrs++;
1726 }
1727 if (keySize > 0 &&
1728 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN0x00000161UL)) {
1729 valueLen = (CK_ULONG)keySize;
1730 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen)(attrs)->type = (0x00000161UL); (attrs)->pValue = (&
valueLen); (attrs)->ulValueLen = (sizeof valueLen);
;
1731 attrs++;
1732 }
1733 if ((operation != CKA_FLAGS_ONLY0) &&
1734 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) {
1735 PK11_SETATTRS(attrs, operation, &cktrue, sizeof cktrue)(attrs)->type = (operation); (attrs)->pValue = (&cktrue
); (attrs)->ulValueLen = (sizeof cktrue);
;
1736 attrs++;
1737 }
1738
1739 templateCount = attrs - keyTemplate;
1740 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE))((templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE
))?((void)0):PR_Assert("templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",1740))
;
1741
1742 /* move the key to a slot that can do the function */
1743 if (!PK11_DoesMechanism(slot, derive)) {
1744 /* get a new base key & slot */
1745 PK11SlotInfo *newSlot = PK11_GetBestSlot(derive, baseKey->cx);
1746
1747 if (newSlot == NULL((void*)0))
1748 return NULL((void*)0);
1749
1750 newBaseKey = pk11_CopyToSlot(newSlot, derive, CKA_DERIVE0x0000010CUL,
1751 baseKey);
1752 PK11_FreeSlot(newSlot);
1753 if (newBaseKey == NULL((void*)0))
1754 return NULL((void*)0);
1755 baseKey = newBaseKey;
1756 slot = baseKey->slot;
1757 }
1758
1759 /* get our key Structure */
1760 symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE1, baseKey->cx);
1761 if (symKey == NULL((void*)0)) {
1762 return NULL((void*)0);
1763 }
1764
1765 symKey->size = keySize;
1766
1767 mechanism.mechanism = derive;
1768 if (param) {
1769 mechanism.pParameter = param->data;
1770 mechanism.ulParameterLen = param->len;
1771 } else {
1772 mechanism.pParameter = NULL((void*)0);
1773 mechanism.ulParameterLen = 0;
1774 }
1775 symKey->origin = PK11_OriginDerive;
1776
1777 if (isPerm) {
1778 session = PK11_GetRWSession(slot);
1779 } else {
1780 pk11_EnterKeyMonitor(symKey);
1781 session = symKey->session;
1782 }
1783 if (session == CK_INVALID_HANDLE0) {
1784 if (!isPerm)
1785 pk11_ExitKeyMonitor(symKey);
1786 crv = CKR_SESSION_HANDLE_INVALID0x000000B3UL;
1787 } else {
1788 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DeriveKey(session, &mechanism,
1789 baseKey->objectID, keyTemplate, templateCount, &symKey->objectID);
1790 if (isPerm) {
1791 PK11_RestoreROSession(slot, session);
1792 } else {
1793 pk11_ExitKeyMonitor(symKey);
1794 }
1795 }
1796 if (newBaseKey)
1797 PK11_FreeSymKey(newBaseKey);
1798 if (crv != CKR_OK0x00000000UL) {
1799 PK11_FreeSymKey(symKey);
1800 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1801 return NULL((void*)0);
1802 }
1803 return symKey;
1804}
1805
1806/* Create a new key by concatenating base and data
1807 */
1808static PK11SymKey *
1809pk11_ConcatenateBaseAndData(PK11SymKey *base,
1810 CK_BYTE *data, CK_ULONG dataLen, CK_MECHANISM_TYPE target,
1811 CK_ATTRIBUTE_TYPE operation)
1812{
1813 CK_KEY_DERIVATION_STRING_DATA mechParams;
1814 SECItem param;
1815
1816 if (base == NULL((void*)0)) {
1817 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1818 return NULL((void*)0);
1819 }
1820
1821 mechParams.pData = data;
1822 mechParams.ulLen = dataLen;
1823 param.data = (unsigned char *)&mechParams;
1824 param.len = sizeof(CK_KEY_DERIVATION_STRING_DATA);
1825
1826 return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_DATA0x00000362UL,
1827 &param, target, operation, 0);
1828}
1829
1830/* Create a new key by concatenating base and key
1831 */
1832static PK11SymKey *
1833pk11_ConcatenateBaseAndKey(PK11SymKey *base,
1834 PK11SymKey *key, CK_MECHANISM_TYPE target,
1835 CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize)
1836{
1837 SECItem param;
1838
1839 if ((base == NULL((void*)0)) || (key == NULL((void*)0))) {
1840 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1841 return NULL((void*)0);
1842 }
1843
1844 param.data = (unsigned char *)&(key->objectID);
1845 param.len = sizeof(CK_OBJECT_HANDLE);
1846
1847 return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_KEY0x00000360UL,
1848 &param, target, operation, keySize);
1849}
1850
1851PK11SymKey *
1852PK11_ConcatSymKeys(PK11SymKey *left, PK11SymKey *right, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation)
1853{
1854 PK11SymKey *out = NULL((void*)0);
1855 PK11SymKey *copyOfLeft = NULL((void*)0);
1856 PK11SymKey *copyOfRight = NULL((void*)0);
1857
1858 if ((left == NULL((void*)0)) || (right == NULL((void*)0))) {
1859 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1860 return NULL((void*)0);
1861 }
1862
1863 SECStatus rv = PK11_SymKeysToSameSlot(CKM_CONCATENATE_BASE_AND_KEY0x00000360UL,
1864 CKA_DERIVE0x0000010CUL, CKA_DERIVE0x0000010CUL, left, right,
1865 &copyOfLeft, &copyOfRight);
1866 if (rv != SECSuccess) {
1867 /* error code already set */
1868 return NULL((void*)0);
1869 }
1870
1871 out = pk11_ConcatenateBaseAndKey(copyOfLeft ? copyOfLeft : left, copyOfRight ? copyOfRight : right, target, operation, 0);
1872 PK11_FreeSymKey(copyOfLeft);
1873 PK11_FreeSymKey(copyOfRight);
1874 return out;
1875}
1876
1877/* Create a new key whose value is the hash of tobehashed.
1878 * type is the mechanism for the derived key.
1879 */
1880static PK11SymKey *
1881pk11_HashKeyDerivation(PK11SymKey *toBeHashed,
1882 CK_MECHANISM_TYPE hashMechanism, CK_MECHANISM_TYPE target,
1883 CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize)
1884{
1885 return PK11_Derive(toBeHashed, hashMechanism, NULL((void*)0), target, operation, keySize);
1886}
1887
1888/* This function implements the ANSI X9.63 key derivation function
1889 */
1890static PK11SymKey *
1891pk11_ANSIX963Derive(PK11SymKey *sharedSecret,
1892 CK_EC_KDF_TYPE kdf, SECItem *sharedData,
1893 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1894 CK_ULONG keySize)
1895{
1896 CK_KEY_TYPE keyType;
1897 CK_MECHANISM_TYPE hashMechanism, mechanismArray[4];
1898 CK_ULONG derivedKeySize, HashLen, counter, maxCounter, bufferLen;
1899 CK_ULONG SharedInfoLen;
1900 CK_BYTE *buffer = NULL((void*)0);
1901 PK11SymKey *toBeHashed, *hashOutput;
1902 PK11SymKey *newSharedSecret = NULL((void*)0);
1903 PK11SymKey *oldIntermediateResult, *intermediateResult = NULL((void*)0);
1904
1905 if (sharedSecret == NULL((void*)0)) {
1906 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1907 return NULL((void*)0);
1908 }
1909
1910 switch (kdf) {
1911 case CKD_SHA1_KDF0x00000002UL:
1912 HashLen = SHA1_LENGTH20;
1913 hashMechanism = CKM_SHA1_KEY_DERIVATION0x00000392UL;
1914 break;
1915 case CKD_SHA224_KDF0x00000005UL:
1916 HashLen = SHA224_LENGTH28;
1917 hashMechanism = CKM_SHA224_KEY_DERIVATION0x00000396UL;
1918 break;
1919 case CKD_SHA256_KDF0x00000006UL:
1920 HashLen = SHA256_LENGTH32;
1921 hashMechanism = CKM_SHA256_KEY_DERIVATION0x00000393UL;
1922 break;
1923 case CKD_SHA384_KDF0x00000007UL:
1924 HashLen = SHA384_LENGTH48;
1925 hashMechanism = CKM_SHA384_KEY_DERIVATION0x00000394UL;
1926 break;
1927 case CKD_SHA512_KDF0x00000008UL:
1928 HashLen = SHA512_LENGTH64;
1929 hashMechanism = CKM_SHA512_KEY_DERIVATION0x00000395UL;
1930 break;
1931 default:
1932 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1933 return NULL((void*)0);
1934 }
1935
1936 derivedKeySize = keySize;
1937 if (derivedKeySize == 0) {
1938 keyType = PK11_GetKeyType(target, keySize);
1939 derivedKeySize = pk11_GetPredefinedKeyLength(keyType);
1940 if (derivedKeySize == 0) {
1941 derivedKeySize = HashLen;
1942 }
1943 }
1944
1945 /* Check that key_len isn't too long. The maximum key length could be
1946 * greatly increased if the code below did not limit the 4-byte counter
1947 * to a maximum value of 255. */
1948 if (derivedKeySize > 254 * HashLen) {
1949 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1950 return NULL((void*)0);
1951 }
1952
1953 maxCounter = derivedKeySize / HashLen;
1954 if (derivedKeySize > maxCounter * HashLen)
1955 maxCounter++;
1956
1957 if ((sharedData == NULL((void*)0)) || (sharedData->data == NULL((void*)0)))
1958 SharedInfoLen = 0;
1959 else
1960 SharedInfoLen = sharedData->len;
1961
1962 bufferLen = SharedInfoLen + 4;
1963
1964 /* Populate buffer with Counter || sharedData
1965 * where Counter is 0x00000001. */
1966 buffer = (unsigned char *)PORT_AllocPORT_Alloc_Util(bufferLen);
1967 if (buffer == NULL((void*)0)) {
1968 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
1969 return NULL((void*)0);
1970 }
1971
1972 buffer[0] = 0;
1973 buffer[1] = 0;
1974 buffer[2] = 0;
1975 buffer[3] = 1;
1976 if (SharedInfoLen > 0) {
1977 PORT_Memcpymemcpy(&buffer[4], sharedData->data, SharedInfoLen);
1978 }
1979
1980 /* Look for a slot that supports the mechanisms needed
1981 * to implement the ANSI X9.63 KDF as well as the
1982 * target mechanism.
1983 */
1984 mechanismArray[0] = CKM_CONCATENATE_BASE_AND_DATA0x00000362UL;
1985 mechanismArray[1] = hashMechanism;
1986 mechanismArray[2] = CKM_CONCATENATE_BASE_AND_KEY0x00000360UL;
1987 mechanismArray[3] = target;
1988
1989 newSharedSecret = pk11_ForceSlotMultiple(sharedSecret,
1990 mechanismArray, 4, operation);
1991 if (newSharedSecret != NULL((void*)0)) {
1992 sharedSecret = newSharedSecret;
1993 }
1994
1995 for (counter = 1; counter <= maxCounter; counter++) {
1996 /* Concatenate shared_secret and buffer */
1997 toBeHashed = pk11_ConcatenateBaseAndData(sharedSecret, buffer,
1998 bufferLen, hashMechanism, operation);
1999 if (toBeHashed == NULL((void*)0)) {
2000 goto loser;
2001 }
2002
2003 /* Hash value */
2004 if (maxCounter == 1) {
2005 /* In this case the length of the key to be derived is
2006 * less than or equal to the length of the hash output.
2007 * So, the output of the hash operation will be the
2008 * dervied key. */
2009 hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism,
2010 target, operation, keySize);
2011 } else {
2012 /* In this case, the output of the hash operation will be
2013 * concatenated with other data to create the derived key. */
2014 hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism,
2015 CKM_CONCATENATE_BASE_AND_KEY0x00000360UL, operation, 0);
2016 }
2017 PK11_FreeSymKey(toBeHashed);
2018 if (hashOutput == NULL((void*)0)) {
2019 goto loser;
2020 }
2021
2022 /* Append result to intermediate result, if necessary */
2023 oldIntermediateResult = intermediateResult;
2024
2025 if (oldIntermediateResult == NULL((void*)0)) {
2026 intermediateResult = hashOutput;
2027 } else {
2028 if (counter == maxCounter) {
2029 /* This is the final concatenation, and so the output
2030 * will be the derived key. */
2031 intermediateResult =
2032 pk11_ConcatenateBaseAndKey(oldIntermediateResult,
2033 hashOutput, target, operation, keySize);
2034 } else {
2035 /* The output of this concatenation will be concatenated
2036 * with other data to create the derived key. */
2037 intermediateResult =
2038 pk11_ConcatenateBaseAndKey(oldIntermediateResult,
2039 hashOutput, CKM_CONCATENATE_BASE_AND_KEY0x00000360UL,
2040 operation, 0);
2041 }
2042
2043 PK11_FreeSymKey(hashOutput);
2044 PK11_FreeSymKey(oldIntermediateResult);
2045 if (intermediateResult == NULL((void*)0)) {
2046 goto loser;
2047 }
2048 }
2049
2050 /* Increment counter (assumes maxCounter < 255) */
2051 buffer[3]++;
2052 }
2053
2054 PORT_ZFreePORT_ZFree_Util(buffer, bufferLen);
2055 if (newSharedSecret != NULL((void*)0))
2056 PK11_FreeSymKey(newSharedSecret);
2057 return intermediateResult;
2058
2059loser:
2060 PORT_ZFreePORT_ZFree_Util(buffer, bufferLen);
2061 if (newSharedSecret != NULL((void*)0))
2062 PK11_FreeSymKey(newSharedSecret);
2063 if (intermediateResult != NULL((void*)0))
2064 PK11_FreeSymKey(intermediateResult);
2065 return NULL((void*)0);
2066}
2067
2068/*
2069 * This regenerate a public key from a private key. This function is currently
2070 * NSS private. If we want to make it public, we need to add and optional
2071 * template or at least flags (a.la. PK11_DeriveWithFlags).
2072 */
2073CK_OBJECT_HANDLE
2074PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey)
2075{
2076 PK11SlotInfo *slot = privKey->pkcs11Slot;
2077 CK_MECHANISM mechanism;
2078 CK_OBJECT_HANDLE objectID = CK_INVALID_HANDLE0;
2079 CK_RV crv;
2080
2081 mechanism.mechanism = CKM_NSS_PUB_FROM_PRIV((0x80000000UL | 0x4E534350) + 40);
2082 mechanism.pParameter = NULL((void*)0);
2083 mechanism.ulParameterLen = 0;
2084
2085 PK11_EnterSlotMonitor(slot);
2086 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DeriveKey(slot->session, &mechanism,
2087 privKey->pkcs11ID, NULL((void*)0), 0,
2088 &objectID);
2089 PK11_ExitSlotMonitor(slot);
2090 if (crv != CKR_OK0x00000000UL) {
2091 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2092 return CK_INVALID_HANDLE0;
2093 }
2094 return objectID;
2095}
2096
2097/*
2098 * This Generates a wrapping key based on a privateKey, publicKey, and two
2099 * random numbers. For Mail usage RandomB should be NULL. In the Sender's
2100 * case RandomA is generate, otherwise it is passed.
2101 */
2102PK11SymKey *
2103PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
2104 PRBool isSender, SECItem *randomA, SECItem *randomB,
2105 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
2106 CK_ATTRIBUTE_TYPE operation, int keySize, void *wincx)
2107{
2108 PK11SlotInfo *slot = privKey->pkcs11Slot;
2109 CK_MECHANISM mechanism;
2110 PK11SymKey *symKey;
2111 CK_RV crv;
2112
2113 /* get our key Structure */
2114 symKey = pk11_CreateSymKey(slot, target, PR_TRUE1, PR_TRUE1, wincx);
2115 if (symKey == NULL((void*)0)) {
2116 return NULL((void*)0);
2117 }
2118
2119 /* CKA_NSS_MESSAGE is a fake operation to distinguish between
2120 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set
2121 * it as a real attribute */
2122 if ((operation & CKA_NSS_MESSAGE_MASK0xff000000L) == CKA_NSS_MESSAGE0x82000000L) {
2123 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT),
2124 * etc. Strip out the real attribute here */
2125 operation &= ~CKA_NSS_MESSAGE_MASK0xff000000L;
2126 }
2127
2128 symKey->origin = PK11_OriginDerive;
2129
2130 switch (privKey->keyType) {
2131 case rsaKey:
2132 case rsaPssKey:
2133 case rsaOaepKey:
2134 case kyberKey:
2135 case nullKey:
2136 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
2137 break;
2138 case dsaKey:
2139 case keaKey:
2140 case fortezzaKey: {
2141 static unsigned char rb_email[128] = { 0 };
2142 CK_KEA_DERIVE_PARAMS param;
2143 param.isSender = (CK_BBOOL)isSender;
2144 param.ulRandomLen = randomA->len;
2145 param.pRandomA = randomA->data;
2146 param.pRandomB = rb_email;
2147 param.pRandomB[127] = 1;
2148 if (randomB)
2149 param.pRandomB = randomB->data;
2150 if (pubKey->keyType == fortezzaKey) {
2151 param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len;
2152 param.pPublicData = pubKey->u.fortezza.KEAKey.data;
2153 } else {
2154 /* assert type == keaKey */
2155 /* XXX change to match key key types */
2156 param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len;
2157 param.pPublicData = pubKey->u.fortezza.KEAKey.data;
2158 }
2159
2160 mechanism.mechanism = derive;
2161 mechanism.pParameter = &param;
2162 mechanism.ulParameterLen = sizeof(param);
2163
2164 /* get a new symKey structure */
2165 pk11_EnterKeyMonitor(symKey);
2166 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DeriveKey(symKey->session, &mechanism,
2167 privKey->pkcs11ID, NULL((void*)0), 0,
2168 &symKey->objectID);
2169 pk11_ExitKeyMonitor(symKey);
2170 if (crv == CKR_OK0x00000000UL)
2171 return symKey;
2172 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2173 } break;
2174 case dhKey: {
2175 CK_BBOOL cktrue = CK_TRUE1;
2176 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY0x00000004UL;
2177 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET0x00000010UL;
2178 CK_ULONG key_size = 0;
2179 CK_ATTRIBUTE keyTemplate[4];
2180 int templateCount;
2181 CK_ATTRIBUTE *attrs = keyTemplate;
2182
2183 if (pubKey->keyType != dhKey) {
2184 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
2185 break;
2186 }
2187
2188 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyClass); (attrs)->ulValueLen = (sizeof(keyClass));
;
2189 attrs++;
2190 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType))(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof(keyType));
;
2191 attrs++;
2192 PK11_SETATTRS(attrs, operation, &cktrue, 1)(attrs)->type = (operation); (attrs)->pValue = (&cktrue
); (attrs)->ulValueLen = (1);
;
2193 attrs++;
2194 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size))(attrs)->type = (0x00000161UL); (attrs)->pValue = (&
key_size); (attrs)->ulValueLen = (sizeof(key_size));
;
2195 attrs++;
2196 templateCount = attrs - keyTemplate;
2197 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE))((templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE
))?((void)0):PR_Assert("templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",2197))
;
2198
2199 keyType = PK11_GetKeyType(target, keySize);
2200 key_size = keySize;
2201 symKey->size = keySize;
2202 if (key_size == 0)
2203 templateCount--;
2204
2205 mechanism.mechanism = derive;
2206
2207 /* we can undefine these when we define diffie-helman keys */
2208
2209 mechanism.pParameter = pubKey->u.dh.publicValue.data;
2210 mechanism.ulParameterLen = pubKey->u.dh.publicValue.len;
2211
2212 pk11_EnterKeyMonitor(symKey);
2213 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DeriveKey(symKey->session, &mechanism,
2214 privKey->pkcs11ID, keyTemplate,
2215 templateCount, &symKey->objectID);
2216 pk11_ExitKeyMonitor(symKey);
2217 if (crv == CKR_OK0x00000000UL)
2218 return symKey;
2219 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2220 } break;
2221 case edKey:
2222 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
2223 break;
2224 case ecKey: {
2225 CK_BBOOL cktrue = CK_TRUE1;
2226 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY0x00000004UL;
2227 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET0x00000010UL;
2228 CK_ULONG key_size = 0;
2229 CK_ATTRIBUTE keyTemplate[4];
2230 int templateCount;
2231 CK_ATTRIBUTE *attrs = keyTemplate;
2232 CK_ECDH1_DERIVE_PARAMS *mechParams = NULL((void*)0);
2233
2234 if (pubKey->keyType != ecKey) {
2235 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
2236 break;
2237 }
2238
2239 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyClass); (attrs)->ulValueLen = (sizeof(keyClass));
;
2240 attrs++;
2241 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType))(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof(keyType));
;
2242 attrs++;
2243 PK11_SETATTRS(attrs, operation, &cktrue, 1)(attrs)->type = (operation); (attrs)->pValue = (&cktrue
); (attrs)->ulValueLen = (1);
;
2244 attrs++;
2245 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size))(attrs)->type = (0x00000161UL); (attrs)->pValue = (&
key_size); (attrs)->ulValueLen = (sizeof(key_size));
;
2246 attrs++;
2247 templateCount = attrs - keyTemplate;
2248 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE))((templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE
))?((void)0):PR_Assert("templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",2248))
;
2249
2250 keyType = PK11_GetKeyType(target, keySize);
2251 key_size = keySize;
2252 if (key_size == 0) {
2253 if ((key_size = pk11_GetPredefinedKeyLength(keyType))) {
2254 templateCount--;
2255 } else {
2256 /* sigh, some tokens can't figure this out and require
2257 * CKA_VALUE_LEN to be set */
2258 key_size = SHA1_LENGTH20;
2259 }
2260 }
2261 symKey->size = key_size;
2262
2263 mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS)(CK_ECDH1_DERIVE_PARAMS *)PORT_ZAlloc_Util(sizeof(CK_ECDH1_DERIVE_PARAMS
))
;
2264 mechParams->kdf = CKD_SHA1_KDF0x00000002UL;
2265 mechParams->ulSharedDataLen = 0;
2266 mechParams->pSharedData = NULL((void*)0);
2267 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len;
2268 mechParams->pPublicData = pubKey->u.ec.publicValue.data;
2269
2270 mechanism.mechanism = derive;
2271 mechanism.pParameter = mechParams;
2272 mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
2273
2274 pk11_EnterKeyMonitor(symKey);
2275 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DeriveKey(symKey->session,
2276 &mechanism, privKey->pkcs11ID, keyTemplate,
2277 templateCount, &symKey->objectID);
2278 pk11_ExitKeyMonitor(symKey);
2279
2280 /* old PKCS #11 spec was ambiguous on what needed to be passed,
2281 * try this again with and encoded public key */
2282 if (crv != CKR_OK0x00000000UL && pk11_ECGetPubkeyEncoding(pubKey) != ECPoint_XOnly) {
2283 SECItem *pubValue = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(NULL((void*)0), NULL((void*)0),
2284 &pubKey->u.ec.publicValue,
2285 SEC_ASN1_GET(SEC_OctetStringTemplate)SEC_OctetStringTemplate_Util);
2286 if (pubValue == NULL((void*)0)) {
2287 PORT_ZFreePORT_ZFree_Util(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
2288 break;
2289 }
2290 mechParams->ulPublicDataLen = pubValue->len;
2291 mechParams->pPublicData = pubValue->data;
2292
2293 pk11_EnterKeyMonitor(symKey);
2294 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DeriveKey(symKey->session,
2295 &mechanism, privKey->pkcs11ID, keyTemplate,
2296 templateCount, &symKey->objectID);
2297 pk11_ExitKeyMonitor(symKey);
2298
2299 SECITEM_FreeItemSECITEM_FreeItem_Util(pubValue, PR_TRUE1);
2300 }
2301
2302 PORT_ZFreePORT_ZFree_Util(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
2303
2304 if (crv == CKR_OK0x00000000UL)
2305 return symKey;
2306 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2307 }
2308 }
2309
2310 PK11_FreeSymKey(symKey);
2311 return NULL((void*)0);
2312}
2313
2314/* Test for curves that are known to use a special encoding.
2315 * Extend this function when additional curves are added. */
2316static ECPointEncoding
2317pk11_ECGetPubkeyEncoding(const SECKEYPublicKey *pubKey)
2318{
2319 SECItem oid;
2320 SECStatus rv;
2321 PORTCheapArenaPool tmpArena;
2322 ECPointEncoding encoding = ECPoint_Undefined;
2323
2324 PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE(2048));
2325
2326 /* decode the OID tag */
2327 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(&tmpArena.arena, &oid,
2328 SEC_ASN1_GET(SEC_ObjectIDTemplate)SEC_ObjectIDTemplate_Util,
2329 &pubKey->u.ec.DEREncodedParams);
2330 if (rv == SECSuccess) {
2331 SECOidTag tag = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&oid);
2332 switch (tag) {
2333 case SEC_OID_CURVE25519:
2334 encoding = ECPoint_XOnly;
2335 break;
2336 case SEC_OID_SECG_EC_SECP256R1SEC_OID_ANSIX962_EC_PRIME256V1:
2337 case SEC_OID_SECG_EC_SECP384R1:
2338 case SEC_OID_SECG_EC_SECP521R1:
2339 default:
2340 /* unknown curve, default to uncompressed */
2341 encoding = ECPoint_Uncompressed;
2342 }
2343 }
2344 PORT_DestroyCheapArena(&tmpArena);
2345 return encoding;
2346}
2347
2348/* Returns the size of the public key, or 0 if there
2349 * is an error. */
2350static CK_ULONG
2351pk11_ECPubKeySize(SECKEYPublicKey *pubKey)
2352{
2353 SECItem *publicValue = &pubKey->u.ec.publicValue;
2354
2355 ECPointEncoding encoding = pk11_ECGetPubkeyEncoding(pubKey);
2356 if (encoding == ECPoint_XOnly) {
2357 return publicValue->len;
2358 }
2359 if (encoding == ECPoint_Uncompressed) {
2360 /* key encoded in uncompressed form */
2361 return ((publicValue->len - 1) / 2);
2362 }
2363 /* key encoding not recognized */
2364 return 0;
2365}
2366
2367static PK11SymKey *
2368pk11_PubDeriveECKeyWithKDF(
2369 SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
2370 PRBool isSender, SECItem *randomA, SECItem *randomB,
2371 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
2372 CK_ATTRIBUTE_TYPE operation, int keySize,
2373 CK_ULONG kdf, SECItem *sharedData, void *wincx)
2374{
2375 PK11SlotInfo *slot = privKey->pkcs11Slot;
2376 PK11SymKey *symKey;
2377 PK11SymKey *SharedSecret;
2378 CK_MECHANISM mechanism;
2379 CK_RV crv;
2380 CK_BBOOL cktrue = CK_TRUE1;
2381 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY0x00000004UL;
2382 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET0x00000010UL;
2383 CK_ULONG key_size = 0;
2384 CK_ATTRIBUTE keyTemplate[4];
2385 int templateCount;
2386 CK_ATTRIBUTE *attrs = keyTemplate;
2387 CK_ECDH1_DERIVE_PARAMS *mechParams = NULL((void*)0);
2388
2389 if (pubKey->keyType != ecKey) {
2390 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
2391 return NULL((void*)0);
2392 }
2393 if ((kdf != CKD_NULL0x00000001UL) && (kdf != CKD_SHA1_KDF0x00000002UL) &&
2394 (kdf != CKD_SHA224_KDF0x00000005UL) && (kdf != CKD_SHA256_KDF0x00000006UL) &&
2395 (kdf != CKD_SHA384_KDF0x00000007UL) && (kdf != CKD_SHA512_KDF0x00000008UL)) {
2396 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
2397 return NULL((void*)0);
2398 }
2399
2400 /* get our key Structure */
2401 symKey = pk11_CreateSymKey(slot, target, PR_TRUE1, PR_TRUE1, wincx);
2402 if (symKey == NULL((void*)0)) {
2403 return NULL((void*)0);
2404 }
2405 /* CKA_NSS_MESSAGE is a fake operation to distinguish between
2406 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set
2407 * it as a real attribute */
2408 if ((operation & CKA_NSS_MESSAGE_MASK0xff000000L) == CKA_NSS_MESSAGE0x82000000L) {
2409 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT),
2410 * etc. Strip out the real attribute here */
2411 operation &= ~CKA_NSS_MESSAGE_MASK0xff000000L;
2412 }
2413
2414 symKey->origin = PK11_OriginDerive;
2415
2416 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyClass); (attrs)->ulValueLen = (sizeof(keyClass));
;
2417 attrs++;
2418 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType))(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof(keyType));
;
2419 attrs++;
2420 PK11_SETATTRS(attrs, operation, &cktrue, 1)(attrs)->type = (operation); (attrs)->pValue = (&cktrue
); (attrs)->ulValueLen = (1);
;
2421 attrs++;
2422 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size))(attrs)->type = (0x00000161UL); (attrs)->pValue = (&
key_size); (attrs)->ulValueLen = (sizeof(key_size));
;
2423 attrs++;
2424 templateCount = attrs - keyTemplate;
2425 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE))((templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE
))?((void)0):PR_Assert("templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",2425))
;
2426
2427 keyType = PK11_GetKeyType(target, keySize);
2428 key_size = keySize;
2429 if (key_size == 0) {
2430 if ((key_size = pk11_GetPredefinedKeyLength(keyType))) {
2431 templateCount--;
2432 } else {
2433 /* sigh, some tokens can't figure this out and require
2434 * CKA_VALUE_LEN to be set */
2435 switch (kdf) {
2436 case CKD_NULL0x00000001UL:
2437 key_size = pk11_ECPubKeySize(pubKey);
2438 if (key_size == 0) {
2439 PK11_FreeSymKey(symKey);
2440 return NULL((void*)0);
2441 }
2442 break;
2443 case CKD_SHA1_KDF0x00000002UL:
2444 key_size = SHA1_LENGTH20;
2445 break;
2446 case CKD_SHA224_KDF0x00000005UL:
2447 key_size = SHA224_LENGTH28;
2448 break;
2449 case CKD_SHA256_KDF0x00000006UL:
2450 key_size = SHA256_LENGTH32;
2451 break;
2452 case CKD_SHA384_KDF0x00000007UL:
2453 key_size = SHA384_LENGTH48;
2454 break;
2455 case CKD_SHA512_KDF0x00000008UL:
2456 key_size = SHA512_LENGTH64;
2457 break;
2458 default:
2459 PORT_AssertNotReached("Invalid CKD")PR_Assert("Invalid CKD","pk11skey.c",2459);
2460 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
2461 return NULL((void*)0);
2462 }
2463 }
2464 }
2465 symKey->size = key_size;
2466
2467 mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS)(CK_ECDH1_DERIVE_PARAMS *)PORT_ZAlloc_Util(sizeof(CK_ECDH1_DERIVE_PARAMS
))
;
2468 if (!mechParams) {
2469 PK11_FreeSymKey(symKey);
2470 return NULL((void*)0);
2471 }
2472 mechParams->kdf = kdf;
2473 if (sharedData == NULL((void*)0)) {
2474 mechParams->ulSharedDataLen = 0;
2475 mechParams->pSharedData = NULL((void*)0);
2476 } else {
2477 mechParams->ulSharedDataLen = sharedData->len;
2478 mechParams->pSharedData = sharedData->data;
2479 }
2480 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len;
2481 mechParams->pPublicData = pubKey->u.ec.publicValue.data;
2482
2483 mechanism.mechanism = derive;
2484 mechanism.pParameter = mechParams;
2485 mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
2486
2487 pk11_EnterKeyMonitor(symKey);
2488 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DeriveKey(symKey->session, &mechanism,
2489 privKey->pkcs11ID, keyTemplate,
2490 templateCount, &symKey->objectID);
2491 pk11_ExitKeyMonitor(symKey);
2492
2493 /* old PKCS #11 spec was ambiguous on what needed to be passed,
2494 * try this again with an encoded public key */
2495 if (crv != CKR_OK0x00000000UL) {
2496 /* For curves that only use X as public value and no encoding we don't
2497 * have to try again. (Currently only Curve25519) */
2498 if (pk11_ECGetPubkeyEncoding(pubKey) == ECPoint_XOnly) {
2499 goto loser;
2500 }
2501 SECItem *pubValue = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(NULL((void*)0), NULL((void*)0),
2502 &pubKey->u.ec.publicValue,
2503 SEC_ASN1_GET(SEC_OctetStringTemplate)SEC_OctetStringTemplate_Util);
2504 if (pubValue == NULL((void*)0)) {
2505 goto loser;
2506 }
2507 mechParams->ulPublicDataLen = pubValue->len;
2508 mechParams->pPublicData = pubValue->data;
2509
2510 pk11_EnterKeyMonitor(symKey);
2511 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DeriveKey(symKey->session,
2512 &mechanism, privKey->pkcs11ID, keyTemplate,
2513 templateCount, &symKey->objectID);
2514 pk11_ExitKeyMonitor(symKey);
2515
2516 if ((crv != CKR_OK0x00000000UL) && (kdf != CKD_NULL0x00000001UL)) {
2517 /* Some PKCS #11 libraries cannot perform the key derivation
2518 * function. So, try calling C_DeriveKey with CKD_NULL and then
2519 * performing the KDF separately.
2520 */
2521 CK_ULONG derivedKeySize = key_size;
2522
2523 keyType = CKK_GENERIC_SECRET0x00000010UL;
2524 key_size = pk11_ECPubKeySize(pubKey);
2525 if (key_size == 0) {
2526 SECITEM_FreeItemSECITEM_FreeItem_Util(pubValue, PR_TRUE1);
2527 goto loser;
2528 }
2529 SharedSecret = symKey;
2530 SharedSecret->size = key_size;
2531
2532 mechParams->kdf = CKD_NULL0x00000001UL;
2533 mechParams->ulSharedDataLen = 0;
2534 mechParams->pSharedData = NULL((void*)0);
2535 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len;
2536 mechParams->pPublicData = pubKey->u.ec.publicValue.data;
2537
2538 pk11_EnterKeyMonitor(SharedSecret);
2539 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DeriveKey(SharedSecret->session,
2540 &mechanism, privKey->pkcs11ID, keyTemplate,
2541 templateCount, &SharedSecret->objectID);
2542 pk11_ExitKeyMonitor(SharedSecret);
2543
2544 if (crv != CKR_OK0x00000000UL) {
2545 /* old PKCS #11 spec was ambiguous on what needed to be passed,
2546 * try this one final time with an encoded public key */
2547 mechParams->ulPublicDataLen = pubValue->len;
2548 mechParams->pPublicData = pubValue->data;
2549
2550 pk11_EnterKeyMonitor(SharedSecret);
2551 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DeriveKey(SharedSecret->session,
2552 &mechanism, privKey->pkcs11ID, keyTemplate,
2553 templateCount, &SharedSecret->objectID);
2554 pk11_ExitKeyMonitor(SharedSecret);
2555 }
2556
2557 /* Perform KDF. */
2558 if (crv == CKR_OK0x00000000UL) {
2559 symKey = pk11_ANSIX963Derive(SharedSecret, kdf,
2560 sharedData, target, operation,
2561 derivedKeySize);
2562 PK11_FreeSymKey(SharedSecret);
2563 if (symKey == NULL((void*)0)) {
2564 SECITEM_FreeItemSECITEM_FreeItem_Util(pubValue, PR_TRUE1);
2565 PORT_ZFreePORT_ZFree_Util(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
2566 return NULL((void*)0);
2567 }
2568 }
2569 }
2570 SECITEM_FreeItemSECITEM_FreeItem_Util(pubValue, PR_TRUE1);
2571 }
2572
2573loser:
2574 PORT_ZFreePORT_ZFree_Util(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
2575
2576 if (crv != CKR_OK0x00000000UL) {
2577 PK11_FreeSymKey(symKey);
2578 symKey = NULL((void*)0);
2579 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2580 }
2581 return symKey;
2582}
2583
2584PK11SymKey *
2585PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
2586 PRBool isSender, SECItem *randomA, SECItem *randomB,
2587 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
2588 CK_ATTRIBUTE_TYPE operation, int keySize,
2589 CK_ULONG kdf, SECItem *sharedData, void *wincx)
2590{
2591
2592 switch (privKey->keyType) {
2593 case rsaKey:
2594 case nullKey:
2595 case dsaKey:
2596 case keaKey:
2597 case fortezzaKey:
2598 case dhKey:
2599 return PK11_PubDerive(privKey, pubKey, isSender, randomA, randomB,
2600 derive, target, operation, keySize, wincx);
2601 case ecKey:
2602 return pk11_PubDeriveECKeyWithKDF(privKey, pubKey, isSender,
2603 randomA, randomB, derive, target,
2604 operation, keySize,
2605 kdf, sharedData, wincx);
2606 default:
2607 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
2608 break;
2609 }
2610
2611 return NULL((void*)0);
2612}
2613
2614/*
2615 * this little function uses the Decrypt function to unwrap a key, just in
2616 * case we are having problem with unwrap. NOTE: The key size may
2617 * not be preserved properly for some algorithms!
2618 */
2619static PK11SymKey *
2620pk11_HandUnwrap(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey,
2621 CK_MECHANISM *mech, SECItem *inKey, CK_MECHANISM_TYPE target,
2622 CK_ATTRIBUTE *keyTemplate, unsigned int templateCount,
2623 int key_size, void *wincx, CK_RV *crvp, PRBool isPerm)
2624{
2625 CK_ULONG len;
2626 SECItem outKey;
2627 PK11SymKey *symKey;
2628 CK_RV crv;
2629 PRBool owner = PR_TRUE1;
2630 CK_SESSION_HANDLE session;
2631
2632 /* remove any VALUE_LEN parameters */
2633 if (keyTemplate[templateCount - 1].type == CKA_VALUE_LEN0x00000161UL) {
2634 templateCount--;
2635 }
2636
2637 /* keys are almost always aligned, but if we get this far,
2638 * we've gone above and beyond anyway... */
2639 outKey.data = (unsigned char *)PORT_AllocPORT_Alloc_Util(inKey->len);
2640 if (outKey.data == NULL((void*)0)) {
2641 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
2642 if (crvp)
2643 *crvp = CKR_HOST_MEMORY0x00000002UL;
2644 return NULL((void*)0);
2645 }
2646 len = inKey->len;
2647
2648 /* use NULL IV's for wrapping */
2649 session = pk11_GetNewSession(slot, &owner);
2650 if (!owner || !(slot->isThreadSafe))
2651 PK11_EnterSlotMonitor(slot);
2652 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_DecryptInit(session, mech, wrappingKey);
2653 if (crv != CKR_OK0x00000000UL) {
2654 if (!owner || !(slot->isThreadSafe))
2655 PK11_ExitSlotMonitor(slot);
2656 pk11_CloseSession(slot, session, owner);
2657 PORT_FreePORT_Free_Util(outKey.data);
2658 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2659 if (crvp)
2660 *crvp = crv;
2661 return NULL((void*)0);
2662 }
2663 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_Decrypt(session, inKey->data, inKey->len,
2664 outKey.data, &len);
2665 if (!owner || !(slot->isThreadSafe))
2666 PK11_ExitSlotMonitor(slot);
2667 pk11_CloseSession(slot, session, owner);
2668 if (crv != CKR_OK0x00000000UL) {
2669 PORT_FreePORT_Free_Util(outKey.data);
2670 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2671 if (crvp)
2672 *crvp = crv;
2673 return NULL((void*)0);
2674 }
2675
2676 outKey.len = (key_size == 0) ? len : key_size;
2677 outKey.type = siBuffer;
2678
2679 if (PK11_DoesMechanism(slot, target)) {
2680 symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap,
2681 isPerm, keyTemplate,
2682 templateCount, &outKey, wincx);
2683 } else {
2684 slot = PK11_GetBestSlot(target, wincx);
2685 if (slot == NULL((void*)0)) {
2686 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
2687 PORT_FreePORT_Free_Util(outKey.data);
2688 if (crvp)
2689 *crvp = CKR_DEVICE_ERROR0x00000030UL;
2690 return NULL((void*)0);
2691 }
2692 symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap,
2693 isPerm, keyTemplate,
2694 templateCount, &outKey, wincx);
2695 PK11_FreeSlot(slot);
2696 }
2697 PORT_FreePORT_Free_Util(outKey.data);
2698
2699 if (crvp)
2700 *crvp = symKey ? CKR_OK0x00000000UL : CKR_DEVICE_ERROR0x00000030UL;
2701 return symKey;
2702}
2703
2704/*
2705 * The wrap/unwrap function is pretty much the same for private and
2706 * public keys. It's just getting the Object ID and slot right. This is
2707 * the combined unwrap function.
2708 */
2709static PK11SymKey *
2710pk11_AnyUnwrapKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey,
2711 CK_MECHANISM_TYPE wrapType, SECItem *param, SECItem *wrappedKey,
2712 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize,
2713 void *wincx, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, PRBool isPerm)
2714{
2715 PK11SymKey *symKey;
2716 SECItem *param_free = NULL((void*)0);
2717 CK_BBOOL cktrue = CK_TRUE1;
2718 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY0x00000004UL;
2719 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET0x00000010UL;
2720 CK_ULONG valueLen = 0;
2721 CK_MECHANISM mechanism;
2722 CK_SESSION_HANDLE rwsession;
2723 CK_RV crv;
2724 CK_MECHANISM_INFO mechanism_info;
2725#define MAX_ADD_ATTRS 4
2726 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16 + MAX_ADD_ATTRS];
2727#undef MAX_ADD_ATTRS
2728 CK_ATTRIBUTE *attrs = keyTemplate;
2729 unsigned int templateCount;
2730
2731 if (numAttrs > MAX_TEMPL_ATTRS16) {
2732 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2733 return NULL((void*)0);
2734 }
2735 /* CKA_NSS_MESSAGE is a fake operation to distinguish between
2736 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set
2737 * it as a real attribute */
2738 if ((operation & CKA_NSS_MESSAGE_MASK0xff000000L) == CKA_NSS_MESSAGE0x82000000L) {
2739 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT),
2740 * etc. Strip out the real attribute here */
2741 operation &= ~CKA_NSS_MESSAGE_MASK0xff000000L;
2742 }
2743
2744 /* first copy caller attributes in. */
2745 for (templateCount = 0; templateCount < numAttrs; ++templateCount) {
2746 *attrs++ = *userAttr++;
2747 }
2748
2749 /* We only add the following attributes to the template if the caller
2750 ** didn't already supply them.
2751 */
2752 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS0x00000000UL)) {
2753 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass)(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyClass); (attrs)->ulValueLen = (sizeof keyClass);
;
2754 attrs++;
2755 }
2756 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE0x00000100UL)) {
2757 keyType = PK11_GetKeyType(target, keySize);
2758 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType)(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof keyType);
;
2759 attrs++;
2760 }
2761 if ((operation != CKA_FLAGS_ONLY0) &&
2762 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) {
2763 PK11_SETATTRS(attrs, operation, &cktrue, 1)(attrs)->type = (operation); (attrs)->pValue = (&cktrue
); (attrs)->ulValueLen = (1);
;
2764 attrs++;
2765 }
2766
2767 /*
2768 * must be last in case we need to use this template to import the key
2769 */
2770 if (keySize > 0 &&
2771 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN0x00000161UL)) {
2772 valueLen = (CK_ULONG)keySize;
2773 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen)(attrs)->type = (0x00000161UL); (attrs)->pValue = (&
valueLen); (attrs)->ulValueLen = (sizeof valueLen);
;
2774 attrs++;
2775 }
2776
2777 templateCount = attrs - keyTemplate;
2778 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE))((templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE
))?((void)0):PR_Assert("templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",2778))
;
2779
2780 /* find out if we can do wrap directly. Because the RSA case if *very*
2781 * common, cache the results for it. */
2782 if ((wrapType == CKM_RSA_PKCS0x00000001UL) && (slot->hasRSAInfo)) {
2783 mechanism_info.flags = slot->RSAInfoFlags;
2784 } else {
2785 if (!slot->isThreadSafe)
2786 PK11_EnterSlotMonitor(slot);
2787 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_GetMechanismInfo(slot->slotID, wrapType,
2788 &mechanism_info);
2789 if (!slot->isThreadSafe)
2790 PK11_ExitSlotMonitor(slot);
2791 if (crv != CKR_OK0x00000000UL) {
2792 mechanism_info.flags = 0;
2793 }
2794 if (wrapType == CKM_RSA_PKCS0x00000001UL) {
2795 slot->RSAInfoFlags = mechanism_info.flags;
2796 slot->hasRSAInfo = PR_TRUE1;
2797 }
2798 }
2799
2800 /* initialize the mechanism structure */
2801 mechanism.mechanism = wrapType;
2802 /* use NULL IV's for wrapping */
2803 if (param == NULL((void*)0))
2804 param = param_free = PK11_ParamFromIV(wrapType, NULL((void*)0));
2805 if (param) {
2806 mechanism.pParameter = param->data;
2807 mechanism.ulParameterLen = param->len;
2808 } else {
2809 mechanism.pParameter = NULL((void*)0);
2810 mechanism.ulParameterLen = 0;
2811 }
2812
2813 if ((mechanism_info.flags & CKF_DECRYPT0x00000200UL) && !PK11_DoesMechanism(slot, target)) {
2814 symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey,
2815 target, keyTemplate, templateCount, keySize,
2816 wincx, &crv, isPerm);
2817 if (symKey) {
2818 if (param_free)
2819 SECITEM_FreeItemSECITEM_FreeItem_Util(param_free, PR_TRUE1);
2820 return symKey;
2821 }
2822 /*
2823 * if the RSA OP simply failed, don't try to unwrap again
2824 * with this module.
2825 */
2826 if (crv == CKR_DEVICE_ERROR0x00000030UL) {
2827 if (param_free)
2828 SECITEM_FreeItemSECITEM_FreeItem_Util(param_free, PR_TRUE1);
2829 return NULL((void*)0);
2830 }
2831 /* fall through, maybe they incorrectly set CKF_DECRYPT */
2832 }
2833
2834 /* get our key Structure */
2835 symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE1, wincx);
2836 if (symKey == NULL((void*)0)) {
2837 if (param_free)
2838 SECITEM_FreeItemSECITEM_FreeItem_Util(param_free, PR_TRUE1);
2839 return NULL((void*)0);
2840 }
2841
2842 symKey->size = keySize;
2843 symKey->origin = PK11_OriginUnwrap;
2844
2845 if (isPerm) {
2846 rwsession = PK11_GetRWSession(slot);
2847 } else {
2848 pk11_EnterKeyMonitor(symKey);
2849 rwsession = symKey->session;
2850 }
2851 PORT_Assert(rwsession != CK_INVALID_HANDLE)((rwsession != 0)?((void)0):PR_Assert("rwsession != CK_INVALID_HANDLE"
,"pk11skey.c",2851))
;
2852 if (rwsession == CK_INVALID_HANDLE0)
2853 crv = CKR_SESSION_HANDLE_INVALID0x000000B3UL;
2854 else
2855 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_UnwrapKey(rwsession, &mechanism, wrappingKey,
2856 wrappedKey->data, wrappedKey->len,
2857 keyTemplate, templateCount,
2858 &symKey->objectID);
2859 if (isPerm) {
2860 if (rwsession != CK_INVALID_HANDLE0)
2861 PK11_RestoreROSession(slot, rwsession);
2862 } else {
2863 pk11_ExitKeyMonitor(symKey);
2864 }
2865 if (param_free)
2866 SECITEM_FreeItemSECITEM_FreeItem_Util(param_free, PR_TRUE1);
2867 if (crv != CKR_OK0x00000000UL) {
2868 PK11_FreeSymKey(symKey);
2869 symKey = NULL((void*)0);
2870 if (crv != CKR_DEVICE_ERROR0x00000030UL) {
2871 /* try hand Unwrapping */
2872 symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey,
2873 target, keyTemplate, templateCount,
2874 keySize, wincx, NULL((void*)0), isPerm);
2875 }
2876 }
2877
2878 return symKey;
2879}
2880
2881/* use a symetric key to unwrap another symetric key */
2882PK11SymKey *
2883PK11_UnwrapSymKey(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType,
2884 SECItem *param, SECItem *wrappedKey,
2885 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
2886 int keySize)
2887{
2888 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
2889 wrapType, param, wrappedKey, target, operation, keySize,
2890 wrappingKey->cx, NULL((void*)0), 0, PR_FALSE0);
2891}
2892
2893/* use a symetric key to unwrap another symetric key */
2894PK11SymKey *
2895PK11_UnwrapSymKeyWithFlags(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType,
2896 SECItem *param, SECItem *wrappedKey,
2897 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
2898 int keySize, CK_FLAGS flags)
2899{
2900 CK_BBOOL ckTrue = CK_TRUE1;
2901 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16];
2902 unsigned int templateCount;
2903
2904 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
2905 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
2906 wrapType, param, wrappedKey, target, operation, keySize,
2907 wrappingKey->cx, keyTemplate, templateCount, PR_FALSE0);
2908}
2909
2910PK11SymKey *
2911PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey,
2912 CK_MECHANISM_TYPE wrapType,
2913 SECItem *param, SECItem *wrappedKey,
2914 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
2915 int keySize, CK_FLAGS flags, PRBool isPerm)
2916{
2917 CK_BBOOL cktrue = CK_TRUE1;
2918 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16];
2919 CK_ATTRIBUTE *attrs;
2920 unsigned int templateCount;
2921
2922 attrs = keyTemplate;
2923 if (isPerm) {
2924 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL))(attrs)->type = (0x00000001UL); (attrs)->pValue = (&
cktrue); (attrs)->ulValueLen = (sizeof(CK_BBOOL));
;
2925 attrs++;
2926 }
2927 templateCount = attrs - keyTemplate;
2928 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
2929
2930 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
2931 wrapType, param, wrappedKey, target, operation, keySize,
2932 wrappingKey->cx, keyTemplate, templateCount, isPerm);
2933}
2934
2935/* unwrap a symmetric key with a private key. Only supports CKM_RSA_PKCS. */
2936PK11SymKey *
2937PK11_PubUnwrapSymKey(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey,
2938 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize)
2939{
2940 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType);
2941
2942 return PK11_PubUnwrapSymKeyWithMechanism(wrappingKey, wrapType, NULL((void*)0),
2943 wrappedKey, target, operation,
2944 keySize);
2945}
2946
2947/* unwrap a symmetric key with a private key with the given parameters. */
2948PK11SymKey *
2949PK11_PubUnwrapSymKeyWithMechanism(SECKEYPrivateKey *wrappingKey,
2950 CK_MECHANISM_TYPE mechType, SECItem *param,
2951 SECItem *wrappedKey, CK_MECHANISM_TYPE target,
2952 CK_ATTRIBUTE_TYPE operation, int keySize)
2953{
2954 PK11SlotInfo *slot = wrappingKey->pkcs11Slot;
2955
2956 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey, CKA_PRIVATE)(0 != (wrappingKey->staticflags & 0x1)) ? (0 != (wrappingKey
->staticflags & (1U << 1))) : PK11_HasAttributeSet
(wrappingKey->pkcs11Slot, wrappingKey->pkcs11ID, 0x00000002UL
, 0)
) {
2957 PK11_HandlePasswordCheck(slot, wrappingKey->wincx);
2958 }
2959
2960 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, mechType, param,
2961 wrappedKey, target, operation, keySize,
2962 wrappingKey->wincx, NULL((void*)0), 0, PR_FALSE0);
2963}
2964
2965/* unwrap a symetric key with a private key. */
2966PK11SymKey *
2967PK11_PubUnwrapSymKeyWithFlags(SECKEYPrivateKey *wrappingKey,
2968 SECItem *wrappedKey, CK_MECHANISM_TYPE target,
2969 CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags)
2970{
2971 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType);
2972 CK_BBOOL ckTrue = CK_TRUE1;
2973 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16];
2974 unsigned int templateCount;
2975 PK11SlotInfo *slot = wrappingKey->pkcs11Slot;
2976
2977 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
2978
2979 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey, CKA_PRIVATE)(0 != (wrappingKey->staticflags & 0x1)) ? (0 != (wrappingKey
->staticflags & (1U << 1))) : PK11_HasAttributeSet
(wrappingKey->pkcs11Slot, wrappingKey->pkcs11ID, 0x00000002UL
, 0)
) {
2980 PK11_HandlePasswordCheck(slot, wrappingKey->wincx);
2981 }
2982
2983 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID,
2984 wrapType, NULL((void*)0), wrappedKey, target, operation, keySize,
2985 wrappingKey->wincx, keyTemplate, templateCount, PR_FALSE0);
2986}
2987
2988PK11SymKey *
2989PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey,
2990 SECItem *wrappedKey, CK_MECHANISM_TYPE target,
2991 CK_ATTRIBUTE_TYPE operation, int keySize,
2992 CK_FLAGS flags, PRBool isPerm)
2993{
2994 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType);
2995 CK_BBOOL cktrue = CK_TRUE1;
2996 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16];
2997 CK_ATTRIBUTE *attrs;
2998 unsigned int templateCount;
2999 PK11SlotInfo *slot = wrappingKey->pkcs11Slot;
3000
3001 attrs = keyTemplate;
3002 if (isPerm) {
3003 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL))(attrs)->type = (0x00000001UL); (attrs)->pValue = (&
cktrue); (attrs)->ulValueLen = (sizeof(CK_BBOOL));
;
3004 attrs++;
3005 }
3006 templateCount = attrs - keyTemplate;
3007
3008 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
3009
3010 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey, CKA_PRIVATE)(0 != (wrappingKey->staticflags & 0x1)) ? (0 != (wrappingKey
->staticflags & (1U << 1))) : PK11_HasAttributeSet
(wrappingKey->pkcs11Slot, wrappingKey->pkcs11ID, 0x00000002UL
, 0)
) {
3011 PK11_HandlePasswordCheck(slot, wrappingKey->wincx);
3012 }
3013
3014 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID,
3015 wrapType, NULL((void*)0), wrappedKey, target, operation, keySize,
3016 wrappingKey->wincx, keyTemplate, templateCount, isPerm);
3017}
3018
3019PK11SymKey *
3020PK11_CopySymKeyForSigning(PK11SymKey *originalKey, CK_MECHANISM_TYPE mech)
3021{
3022 CK_RV crv;
3023 CK_ATTRIBUTE setTemplate;
3024 CK_BBOOL ckTrue = CK_TRUE1;
3025 PK11SlotInfo *slot = originalKey->slot;
3026
3027 /* first just try to set this key up for signing */
3028 PK11_SETATTRS(&setTemplate, CKA_SIGN, &ckTrue, sizeof(ckTrue))(&setTemplate)->type = (0x00000108UL); (&setTemplate
)->pValue = (&ckTrue); (&setTemplate)->ulValueLen
= (sizeof(ckTrue));
;
3029 pk11_EnterKeyMonitor(originalKey);
3030 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_SetAttributeValue(originalKey->session,
3031 originalKey->objectID, &setTemplate, 1);
3032 pk11_ExitKeyMonitor(originalKey);
3033 if (crv == CKR_OK0x00000000UL) {
3034 return PK11_ReferenceSymKey(originalKey);
3035 }
3036
3037 /* nope, doesn't like it, use the pk11 copy object command */
3038 return pk11_CopyToSlot(slot, mech, CKA_SIGN0x00000108UL, originalKey);
3039}
3040
3041void
3042PK11_SetFortezzaHack(PK11SymKey *symKey)
3043{
3044 symKey->origin = PK11_OriginFortezzaHack;
3045}
3046
3047/*
3048 * This is required to allow FORTEZZA_NULL and FORTEZZA_RC4
3049 * working. This function simply gets a valid IV for the keys.
3050 */
3051SECStatus
3052PK11_GenerateFortezzaIV(PK11SymKey *symKey, unsigned char *iv, int len)
3053{
3054 CK_MECHANISM mech_info;
3055 CK_ULONG count = 0;
3056 CK_RV crv;
3057 SECStatus rv = SECFailure;
3058
3059 mech_info.mechanism = CKM_SKIPJACK_CBC640x00001002UL;
3060 mech_info.pParameter = iv;
3061 mech_info.ulParameterLen = len;
3062
3063 /* generate the IV for fortezza */
3064 PK11_EnterSlotMonitor(symKey->slot);
3065 crv = PK11_GETTAB(symKey->slot)((CK_FUNCTION_LIST_3_0_PTR)((symKey->slot)->functionList
))
->C_EncryptInit(symKey->slot->session, &mech_info, symKey->objectID);
3066 if (crv == CKR_OK0x00000000UL) {
3067 PK11_GETTAB(symKey->slot)((CK_FUNCTION_LIST_3_0_PTR)((symKey->slot)->functionList
))
->C_EncryptFinal(symKey->slot->session, NULL((void*)0), &count);
3068 rv = SECSuccess;
3069 }
3070 PK11_ExitSlotMonitor(symKey->slot);
3071 return rv;
3072}
3073
3074CK_OBJECT_HANDLE
3075PK11_GetSymKeyHandle(PK11SymKey *symKey)
3076{
3077 return symKey->objectID;
3078}
3079
3080static CK_ULONG
3081pk11_KyberCiphertextLength(SECKEYKyberPublicKey *pubKey)
3082{
3083 switch (pubKey->params) {
3084 case params_kyber768_round3:
3085 case params_kyber768_round3_test_mode:
3086 return KYBER768_CIPHERTEXT_BYTES1088U;
3087 default:
3088 // unreachable
3089 return 0;
3090 }
3091}
3092
3093static CK_ULONG
3094pk11_KEMCiphertextLength(SECKEYPublicKey *pubKey)
3095{
3096 switch (pubKey->keyType) {
3097 case kyberKey:
3098 return pk11_KyberCiphertextLength(&pubKey->u.kyber);
3099 default:
3100 // unreachable
3101 PORT_Assert(0)((0)?((void)0):PR_Assert("0","pk11skey.c",3101));
3102 return 0;
3103 }
3104}
3105
3106SECStatus
3107PK11_Encapsulate(SECKEYPublicKey *pubKey, CK_MECHANISM_TYPE target, PK11AttrFlags attrFlags, CK_FLAGS opFlags, PK11SymKey **outKey, SECItem **outCiphertext)
3108{
3109 PORT_Assert(pubKey)((pubKey)?((void)0):PR_Assert("pubKey","pk11skey.c",3109));
3110 PORT_Assert(outKey)((outKey)?((void)0):PR_Assert("outKey","pk11skey.c",3110));
3111 PORT_Assert(outCiphertext)((outCiphertext)?((void)0):PR_Assert("outCiphertext","pk11skey.c"
,3111))
;
3112
3113 PK11SlotInfo *slot = pubKey->pkcs11Slot;
3114
3115 PK11SymKey *sharedSecret = NULL((void*)0);
3116 SECItem *ciphertext = NULL((void*)0);
3117
3118 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16];
3119 unsigned int templateCount;
3120
3121 CK_ATTRIBUTE *attrs;
3122 CK_BBOOL cktrue = CK_TRUE1;
3123 CK_BBOOL ckfalse = CK_FALSE0;
3124 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY0x00000004UL;
3125 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET0x00000010UL;
3126
3127 CK_INTERFACE_PTR KEMInterface = NULL((void*)0);
3128 CK_UTF8CHAR_PTR KEMInterfaceName = (CK_UTF8CHAR_PTR) "Vendor NSS KEM Interface";
3129 CK_VERSION KEMInterfaceVersion = { 1, 0 };
3130 CK_NSS_KEM_FUNCTIONS *KEMInterfaceFunctions = NULL((void*)0);
3131
3132 CK_RV crv;
3133
3134 *outKey = NULL((void*)0);
3135 *outCiphertext = NULL((void*)0);
3136
3137 CK_MECHANISM_TYPE kemType;
3138 switch (pubKey->keyType) {
3139 case kyberKey:
3140 kemType = CKM_NSS_KYBER((0x80000000UL | 0x4E534350) + 46);
3141 break;
3142 default:
3143 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
3144 return SECFailure;
3145 }
3146
3147 CK_NSS_KEM_PARAMETER_SET_TYPE kemParameterSet = PK11_ReadULongAttribute(slot, pubKey->pkcs11ID, CKA_NSS_PARAMETER_SET((0x80000000UL | 0x4E534350) + 40));
3148 CK_MECHANISM mech = { kemType, &kemParameterSet, sizeof(kemParameterSet) };
3149
3150 sharedSecret = pk11_CreateSymKey(slot, target, PR_TRUE1, PR_TRUE1, NULL((void*)0));
3151 if (sharedSecret == NULL((void*)0)) {
3152 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
3153 return SECFailure;
3154 }
3155 sharedSecret->origin = PK11_OriginGenerated;
3156
3157 attrs = keyTemplate;
3158 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyClass); (attrs)->ulValueLen = (sizeof(keyClass));
;
3159 attrs++;
3160
3161 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType))(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof(keyType));
;
3162 attrs++;
3163
3164 attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse);
3165 attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue);
3166
3167 templateCount = attrs - keyTemplate;
3168 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE))((templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE
))?((void)0):PR_Assert("templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",3168))
;
3169
3170 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_GetInterface(KEMInterfaceName, &KEMInterfaceVersion, &KEMInterface, 0);
3171 if (crv != CKR_OK0x00000000UL) {
3172 goto error;
3173 }
3174 KEMInterfaceFunctions = (CK_NSS_KEM_FUNCTIONS *)(KEMInterface->pFunctionList);
3175
3176 CK_ULONG ciphertextLen = pk11_KEMCiphertextLength(pubKey);
3177 ciphertext = SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), NULL((void*)0), ciphertextLen);
3178 if (ciphertext == NULL((void*)0)) {
3179 crv = CKR_HOST_MEMORY0x00000002UL;
3180 goto error;
3181 }
3182
3183 pk11_EnterKeyMonitor(sharedSecret);
3184 crv = KEMInterfaceFunctions->C_Encapsulate(sharedSecret->session,
3185 &mech,
3186 pubKey->pkcs11ID,
3187 keyTemplate,
3188 templateCount,
3189 &sharedSecret->objectID,
3190 ciphertext->data,
3191 &ciphertextLen);
3192 pk11_ExitKeyMonitor(sharedSecret);
3193 if (crv != CKR_OK0x00000000UL) {
3194 goto error;
3195 }
3196
3197 PORT_Assert(ciphertextLen == ciphertext->len)((ciphertextLen == ciphertext->len)?((void)0):PR_Assert("ciphertextLen == ciphertext->len"
,"pk11skey.c",3197))
;
3198
3199 *outKey = sharedSecret;
3200 *outCiphertext = ciphertext;
3201
3202 return SECSuccess;
3203
3204error:
3205 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
3206 PK11_FreeSymKey(sharedSecret);
3207 SECITEM_FreeItemSECITEM_FreeItem_Util(ciphertext, PR_TRUE1);
3208 return SECFailure;
3209}
3210
3211SECStatus
3212PK11_Decapsulate(SECKEYPrivateKey *privKey, const SECItem *ciphertext, CK_MECHANISM_TYPE target, PK11AttrFlags attrFlags, CK_FLAGS opFlags, PK11SymKey **outKey)
3213{
3214 PORT_Assert(privKey)((privKey)?((void)0):PR_Assert("privKey","pk11skey.c",3214));
3215 PORT_Assert(ciphertext)((ciphertext)?((void)0):PR_Assert("ciphertext","pk11skey.c",3215
))
;
3216 PORT_Assert(outKey)((outKey)?((void)0):PR_Assert("outKey","pk11skey.c",3216));
3217
3218 PK11SlotInfo *slot = privKey->pkcs11Slot;
3219
3220 PK11SymKey *sharedSecret;
3221
3222 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS16];
3223 unsigned int templateCount;
3224
3225 CK_ATTRIBUTE *attrs;
3226 CK_BBOOL cktrue = CK_TRUE1;
3227 CK_BBOOL ckfalse = CK_FALSE0;
3228 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY0x00000004UL;
3229 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET0x00000010UL;
3230
3231 CK_INTERFACE_PTR KEMInterface = NULL((void*)0);
3232 CK_UTF8CHAR_PTR KEMInterfaceName = (CK_UTF8CHAR_PTR) "Vendor NSS KEM Interface";
3233 CK_VERSION KEMInterfaceVersion = { 1, 0 };
3234 CK_NSS_KEM_FUNCTIONS *KEMInterfaceFunctions = NULL((void*)0);
3235
3236 CK_RV crv;
3237
3238 *outKey = NULL((void*)0);
3239
3240 CK_MECHANISM_TYPE kemType;
3241 switch (privKey->keyType) {
3242 case kyberKey:
3243 kemType = CKM_NSS_KYBER((0x80000000UL | 0x4E534350) + 46);
3244 break;
3245 default:
3246 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
3247 return SECFailure;
3248 }
3249
3250 CK_NSS_KEM_PARAMETER_SET_TYPE kemParameterSet = PK11_ReadULongAttribute(slot, privKey->pkcs11ID, CKA_NSS_PARAMETER_SET((0x80000000UL | 0x4E534350) + 40));
3251 CK_MECHANISM mech = { kemType, &kemParameterSet, sizeof(kemParameterSet) };
3252
3253 sharedSecret = pk11_CreateSymKey(slot, target, PR_TRUE1, PR_TRUE1, NULL((void*)0));
3254 if (sharedSecret == NULL((void*)0)) {
3255 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
3256 return SECFailure;
3257 }
3258 sharedSecret->origin = PK11_OriginUnwrap;
3259
3260 attrs = keyTemplate;
3261 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyClass); (attrs)->ulValueLen = (sizeof(keyClass));
;
3262 attrs++;
3263
3264 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType))(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof(keyType));
;
3265 attrs++;
3266
3267 attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse);
3268 attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue);
3269
3270 templateCount = attrs - keyTemplate;
3271 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE))((templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE
))?((void)0):PR_Assert("templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)"
,"pk11skey.c",3271))
;
3272
3273 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_0_PTR)((slot)->functionList))->C_GetInterface(KEMInterfaceName, &KEMInterfaceVersion, &KEMInterface, 0);
3274 if (crv != CKR_OK0x00000000UL) {
3275 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
3276 goto error;
3277 }
3278 KEMInterfaceFunctions = (CK_NSS_KEM_FUNCTIONS *)(KEMInterface->pFunctionList);
3279
3280 pk11_EnterKeyMonitor(sharedSecret);
3281 crv = KEMInterfaceFunctions->C_Decapsulate(sharedSecret->session,
3282 &mech,
3283 privKey->pkcs11ID,
3284 ciphertext->data,
3285 ciphertext->len,
3286 keyTemplate,
3287 templateCount,
3288 &sharedSecret->objectID);
3289 pk11_ExitKeyMonitor(sharedSecret);
3290 if (crv != CKR_OK0x00000000UL) {
3291 goto error;
3292 }
3293
3294 *outKey = sharedSecret;
3295 return SECSuccess;
3296
3297error:
3298 PK11_FreeSymKey(sharedSecret);
3299 return SECFailure;
3300}