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