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