Bug Summary

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