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 PKCS 11 on top of our existing security modules
6  *
7  * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
8  *   This implementation has two slots:
9  *      slot 1 is our generic crypto support. It does not require login.
10  *   It supports Public Key ops, and all they bulk ciphers and hashes.
11  *   It can also support Private Key ops for imported Private keys. It does
12  *   not have any token storage.
13  *      slot 2 is our private key support. It requires a login before use. It
14  *   can store Private Keys and Certs as token objects. Currently only private
15  *   keys and their associated Certificates are saved on the token.
16  *
17  *   In this implementation, session objects are only visible to the session
18  *   that created or generated them.
19  */
20 #include "seccomon.h"
21 #include "secitem.h"
22 #include "secport.h"
23 #include "blapi.h"
24 #include "pkcs11.h"
25 #include "pkcs11i.h"
26 #include "pkcs1sig.h"
27 #include "lowkeyi.h"
28 #include "secder.h"
29 #include "secdig.h"
30 #include "lowpbe.h" /* We do PBE below */
31 #include "pkcs11t.h"
32 #include "secoid.h"
33 #include "cmac.h"
34 #include "alghmac.h"
35 #include "softoken.h"
36 #include "secasn1.h"
37 #include "secerr.h"
38 
39 #include "prprf.h"
40 #include "prenv.h"
41 
42 #define __PASTE(x, y) x##y
43 #define BAD_PARAM_CAST(pMech, typeSize) (!pMech->pParameter || pMech->ulParameterLen < typeSize)
44 /*
45  * we renamed all our internal functions, get the correct
46  * definitions for them...
47  */
48 #undef CK_PKCS11_FUNCTION_INFO
49 #undef CK_NEED_ARG_LIST
50 
51 #define CK_PKCS11_3_0 1
52 
53 #define CK_EXTERN extern
54 #define CK_PKCS11_FUNCTION_INFO(func) \
55     CK_RV __PASTE(NS, func)
56 #define CK_NEED_ARG_LIST 1
57 
58 #include "pkcs11f.h"
59 
60 /* create a definition of SHA1 that's consistent
61  * with the rest of the CKM_SHAxxx hashes*/
62 #define CKM_SHA1 CKM_SHA_1
63 #define CKM_SHA1_HMAC CKM_SHA_1_HMAC
64 #define CKM_SHA1_HMAC_GENERAL CKM_SHA_1_HMAC_GENERAL
65 
66 typedef struct {
67     PRUint8 client_version[2];
68     PRUint8 random[46];
69 } SSL3RSAPreMasterSecret;
70 
71 static void
sftk_Null(void * data,PRBool freeit)72 sftk_Null(void *data, PRBool freeit)
73 {
74     return;
75 }
76 
77 #ifdef EC_DEBUG
78 #define SEC_PRINT(str1, str2, num, sitem)             \
79     printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
80            str1, str2, num, sitem->len);              \
81     for (i = 0; i < sitem->len; i++) {                \
82         printf("%02x:", sitem->data[i]);              \
83     }                                                 \
84     printf("\n")
85 #else
86 #undef EC_DEBUG
87 #define SEC_PRINT(a, b, c, d)
88 #endif
89 
90 /*
91  * free routines.... Free local type  allocated data, and convert
92  * other free routines to the destroy signature.
93  */
94 static void
sftk_FreePrivKey(NSSLOWKEYPrivateKey * key,PRBool freeit)95 sftk_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit)
96 {
97     nsslowkey_DestroyPrivateKey(key);
98 }
99 
100 static void
sftk_Space(void * data,PRBool freeit)101 sftk_Space(void *data, PRBool freeit)
102 {
103     PORT_Free(data);
104 }
105 
106 static void
sftk_ZSpace(void * data,PRBool freeit)107 sftk_ZSpace(void *data, PRBool freeit)
108 {
109     size_t len = *(size_t *)data;
110     PORT_ZFree(data, len);
111 }
112 
113 /*
114  * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
115  * Deprecating a full des key to 40 bit key strenth.
116  */
117 static CK_RV
sftk_cdmf2des(unsigned char * cdmfkey,unsigned char * deskey)118 sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
119 {
120     unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
121     unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
122     unsigned char enc_src[8];
123     unsigned char enc_dest[8];
124     unsigned int leng, i;
125     DESContext *descx;
126     SECStatus rv;
127     CK_RV crv = CKR_OK;
128 
129     /* zero the parity bits */
130     for (i = 0; i < 8; i++) {
131         enc_src[i] = cdmfkey[i] & 0xfe;
132     }
133 
134     /* encrypt with key 1 */
135     descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);
136     if (descx == NULL) {
137         crv = CKR_HOST_MEMORY;
138         goto done;
139     }
140     rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);
141     DES_DestroyContext(descx, PR_TRUE);
142     if (rv != SECSuccess) {
143         crv = sftk_MapCryptError(PORT_GetError());
144         goto done;
145     }
146 
147     /* xor source with des, zero the parity bits and deprecate the key*/
148     for (i = 0; i < 8; i++) {
149         if (i & 1) {
150             enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;
151         } else {
152             enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;
153         }
154     }
155 
156     /* encrypt with key 2 */
157     descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);
158     if (descx == NULL) {
159         crv = CKR_HOST_MEMORY;
160         goto done;
161     }
162     rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);
163     DES_DestroyContext(descx, PR_TRUE);
164     if (rv != SECSuccess) {
165         crv = sftk_MapCryptError(PORT_GetError());
166         goto done;
167     }
168 
169     /* set the corret parity on our new des key */
170     sftk_FormatDESKey(deskey, 8);
171 done:
172     PORT_Memset(enc_src, 0, sizeof enc_src);
173     PORT_Memset(enc_dest, 0, sizeof enc_dest);
174     return crv;
175 }
176 
177 /* NSC_DestroyObject destroys an object. */
178 CK_RV
NSC_DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject)179 NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
180 {
181     SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
182     SFTKSession *session;
183     SFTKObject *object;
184     SFTKFreeStatus status;
185 
186     CHECK_FORK();
187 
188     if (slot == NULL) {
189         return CKR_SESSION_HANDLE_INVALID;
190     }
191     /*
192      * This whole block just makes sure we really can destroy the
193      * requested object.
194      */
195     session = sftk_SessionFromHandle(hSession);
196     if (session == NULL) {
197         return CKR_SESSION_HANDLE_INVALID;
198     }
199 
200     object = sftk_ObjectFromHandle(hObject, session);
201     if (object == NULL) {
202         sftk_FreeSession(session);
203         return CKR_OBJECT_HANDLE_INVALID;
204     }
205 
206     /* don't destroy a private object if we aren't logged in */
207     if ((!slot->isLoggedIn) && (slot->needLogin) &&
208         (sftk_isTrue(object, CKA_PRIVATE))) {
209         sftk_FreeSession(session);
210         sftk_FreeObject(object);
211         return CKR_USER_NOT_LOGGED_IN;
212     }
213 
214     /* don't destroy a token object if we aren't in a rw session */
215 
216     if (((session->info.flags & CKF_RW_SESSION) == 0) &&
217         (sftk_isTrue(object, CKA_TOKEN))) {
218         sftk_FreeSession(session);
219         sftk_FreeObject(object);
220         return CKR_SESSION_READ_ONLY;
221     }
222 
223     sftk_DeleteObject(session, object);
224 
225     sftk_FreeSession(session);
226 
227     /*
228      * get some indication if the object is destroyed. Note: this is not
229      * 100%. Someone may have an object reference outstanding (though that
230      * should not be the case by here. Also note that the object is "half"
231      * destroyed. Our internal representation is destroyed, but it may still
232      * be in the data base.
233      */
234     status = sftk_FreeObject(object);
235 
236     return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
237 }
238 
239 /*
240  ************** Crypto Functions:     Utilities ************************
241  */
242 /*
243  * Utility function for converting PSS/OAEP parameter types into
244  * HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447.
245  */
246 static HASH_HashType
GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech)247 GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech)
248 {
249     switch (mech) {
250         case CKM_SHA_1:
251         case CKG_MGF1_SHA1:
252             return HASH_AlgSHA1;
253         case CKM_SHA224:
254         case CKG_MGF1_SHA224:
255             return HASH_AlgSHA224;
256         case CKM_SHA256:
257         case CKG_MGF1_SHA256:
258             return HASH_AlgSHA256;
259         case CKM_SHA384:
260         case CKG_MGF1_SHA384:
261             return HASH_AlgSHA384;
262         case CKM_SHA512:
263         case CKG_MGF1_SHA512:
264             return HASH_AlgSHA512;
265         default:
266             return HASH_AlgNULL;
267     }
268 }
269 
270 /*
271  * Returns true if "params" contains a valid set of PSS parameters
272  */
273 static PRBool
sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS * params)274 sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params)
275 {
276     if (!params) {
277         return PR_FALSE;
278     }
279     if (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL ||
280         GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) {
281         return PR_FALSE;
282     }
283     return PR_TRUE;
284 }
285 
286 /*
287  * Returns true if "params" contains a valid set of OAEP parameters
288  */
289 static PRBool
sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS * params)290 sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params)
291 {
292     if (!params) {
293         return PR_FALSE;
294     }
295     /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which
296      * state:
297      *   If the parameter is empty, pSourceData must be NULL and
298      *   ulSourceDataLen must be zero.
299      */
300     if (params->source != CKZ_DATA_SPECIFIED ||
301         (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) ||
302         (GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) ||
303         (params->ulSourceDataLen == 0 && params->pSourceData != NULL) ||
304         (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) {
305         return PR_FALSE;
306     }
307     return PR_TRUE;
308 }
309 
310 /*
311  * return a context based on the SFTKContext type.
312  */
313 SFTKSessionContext *
sftk_ReturnContextByType(SFTKSession * session,SFTKContextType type)314 sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
315 {
316     switch (type) {
317         case SFTK_ENCRYPT:
318         case SFTK_DECRYPT:
319         case SFTK_MESSAGE_ENCRYPT:
320         case SFTK_MESSAGE_DECRYPT:
321             return session->enc_context;
322         case SFTK_HASH:
323             return session->hash_context;
324         case SFTK_SIGN:
325         case SFTK_SIGN_RECOVER:
326         case SFTK_VERIFY:
327         case SFTK_VERIFY_RECOVER:
328         case SFTK_MESSAGE_SIGN:
329         case SFTK_MESSAGE_VERIFY:
330             return session->hash_context;
331     }
332     return NULL;
333 }
334 
335 /*
336  * change a context based on the SFTKContext type.
337  */
338 void
sftk_SetContextByType(SFTKSession * session,SFTKContextType type,SFTKSessionContext * context)339 sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
340                       SFTKSessionContext *context)
341 {
342     switch (type) {
343         case SFTK_ENCRYPT:
344         case SFTK_DECRYPT:
345         case SFTK_MESSAGE_ENCRYPT:
346         case SFTK_MESSAGE_DECRYPT:
347             session->enc_context = context;
348             break;
349         case SFTK_HASH:
350             session->hash_context = context;
351             break;
352         case SFTK_SIGN:
353         case SFTK_SIGN_RECOVER:
354         case SFTK_VERIFY:
355         case SFTK_VERIFY_RECOVER:
356         case SFTK_MESSAGE_SIGN:
357         case SFTK_MESSAGE_VERIFY:
358             session->hash_context = context;
359             break;
360     }
361     return;
362 }
363 
364 /*
365  * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
366  * and C_XXX function. The function takes a session handle, the context type,
367  * and wether or not the session needs to be multipart. It returns the context,
368  * and optionally returns the session pointer (if sessionPtr != NULL) if session
369  * pointer is returned, the caller is responsible for freeing it.
370  */
371 CK_RV
sftk_GetContext(CK_SESSION_HANDLE handle,SFTKSessionContext ** contextPtr,SFTKContextType type,PRBool needMulti,SFTKSession ** sessionPtr)372 sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr,
373                 SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr)
374 {
375     SFTKSession *session;
376     SFTKSessionContext *context;
377 
378     session = sftk_SessionFromHandle(handle);
379     if (session == NULL)
380         return CKR_SESSION_HANDLE_INVALID;
381     context = sftk_ReturnContextByType(session, type);
382     /* make sure the context is valid */
383     if ((context == NULL) || (context->type != type) || (needMulti && !(context->multi))) {
384         sftk_FreeSession(session);
385         return CKR_OPERATION_NOT_INITIALIZED;
386     }
387     *contextPtr = context;
388     if (sessionPtr != NULL) {
389         *sessionPtr = session;
390     } else {
391         sftk_FreeSession(session);
392     }
393     return CKR_OK;
394 }
395 
396 /** Terminate operation (in the PKCS#11 spec sense).
397  *  Intuitive name for FreeContext/SetNullContext pair.
398  */
399 void
sftk_TerminateOp(SFTKSession * session,SFTKContextType ctype,SFTKSessionContext * context)400 sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype,
401                  SFTKSessionContext *context)
402 {
403     session->lastOpWasFIPS = context->isFIPS;
404     sftk_FreeContext(context);
405     sftk_SetContextByType(session, ctype, NULL);
406 }
407 
408 /*
409  ************** Crypto Functions:     Encrypt ************************
410  */
411 
412 /*
413  * All the NSC_InitXXX functions have a set of common checks and processing they
414  * all need to do at the beginning. This is done here.
415  */
416 CK_RV
sftk_InitGeneric(SFTKSession * session,CK_MECHANISM * pMechanism,SFTKSessionContext ** contextPtr,SFTKContextType ctype,SFTKObject ** keyPtr,CK_OBJECT_HANDLE hKey,CK_KEY_TYPE * keyTypePtr,CK_OBJECT_CLASS pubKeyType,CK_ATTRIBUTE_TYPE operation)417 sftk_InitGeneric(SFTKSession *session, CK_MECHANISM *pMechanism,
418                  SFTKSessionContext **contextPtr,
419                  SFTKContextType ctype, SFTKObject **keyPtr,
420                  CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
421                  CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation)
422 {
423     SFTKObject *key = NULL;
424     SFTKAttribute *att;
425     SFTKSessionContext *context;
426 
427     /* We can only init if there is not current context active */
428     if (sftk_ReturnContextByType(session, ctype) != NULL) {
429         return CKR_OPERATION_ACTIVE;
430     }
431 
432     /* find the key */
433     if (keyPtr) {
434         key = sftk_ObjectFromHandle(hKey, session);
435         if (key == NULL) {
436             return CKR_KEY_HANDLE_INVALID;
437         }
438 
439         /* make sure it's a valid  key for this operation */
440         if (((key->objclass != CKO_SECRET_KEY) &&
441              (key->objclass != pubKeyType)) ||
442             !sftk_isTrue(key, operation)) {
443             sftk_FreeObject(key);
444             return CKR_KEY_TYPE_INCONSISTENT;
445         }
446         /* get the key type */
447         att = sftk_FindAttribute(key, CKA_KEY_TYPE);
448         if (att == NULL) {
449             sftk_FreeObject(key);
450             return CKR_KEY_TYPE_INCONSISTENT;
451         }
452         PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE));
453         if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) {
454             sftk_FreeAttribute(att);
455             sftk_FreeObject(key);
456             return CKR_ATTRIBUTE_VALUE_INVALID;
457         }
458         PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE));
459         sftk_FreeAttribute(att);
460         *keyPtr = key;
461     }
462 
463     /* allocate the context structure */
464     context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext));
465     if (context == NULL) {
466         if (key)
467             sftk_FreeObject(key);
468         return CKR_HOST_MEMORY;
469     }
470     context->type = ctype;
471     context->multi = PR_TRUE;
472     context->rsa = PR_FALSE;
473     context->cipherInfo = NULL;
474     context->hashInfo = NULL;
475     context->doPad = PR_FALSE;
476     context->padDataLength = 0;
477     context->key = key;
478     context->blockSize = 0;
479     context->maxLen = 0;
480     context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism,
481                                            operation, key);
482     *contextPtr = context;
483     return CKR_OK;
484 }
485 
486 static int
sftk_aes_mode(CK_MECHANISM_TYPE mechanism)487 sftk_aes_mode(CK_MECHANISM_TYPE mechanism)
488 {
489     switch (mechanism) {
490         case CKM_AES_CBC_PAD:
491         case CKM_AES_CBC:
492             return NSS_AES_CBC;
493         case CKM_AES_ECB:
494             return NSS_AES;
495         case CKM_AES_CTS:
496             return NSS_AES_CTS;
497         case CKM_AES_CTR:
498             return NSS_AES_CTR;
499         case CKM_AES_GCM:
500             return NSS_AES_GCM;
501     }
502     return -1;
503 }
504 
505 static SECStatus
sftk_RSAEncryptRaw(NSSLOWKEYPublicKey * key,unsigned char * output,unsigned int * outputLen,unsigned int maxLen,const unsigned char * input,unsigned int inputLen)506 sftk_RSAEncryptRaw(NSSLOWKEYPublicKey *key, unsigned char *output,
507                    unsigned int *outputLen, unsigned int maxLen,
508                    const unsigned char *input, unsigned int inputLen)
509 {
510     SECStatus rv = SECFailure;
511 
512     PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
513     if (key->keyType != NSSLOWKEYRSAKey) {
514         PORT_SetError(SEC_ERROR_INVALID_KEY);
515         return SECFailure;
516     }
517 
518     rv = RSA_EncryptRaw(&key->u.rsa, output, outputLen, maxLen, input,
519                         inputLen);
520     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
521         sftk_fatalError = PR_TRUE;
522     }
523 
524     return rv;
525 }
526 
527 static SECStatus
sftk_RSADecryptRaw(NSSLOWKEYPrivateKey * key,unsigned char * output,unsigned int * outputLen,unsigned int maxLen,const unsigned char * input,unsigned int inputLen)528 sftk_RSADecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output,
529                    unsigned int *outputLen, unsigned int maxLen,
530                    const unsigned char *input, unsigned int inputLen)
531 {
532     SECStatus rv = SECFailure;
533 
534     PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
535     if (key->keyType != NSSLOWKEYRSAKey) {
536         PORT_SetError(SEC_ERROR_INVALID_KEY);
537         return SECFailure;
538     }
539 
540     rv = RSA_DecryptRaw(&key->u.rsa, output, outputLen, maxLen, input,
541                         inputLen);
542     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
543         sftk_fatalError = PR_TRUE;
544     }
545 
546     return rv;
547 }
548 
549 static SECStatus
sftk_RSAEncrypt(NSSLOWKEYPublicKey * key,unsigned char * output,unsigned int * outputLen,unsigned int maxLen,const unsigned char * input,unsigned int inputLen)550 sftk_RSAEncrypt(NSSLOWKEYPublicKey *key, unsigned char *output,
551                 unsigned int *outputLen, unsigned int maxLen,
552                 const unsigned char *input, unsigned int inputLen)
553 {
554     SECStatus rv = SECFailure;
555 
556     PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
557     if (key->keyType != NSSLOWKEYRSAKey) {
558         PORT_SetError(SEC_ERROR_INVALID_KEY);
559         return SECFailure;
560     }
561 
562     rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
563                           inputLen);
564     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
565         sftk_fatalError = PR_TRUE;
566     }
567 
568     return rv;
569 }
570 
571 static SECStatus
sftk_RSADecrypt(NSSLOWKEYPrivateKey * key,unsigned char * output,unsigned int * outputLen,unsigned int maxLen,const unsigned char * input,unsigned int inputLen)572 sftk_RSADecrypt(NSSLOWKEYPrivateKey *key, unsigned char *output,
573                 unsigned int *outputLen, unsigned int maxLen,
574                 const unsigned char *input, unsigned int inputLen)
575 {
576     SECStatus rv = SECFailure;
577 
578     PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
579     if (key->keyType != NSSLOWKEYRSAKey) {
580         PORT_SetError(SEC_ERROR_INVALID_KEY);
581         return SECFailure;
582     }
583 
584     rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
585                           inputLen);
586     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
587         sftk_fatalError = PR_TRUE;
588     }
589 
590     return rv;
591 }
592 
593 static void
sftk_freeRSAOAEPInfo(SFTKOAEPInfo * info,PRBool freeit)594 sftk_freeRSAOAEPInfo(SFTKOAEPInfo *info, PRBool freeit)
595 {
596     PORT_ZFree(info->params.pSourceData, info->params.ulSourceDataLen);
597     PORT_ZFree(info, sizeof(SFTKOAEPInfo));
598 }
599 
600 static SECStatus
sftk_RSAEncryptOAEP(SFTKOAEPInfo * info,unsigned char * output,unsigned int * outputLen,unsigned int maxLen,const unsigned char * input,unsigned int inputLen)601 sftk_RSAEncryptOAEP(SFTKOAEPInfo *info, unsigned char *output,
602                     unsigned int *outputLen, unsigned int maxLen,
603                     const unsigned char *input, unsigned int inputLen)
604 {
605     HASH_HashType hashAlg;
606     HASH_HashType maskHashAlg;
607 
608     PORT_Assert(info->key.pub->keyType == NSSLOWKEYRSAKey);
609     if (info->key.pub->keyType != NSSLOWKEYRSAKey) {
610         PORT_SetError(SEC_ERROR_INVALID_KEY);
611         return SECFailure;
612     }
613 
614     hashAlg = GetHashTypeFromMechanism(info->params.hashAlg);
615     maskHashAlg = GetHashTypeFromMechanism(info->params.mgf);
616 
617     return RSA_EncryptOAEP(&info->key.pub->u.rsa, hashAlg, maskHashAlg,
618                            (const unsigned char *)info->params.pSourceData,
619                            info->params.ulSourceDataLen, NULL, 0,
620                            output, outputLen, maxLen, input, inputLen);
621 }
622 
623 static SECStatus
sftk_RSADecryptOAEP(SFTKOAEPInfo * info,unsigned char * output,unsigned int * outputLen,unsigned int maxLen,const unsigned char * input,unsigned int inputLen)624 sftk_RSADecryptOAEP(SFTKOAEPInfo *info, unsigned char *output,
625                     unsigned int *outputLen, unsigned int maxLen,
626                     const unsigned char *input, unsigned int inputLen)
627 {
628     SECStatus rv = SECFailure;
629     HASH_HashType hashAlg;
630     HASH_HashType maskHashAlg;
631 
632     PORT_Assert(info->key.priv->keyType == NSSLOWKEYRSAKey);
633     if (info->key.priv->keyType != NSSLOWKEYRSAKey) {
634         PORT_SetError(SEC_ERROR_INVALID_KEY);
635         return SECFailure;
636     }
637 
638     hashAlg = GetHashTypeFromMechanism(info->params.hashAlg);
639     maskHashAlg = GetHashTypeFromMechanism(info->params.mgf);
640 
641     rv = RSA_DecryptOAEP(&info->key.priv->u.rsa, hashAlg, maskHashAlg,
642                          (const unsigned char *)info->params.pSourceData,
643                          info->params.ulSourceDataLen,
644                          output, outputLen, maxLen, input, inputLen);
645     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
646         sftk_fatalError = PR_TRUE;
647     }
648     return rv;
649 }
650 
651 static SFTKChaCha20Poly1305Info *
sftk_ChaCha20Poly1305_CreateContext(const unsigned char * key,unsigned int keyLen,const CK_NSS_AEAD_PARAMS * params)652 sftk_ChaCha20Poly1305_CreateContext(const unsigned char *key,
653                                     unsigned int keyLen,
654                                     const CK_NSS_AEAD_PARAMS *params)
655 {
656     SFTKChaCha20Poly1305Info *ctx;
657 
658     if (params->ulNonceLen != sizeof(ctx->nonce)) {
659         PORT_SetError(SEC_ERROR_INPUT_LEN);
660         return NULL;
661     }
662 
663     ctx = PORT_New(SFTKChaCha20Poly1305Info);
664     if (ctx == NULL) {
665         return NULL;
666     }
667 
668     if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen,
669                                      params->ulTagLen) != SECSuccess) {
670         PORT_Free(ctx);
671         return NULL;
672     }
673 
674     PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce));
675 
676     /* AAD data and length must both be null, or both non-null. */
677     PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0));
678 
679     if (params->ulAADLen > sizeof(ctx->ad)) {
680         /* Need to allocate an overflow buffer for the additional data. */
681         ctx->adOverflow = (unsigned char *)PORT_Alloc(params->ulAADLen);
682         if (!ctx->adOverflow) {
683             PORT_Free(ctx);
684             return NULL;
685         }
686         PORT_Memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen);
687     } else {
688         ctx->adOverflow = NULL;
689         if (params->pAAD) {
690             PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen);
691         }
692     }
693     ctx->adLen = params->ulAADLen;
694 
695     return ctx;
696 }
697 
698 static void
sftk_ChaCha20Poly1305_DestroyContext(SFTKChaCha20Poly1305Info * ctx,PRBool freeit)699 sftk_ChaCha20Poly1305_DestroyContext(SFTKChaCha20Poly1305Info *ctx,
700                                      PRBool freeit)
701 {
702     ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE);
703     if (ctx->adOverflow != NULL) {
704         PORT_ZFree(ctx->adOverflow, ctx->adLen);
705         ctx->adOverflow = NULL;
706     } else {
707         PORT_Memset(ctx->ad, 0, ctx->adLen);
708     }
709     ctx->adLen = 0;
710     if (freeit) {
711         PORT_Free(ctx);
712     }
713 }
714 
715 static SECStatus
sftk_ChaCha20Poly1305_Encrypt(const SFTKChaCha20Poly1305Info * ctx,unsigned char * output,unsigned int * outputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)716 sftk_ChaCha20Poly1305_Encrypt(const SFTKChaCha20Poly1305Info *ctx,
717                               unsigned char *output, unsigned int *outputLen,
718                               unsigned int maxOutputLen,
719                               const unsigned char *input, unsigned int inputLen)
720 {
721     const unsigned char *ad = ctx->adOverflow;
722 
723     if (ad == NULL) {
724         ad = ctx->ad;
725     }
726 
727     return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen,
728                                  maxOutputLen, input, inputLen, ctx->nonce,
729                                  sizeof(ctx->nonce), ad, ctx->adLen);
730 }
731 
732 static SECStatus
sftk_ChaCha20Poly1305_Decrypt(const SFTKChaCha20Poly1305Info * ctx,unsigned char * output,unsigned int * outputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)733 sftk_ChaCha20Poly1305_Decrypt(const SFTKChaCha20Poly1305Info *ctx,
734                               unsigned char *output, unsigned int *outputLen,
735                               unsigned int maxOutputLen,
736                               const unsigned char *input, unsigned int inputLen)
737 {
738     const unsigned char *ad = ctx->adOverflow;
739 
740     if (ad == NULL) {
741         ad = ctx->ad;
742     }
743 
744     return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen,
745                                  maxOutputLen, input, inputLen, ctx->nonce,
746                                  sizeof(ctx->nonce), ad, ctx->adLen);
747 }
748 
749 static SECStatus
sftk_ChaCha20Ctr(const SFTKChaCha20CtrInfo * ctx,unsigned char * output,unsigned int * outputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)750 sftk_ChaCha20Ctr(const SFTKChaCha20CtrInfo *ctx,
751                  unsigned char *output, unsigned int *outputLen,
752                  unsigned int maxOutputLen,
753                  const unsigned char *input, unsigned int inputLen)
754 {
755     if (maxOutputLen < inputLen) {
756         PORT_SetError(SEC_ERROR_OUTPUT_LEN);
757         return SECFailure;
758     }
759     ChaCha20_Xor(output, input, inputLen, ctx->key,
760                  ctx->nonce, ctx->counter);
761     *outputLen = inputLen;
762     return SECSuccess;
763 }
764 
765 static void
sftk_ChaCha20Ctr_DestroyContext(SFTKChaCha20CtrInfo * ctx,PRBool freeit)766 sftk_ChaCha20Ctr_DestroyContext(SFTKChaCha20CtrInfo *ctx,
767                                 PRBool freeit)
768 {
769     memset(ctx, 0, sizeof(*ctx));
770     if (freeit) {
771         PORT_Free(ctx);
772     }
773 }
774 
775 /** NSC_CryptInit initializes an encryption/Decryption operation.
776  *
777  * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
778  * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block
779  *  ciphers MAC'ing.
780  */
781 CK_RV
sftk_CryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey,CK_ATTRIBUTE_TYPE mechUsage,CK_ATTRIBUTE_TYPE keyUsage,SFTKContextType contextType,PRBool isEncrypt)782 sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
783                CK_OBJECT_HANDLE hKey,
784                CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage,
785                SFTKContextType contextType, PRBool isEncrypt)
786 {
787     SFTKSession *session;
788     SFTKObject *key;
789     SFTKSessionContext *context;
790     SFTKAttribute *att;
791 #ifndef NSS_DISABLE_DEPRECATED_RC2
792     CK_RC2_CBC_PARAMS *rc2_param;
793     unsigned effectiveKeyLength;
794 #endif
795 #if NSS_SOFTOKEN_DOES_RC5
796     CK_RC5_CBC_PARAMS *rc5_param;
797     SECItem rc5Key;
798 #endif
799     CK_NSS_GCM_PARAMS nss_gcm_param;
800     void *aes_param;
801     CK_NSS_AEAD_PARAMS nss_aead_params;
802     CK_NSS_AEAD_PARAMS *nss_aead_params_ptr = NULL;
803     CK_KEY_TYPE key_type;
804     CK_RV crv = CKR_OK;
805     unsigned char newdeskey[24];
806     PRBool useNewKey = PR_FALSE;
807     int t;
808 
809     if (!pMechanism) {
810         return CKR_MECHANISM_PARAM_INVALID;
811     }
812 
813     crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage);
814     if (crv != CKR_OK)
815         return crv;
816 
817     session = sftk_SessionFromHandle(hSession);
818     if (session == NULL)
819         return CKR_SESSION_HANDLE_INVALID;
820 
821     crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key,
822                            hKey, &key_type,
823                            isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY,
824                            keyUsage);
825 
826     if (crv != CKR_OK) {
827         sftk_FreeSession(session);
828         return crv;
829     }
830 
831     context->doPad = PR_FALSE;
832     switch (pMechanism->mechanism) {
833         case CKM_RSA_PKCS:
834         case CKM_RSA_X_509:
835             if (key_type != CKK_RSA) {
836                 crv = CKR_KEY_TYPE_INCONSISTENT;
837                 break;
838             }
839             context->multi = PR_FALSE;
840             context->rsa = PR_TRUE;
841             if (isEncrypt) {
842                 NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
843                 if (pubKey == NULL) {
844                     crv = CKR_KEY_HANDLE_INVALID;
845                     break;
846                 }
847                 context->maxLen = nsslowkey_PublicModulusLen(pubKey);
848                 context->cipherInfo = (void *)pubKey;
849                 context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509
850                                                    ? sftk_RSAEncryptRaw
851                                                    : sftk_RSAEncrypt);
852             } else {
853                 NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key, CKK_RSA, &crv);
854                 if (privKey == NULL) {
855                     crv = CKR_KEY_HANDLE_INVALID;
856                     break;
857                 }
858                 context->maxLen = nsslowkey_PrivateModulusLen(privKey);
859                 context->cipherInfo = (void *)privKey;
860                 context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509
861                                                    ? sftk_RSADecryptRaw
862                                                    : sftk_RSADecrypt);
863             }
864             context->destroy = sftk_Null;
865             break;
866         case CKM_RSA_PKCS_OAEP:
867             if (key_type != CKK_RSA) {
868                 crv = CKR_KEY_TYPE_INCONSISTENT;
869                 break;
870             }
871             if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) ||
872                 !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter)) {
873                 crv = CKR_MECHANISM_PARAM_INVALID;
874                 break;
875             }
876             context->multi = PR_FALSE;
877             context->rsa = PR_TRUE;
878             {
879                 SFTKOAEPInfo *info;
880                 CK_RSA_PKCS_OAEP_PARAMS *params =
881                     (CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter;
882                 /* make a copy of the source data value for future
883                  * use (once the user has reclaimed his data in pParameter)*/
884                 void *newSource = NULL;
885                 if (params->pSourceData) {
886                     newSource = PORT_Alloc(params->ulSourceDataLen);
887                     if (newSource == NULL) {
888                         crv = CKR_HOST_MEMORY;
889                         break;
890                     }
891                     PORT_Memcpy(newSource, params->pSourceData, params->ulSourceDataLen);
892                 }
893                 info = PORT_New(SFTKOAEPInfo);
894                 if (info == NULL) {
895                     PORT_ZFree(newSource, params->ulSourceDataLen);
896                     crv = CKR_HOST_MEMORY;
897                     break;
898                 }
899                 info->params = *params;
900                 info->params.pSourceData = newSource;
901                 info->isEncrypt = isEncrypt;
902 
903                 /* now setup encryption and decryption contexts */
904                 if (isEncrypt) {
905                     info->key.pub = sftk_GetPubKey(key, CKK_RSA, &crv);
906                     if (info->key.pub == NULL) {
907                         sftk_freeRSAOAEPInfo(info, PR_TRUE);
908                         crv = CKR_KEY_HANDLE_INVALID;
909                         break;
910                     }
911                     context->update = (SFTKCipher)sftk_RSAEncryptOAEP;
912                     context->maxLen = nsslowkey_PublicModulusLen(info->key.pub);
913                 } else {
914                     info->key.priv = sftk_GetPrivKey(key, CKK_RSA, &crv);
915                     if (info->key.priv == NULL) {
916                         sftk_freeRSAOAEPInfo(info, PR_TRUE);
917                         crv = CKR_KEY_HANDLE_INVALID;
918                         break;
919                     }
920                     context->update = (SFTKCipher)sftk_RSADecryptOAEP;
921                     context->maxLen = nsslowkey_PrivateModulusLen(info->key.priv);
922                 }
923                 context->cipherInfo = info;
924             }
925             context->destroy = (SFTKDestroy)sftk_freeRSAOAEPInfo;
926             break;
927 #ifndef NSS_DISABLE_DEPRECATED_RC2
928         case CKM_RC2_CBC_PAD:
929             context->doPad = PR_TRUE;
930         /* fall thru */
931         case CKM_RC2_ECB:
932         case CKM_RC2_CBC:
933             context->blockSize = 8;
934             if (key_type != CKK_RC2) {
935                 crv = CKR_KEY_TYPE_INCONSISTENT;
936                 break;
937             }
938             att = sftk_FindAttribute(key, CKA_VALUE);
939             if (att == NULL) {
940                 crv = CKR_KEY_HANDLE_INVALID;
941                 break;
942             }
943 
944             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) {
945                 crv = CKR_MECHANISM_PARAM_INVALID;
946                 break;
947             }
948             rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
949             effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8;
950             context->cipherInfo =
951                 RC2_CreateContext((unsigned char *)att->attrib.pValue,
952                                   att->attrib.ulValueLen, rc2_param->iv,
953                                   pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : NSS_RC2_CBC, effectiveKeyLength);
954             sftk_FreeAttribute(att);
955             if (context->cipherInfo == NULL) {
956                 crv = CKR_HOST_MEMORY;
957                 break;
958             }
959             context->update = (SFTKCipher)(isEncrypt ? RC2_Encrypt : RC2_Decrypt);
960             context->destroy = (SFTKDestroy)RC2_DestroyContext;
961             break;
962 #endif /* NSS_DISABLE_DEPRECATED_RC2 */
963 
964 #if NSS_SOFTOKEN_DOES_RC5
965         case CKM_RC5_CBC_PAD:
966             context->doPad = PR_TRUE;
967         /* fall thru */
968         case CKM_RC5_ECB:
969         case CKM_RC5_CBC:
970             if (key_type != CKK_RC5) {
971                 crv = CKR_KEY_TYPE_INCONSISTENT;
972                 break;
973             }
974             att = sftk_FindAttribute(key, CKA_VALUE);
975             if (att == NULL) {
976                 crv = CKR_KEY_HANDLE_INVALID;
977                 break;
978             }
979 
980             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_CBC_PARAMS))) {
981                 crv = CKR_MECHANISM_PARAM_INVALID;
982                 break;
983             }
984             rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
985             context->blockSize = rc5_param->ulWordsize * 2;
986             rc5Key.data = (unsigned char *)att->attrib.pValue;
987             rc5Key.len = att->attrib.ulValueLen;
988             context->cipherInfo = RC5_CreateContext(&rc5Key, rc5_param->ulRounds,
989                                                     rc5_param->ulWordsize, rc5_param->pIv,
990                                                     pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
991             sftk_FreeAttribute(att);
992             if (context->cipherInfo == NULL) {
993                 crv = CKR_HOST_MEMORY;
994                 break;
995             }
996             context->update = (SFTKCipher)(isEncrypt ? RC5_Encrypt : RC5_Decrypt);
997             context->destroy = (SFTKDestroy)RC5_DestroyContext;
998             break;
999 #endif
1000         case CKM_RC4:
1001             if (key_type != CKK_RC4) {
1002                 crv = CKR_KEY_TYPE_INCONSISTENT;
1003                 break;
1004             }
1005             att = sftk_FindAttribute(key, CKA_VALUE);
1006             if (att == NULL) {
1007                 crv = CKR_KEY_HANDLE_INVALID;
1008                 break;
1009             }
1010             context->cipherInfo =
1011                 RC4_CreateContext((unsigned char *)att->attrib.pValue,
1012                                   att->attrib.ulValueLen);
1013             sftk_FreeAttribute(att);
1014             if (context->cipherInfo == NULL) {
1015                 crv = CKR_HOST_MEMORY; /* WRONG !!! */
1016                 break;
1017             }
1018             context->update = (SFTKCipher)(isEncrypt ? RC4_Encrypt : RC4_Decrypt);
1019             context->destroy = (SFTKDestroy)RC4_DestroyContext;
1020             break;
1021         case CKM_CDMF_CBC_PAD:
1022             context->doPad = PR_TRUE;
1023         /* fall thru */
1024         case CKM_CDMF_ECB:
1025         case CKM_CDMF_CBC:
1026             if (key_type != CKK_CDMF) {
1027                 crv = CKR_KEY_TYPE_INCONSISTENT;
1028                 break;
1029             }
1030             t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
1031             goto finish_des;
1032         case CKM_DES_ECB:
1033             if (key_type != CKK_DES) {
1034                 crv = CKR_KEY_TYPE_INCONSISTENT;
1035                 break;
1036             }
1037             t = NSS_DES;
1038             goto finish_des;
1039         case CKM_DES_CBC_PAD:
1040             context->doPad = PR_TRUE;
1041         /* fall thru */
1042         case CKM_DES_CBC:
1043             if (key_type != CKK_DES) {
1044                 crv = CKR_KEY_TYPE_INCONSISTENT;
1045                 break;
1046             }
1047             t = NSS_DES_CBC;
1048             goto finish_des;
1049         case CKM_DES3_ECB:
1050             if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
1051                 crv = CKR_KEY_TYPE_INCONSISTENT;
1052                 break;
1053             }
1054             t = NSS_DES_EDE3;
1055             goto finish_des;
1056         case CKM_DES3_CBC_PAD:
1057             context->doPad = PR_TRUE;
1058         /* fall thru */
1059         case CKM_DES3_CBC:
1060             if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
1061                 crv = CKR_KEY_TYPE_INCONSISTENT;
1062                 break;
1063             }
1064             t = NSS_DES_EDE3_CBC;
1065         finish_des:
1066             if ((t != NSS_DES && t != NSS_DES_EDE3) && (pMechanism->pParameter == NULL ||
1067                                                         pMechanism->ulParameterLen < 8)) {
1068                 crv = CKR_DOMAIN_PARAMS_INVALID;
1069                 break;
1070             }
1071             context->blockSize = 8;
1072             att = sftk_FindAttribute(key, CKA_VALUE);
1073             if (att == NULL) {
1074                 crv = CKR_KEY_HANDLE_INVALID;
1075                 break;
1076             }
1077             if (key_type == CKK_DES2 &&
1078                 (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) {
1079                 /* extend DES2 key to DES3 key. */
1080                 memcpy(newdeskey, att->attrib.pValue, 16);
1081                 memcpy(newdeskey + 16, newdeskey, 8);
1082                 useNewKey = PR_TRUE;
1083             } else if (key_type == CKK_CDMF) {
1084                 crv = sftk_cdmf2des((unsigned char *)att->attrib.pValue, newdeskey);
1085                 if (crv != CKR_OK) {
1086                     sftk_FreeAttribute(att);
1087                     break;
1088                 }
1089                 useNewKey = PR_TRUE;
1090             }
1091             context->cipherInfo = DES_CreateContext(
1092                 useNewKey ? newdeskey : (unsigned char *)att->attrib.pValue,
1093                 (unsigned char *)pMechanism->pParameter, t, isEncrypt);
1094             if (useNewKey)
1095                 memset(newdeskey, 0, sizeof newdeskey);
1096             sftk_FreeAttribute(att);
1097             if (context->cipherInfo == NULL) {
1098                 crv = CKR_HOST_MEMORY;
1099                 break;
1100             }
1101             context->update = (SFTKCipher)(isEncrypt ? DES_Encrypt : DES_Decrypt);
1102             context->destroy = (SFTKDestroy)DES_DestroyContext;
1103             break;
1104 #ifndef NSS_DISABLE_DEPRECATED_SEED
1105         case CKM_SEED_CBC_PAD:
1106             context->doPad = PR_TRUE;
1107         /* fall thru */
1108         case CKM_SEED_CBC:
1109             if (!pMechanism->pParameter ||
1110                 pMechanism->ulParameterLen != 16) {
1111                 crv = CKR_MECHANISM_PARAM_INVALID;
1112                 break;
1113             }
1114         /* fall thru */
1115         case CKM_SEED_ECB:
1116             context->blockSize = 16;
1117             if (key_type != CKK_SEED) {
1118                 crv = CKR_KEY_TYPE_INCONSISTENT;
1119                 break;
1120             }
1121             att = sftk_FindAttribute(key, CKA_VALUE);
1122             if (att == NULL) {
1123                 crv = CKR_KEY_HANDLE_INVALID;
1124                 break;
1125             }
1126             context->cipherInfo = SEED_CreateContext(
1127                 (unsigned char *)att->attrib.pValue,
1128                 (unsigned char *)pMechanism->pParameter,
1129                 pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC,
1130                 isEncrypt);
1131             sftk_FreeAttribute(att);
1132             if (context->cipherInfo == NULL) {
1133                 crv = CKR_HOST_MEMORY;
1134                 break;
1135             }
1136             context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt);
1137             context->destroy = (SFTKDestroy)SEED_DestroyContext;
1138             break;
1139 #endif /* NSS_DISABLE_DEPRECATED_SEED */
1140         case CKM_CAMELLIA_CBC_PAD:
1141             context->doPad = PR_TRUE;
1142         /* fall thru */
1143         case CKM_CAMELLIA_CBC:
1144             if (!pMechanism->pParameter ||
1145                 pMechanism->ulParameterLen != 16) {
1146                 crv = CKR_MECHANISM_PARAM_INVALID;
1147                 break;
1148             }
1149         /* fall thru */
1150         case CKM_CAMELLIA_ECB:
1151             context->blockSize = 16;
1152             if (key_type != CKK_CAMELLIA) {
1153                 crv = CKR_KEY_TYPE_INCONSISTENT;
1154                 break;
1155             }
1156             att = sftk_FindAttribute(key, CKA_VALUE);
1157             if (att == NULL) {
1158                 crv = CKR_KEY_HANDLE_INVALID;
1159                 break;
1160             }
1161             context->cipherInfo = Camellia_CreateContext(
1162                 (unsigned char *)att->attrib.pValue,
1163                 (unsigned char *)pMechanism->pParameter,
1164                 pMechanism->mechanism ==
1165                         CKM_CAMELLIA_ECB
1166                     ? NSS_CAMELLIA
1167                     : NSS_CAMELLIA_CBC,
1168                 isEncrypt, att->attrib.ulValueLen);
1169             sftk_FreeAttribute(att);
1170             if (context->cipherInfo == NULL) {
1171                 crv = CKR_HOST_MEMORY;
1172                 break;
1173             }
1174             context->update = (SFTKCipher)(isEncrypt ? Camellia_Encrypt : Camellia_Decrypt);
1175             context->destroy = (SFTKDestroy)Camellia_DestroyContext;
1176             break;
1177 
1178         case CKM_AES_CBC_PAD:
1179             context->doPad = PR_TRUE;
1180         /* fall thru */
1181         case CKM_AES_ECB:
1182         case CKM_AES_CBC:
1183             context->blockSize = 16;
1184         case CKM_AES_CTS:
1185         case CKM_AES_CTR:
1186         case CKM_AES_GCM:
1187             aes_param = pMechanism->pParameter;
1188             /*
1189              *  Due to a mismatch between the documentation and the header
1190              *  file, two different definitions for CK_GCM_PARAMS exist.
1191              *  The header file is normative according to Oasis, but NSS used
1192              *  the documentation. In PKCS #11 v3.0, this was reconciled in
1193              *  favor of the header file definition. To maintain binary
1194              *  compatibility, NSS now defines CK_GCM_PARAMS_V3 as the official
1195              *  version v3 (V2.4 header file) and CK_NSS_GCM_PARAMS as the
1196              *  legacy (V2.4 documentation, NSS version). CK_GCM_PARAMS
1197              *  is defined as CK_GCM_PARAMS_V3 if NSS_PKCS11_2_0_COMPAT is not
1198              *  defined and CK_NSS_GCM_PARAMS if it is. Internally
1199              *  softoken continues to use the legacy version. The code below
1200              *  automatically detects which parameter was passed in and
1201              *  converts CK_GCM_PARAMS_V3 to the CK_NSS_GCM_PARAMS (legacy
1202              *  version) on the fly. NSS proper will eventually start
1203              *  using the CK_GCM_PARAMS_V3 version and fall back to the
1204              *  CK_NSS_GCM_PARAMS if the CK_GCM_PARAMS_V3 version fails with
1205              *  CKR_MECHANISM_PARAM_INVALID.
1206              */
1207             if (pMechanism->mechanism == CKM_AES_GCM) {
1208                 if (!aes_param) {
1209                     crv = CKR_MECHANISM_PARAM_INVALID;
1210                     break;
1211                 }
1212                 if (pMechanism->ulParameterLen == sizeof(CK_GCM_PARAMS_V3)) {
1213                     /* convert the true V3 parameters into the old NSS parameters */
1214                     CK_GCM_PARAMS_V3 *gcm_params = (CK_GCM_PARAMS_V3 *)aes_param;
1215                     if (gcm_params->ulIvLen * 8 != gcm_params->ulIvBits) {
1216                         /* only support byte aligned IV lengths */
1217                         crv = CKR_MECHANISM_PARAM_INVALID;
1218                         break;
1219                     }
1220                     aes_param = (void *)&nss_gcm_param;
1221                     nss_gcm_param.pIv = gcm_params->pIv;
1222                     nss_gcm_param.ulIvLen = gcm_params->ulIvLen;
1223                     nss_gcm_param.pAAD = gcm_params->pAAD;
1224                     nss_gcm_param.ulAADLen = gcm_params->ulAADLen;
1225                     nss_gcm_param.ulTagBits = gcm_params->ulTagBits;
1226                 } else if (pMechanism->ulParameterLen != sizeof(CK_NSS_GCM_PARAMS)) {
1227                     /* neither old nor new style params, must be invalid */
1228                     crv = CKR_MECHANISM_PARAM_INVALID;
1229                     break;
1230                 }
1231             } else if ((pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) ||
1232                        ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) {
1233                 crv = CKR_MECHANISM_PARAM_INVALID;
1234                 break;
1235             }
1236 
1237             if (pMechanism->mechanism == CKM_AES_GCM) {
1238                 context->multi = PR_FALSE;
1239             }
1240             if (key_type != CKK_AES) {
1241                 crv = CKR_KEY_TYPE_INCONSISTENT;
1242                 break;
1243             }
1244             att = sftk_FindAttribute(key, CKA_VALUE);
1245             if (att == NULL) {
1246                 crv = CKR_KEY_HANDLE_INVALID;
1247                 break;
1248             }
1249             context->cipherInfo = AES_CreateContext(
1250                 (unsigned char *)att->attrib.pValue,
1251                 (unsigned char *)aes_param,
1252                 sftk_aes_mode(pMechanism->mechanism),
1253                 isEncrypt, att->attrib.ulValueLen, 16);
1254             sftk_FreeAttribute(att);
1255             if (context->cipherInfo == NULL) {
1256                 crv = CKR_HOST_MEMORY;
1257                 break;
1258             }
1259             context->update = (SFTKCipher)(isEncrypt ? AES_Encrypt : AES_Decrypt);
1260             context->destroy = (SFTKDestroy)AES_DestroyContext;
1261             break;
1262 
1263         case CKM_NSS_CHACHA20_POLY1305:
1264         case CKM_CHACHA20_POLY1305:
1265             if (pMechanism->mechanism == CKM_NSS_CHACHA20_POLY1305) {
1266                 if (key_type != CKK_NSS_CHACHA20) {
1267                     crv = CKR_KEY_TYPE_INCONSISTENT;
1268                     break;
1269                 }
1270                 if ((pMechanism->pParameter == NULL) ||
1271                     (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS))) {
1272                     crv = CKR_MECHANISM_PARAM_INVALID;
1273                     break;
1274                 }
1275                 nss_aead_params_ptr = (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter;
1276             } else {
1277                 CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR chacha_poly_params;
1278                 if (key_type != CKK_CHACHA20) {
1279                     crv = CKR_KEY_TYPE_INCONSISTENT;
1280                     break;
1281                 }
1282                 if ((pMechanism->pParameter == NULL) ||
1283                     (pMechanism->ulParameterLen !=
1284                      sizeof(CK_SALSA20_CHACHA20_POLY1305_PARAMS))) {
1285                     crv = CKR_MECHANISM_PARAM_INVALID;
1286                     break;
1287                 }
1288                 chacha_poly_params = (CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR)
1289                                          pMechanism->pParameter;
1290                 nss_aead_params_ptr = &nss_aead_params;
1291                 nss_aead_params.pNonce = chacha_poly_params->pNonce;
1292                 nss_aead_params.ulNonceLen = chacha_poly_params->ulNonceLen;
1293                 nss_aead_params.pAAD = chacha_poly_params->pAAD;
1294                 nss_aead_params.ulAADLen = chacha_poly_params->ulAADLen;
1295                 nss_aead_params.ulTagLen = 16; /* Poly1305 is always 16 */
1296             }
1297 
1298             context->multi = PR_FALSE;
1299             att = sftk_FindAttribute(key, CKA_VALUE);
1300             if (att == NULL) {
1301                 crv = CKR_KEY_HANDLE_INVALID;
1302                 break;
1303             }
1304             context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext(
1305                 (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen,
1306                 nss_aead_params_ptr);
1307             sftk_FreeAttribute(att);
1308             if (context->cipherInfo == NULL) {
1309                 crv = sftk_MapCryptError(PORT_GetError());
1310                 break;
1311             }
1312             context->update = (SFTKCipher)(isEncrypt ? sftk_ChaCha20Poly1305_Encrypt : sftk_ChaCha20Poly1305_Decrypt);
1313             context->destroy = (SFTKDestroy)sftk_ChaCha20Poly1305_DestroyContext;
1314             break;
1315 
1316         case CKM_NSS_CHACHA20_CTR: /* old NSS private version */
1317         case CKM_CHACHA20:         /* PKCS #11 v3 version */
1318         {
1319             unsigned char *counter;
1320             unsigned char *nonce;
1321             unsigned long counter_len;
1322             unsigned long nonce_len;
1323             context->multi = PR_FALSE;
1324             if (pMechanism->mechanism == CKM_NSS_CHACHA20_CTR) {
1325                 if (key_type != CKK_NSS_CHACHA20) {
1326                     crv = CKR_KEY_TYPE_INCONSISTENT;
1327                     break;
1328                 }
1329                 if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) {
1330                     crv = CKR_MECHANISM_PARAM_INVALID;
1331                     break;
1332                 }
1333                 counter_len = 4;
1334                 counter = pMechanism->pParameter;
1335                 nonce = counter + 4;
1336                 nonce_len = 12;
1337             } else {
1338                 CK_CHACHA20_PARAMS_PTR chacha20_param_ptr;
1339                 if (key_type != CKK_CHACHA20) {
1340                     crv = CKR_KEY_TYPE_INCONSISTENT;
1341                     break;
1342                 }
1343                 if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != sizeof(CK_CHACHA20_PARAMS)) {
1344                     crv = CKR_MECHANISM_PARAM_INVALID;
1345                     break;
1346                 }
1347                 chacha20_param_ptr = (CK_CHACHA20_PARAMS_PTR)pMechanism->pParameter;
1348                 if ((chacha20_param_ptr->blockCounterBits != 32) &&
1349                     (chacha20_param_ptr->blockCounterBits != 64)) {
1350                     crv = CKR_MECHANISM_PARAM_INVALID;
1351                     break;
1352                 }
1353                 counter_len = chacha20_param_ptr->blockCounterBits / PR_BITS_PER_BYTE;
1354                 counter = chacha20_param_ptr->pBlockCounter;
1355                 nonce = chacha20_param_ptr->pNonce;
1356                 nonce_len = chacha20_param_ptr->ulNonceBits / PR_BITS_PER_BYTE;
1357             }
1358 
1359             att = sftk_FindAttribute(key, CKA_VALUE);
1360             if (att == NULL) {
1361                 crv = CKR_KEY_HANDLE_INVALID;
1362                 break;
1363             }
1364             SFTKChaCha20CtrInfo *ctx = PORT_ZNew(SFTKChaCha20CtrInfo);
1365             if (!ctx) {
1366                 sftk_FreeAttribute(att);
1367                 crv = CKR_HOST_MEMORY;
1368                 break;
1369             }
1370             if (att->attrib.ulValueLen != sizeof(ctx->key)) {
1371                 sftk_FreeAttribute(att);
1372                 PORT_Free(ctx);
1373                 crv = CKR_KEY_HANDLE_INVALID;
1374                 break;
1375             }
1376             memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen);
1377             sftk_FreeAttribute(att);
1378 
1379             /* make sure we don't overflow our parameters */
1380             if ((sizeof(ctx->counter) < counter_len) ||
1381                 (sizeof(ctx->nonce) < nonce_len)) {
1382                 PORT_Free(ctx);
1383                 crv = CKR_MECHANISM_PARAM_INVALID;
1384                 break;
1385             }
1386 
1387             /* The counter is little endian. */
1388             int i = 0;
1389             for (; i < counter_len; ++i) {
1390                 ctx->counter |= (PRUint32)counter[i] << (i * 8);
1391             }
1392             memcpy(ctx->nonce, nonce, nonce_len);
1393             context->cipherInfo = ctx;
1394             context->update = (SFTKCipher)sftk_ChaCha20Ctr;
1395             context->destroy = (SFTKDestroy)sftk_ChaCha20Ctr_DestroyContext;
1396             break;
1397         }
1398 
1399         case CKM_NSS_AES_KEY_WRAP_PAD:
1400         case CKM_AES_KEY_WRAP_PAD:
1401             context->doPad = PR_TRUE;
1402         /* fall thru */
1403         case CKM_NSS_AES_KEY_WRAP:
1404         case CKM_AES_KEY_WRAP:
1405             context->blockSize = 8;
1406         case CKM_AES_KEY_WRAP_KWP:
1407             context->multi = PR_FALSE;
1408             if (key_type != CKK_AES) {
1409                 crv = CKR_KEY_TYPE_INCONSISTENT;
1410                 break;
1411             }
1412             att = sftk_FindAttribute(key, CKA_VALUE);
1413             if (att == NULL) {
1414                 crv = CKR_KEY_HANDLE_INVALID;
1415                 break;
1416             }
1417             context->cipherInfo = AESKeyWrap_CreateContext(
1418                 (unsigned char *)att->attrib.pValue,
1419                 (unsigned char *)pMechanism->pParameter,
1420                 isEncrypt, att->attrib.ulValueLen);
1421             sftk_FreeAttribute(att);
1422             if (context->cipherInfo == NULL) {
1423                 crv = CKR_HOST_MEMORY;
1424                 break;
1425             }
1426             if (pMechanism->mechanism == CKM_AES_KEY_WRAP_KWP) {
1427                 context->update = (SFTKCipher)(isEncrypt ? AESKeyWrap_EncryptKWP
1428                                                          : AESKeyWrap_DecryptKWP);
1429             } else {
1430                 context->update = (SFTKCipher)(isEncrypt ? AESKeyWrap_Encrypt
1431                                                          : AESKeyWrap_Decrypt);
1432             }
1433             context->destroy = (SFTKDestroy)AESKeyWrap_DestroyContext;
1434             break;
1435 
1436         default:
1437             crv = CKR_MECHANISM_INVALID;
1438             break;
1439     }
1440 
1441     if (crv != CKR_OK) {
1442         sftk_FreeContext(context);
1443         sftk_FreeSession(session);
1444         return crv;
1445     }
1446     sftk_SetContextByType(session, contextType, context);
1447     sftk_FreeSession(session);
1448     return CKR_OK;
1449 }
1450 
1451 /* NSC_EncryptInit initializes an encryption operation. */
1452 CK_RV
NSC_EncryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)1453 NSC_EncryptInit(CK_SESSION_HANDLE hSession,
1454                 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1455 {
1456     CHECK_FORK();
1457     return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT,
1458                           SFTK_ENCRYPT, PR_TRUE);
1459 }
1460 
1461 /* NSC_EncryptUpdate continues a multiple-part encryption operation. */
1462 CK_RV
NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen,CK_BYTE_PTR pEncryptedPart,CK_ULONG_PTR pulEncryptedPartLen)1463 NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
1464                   CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
1465                   CK_ULONG_PTR pulEncryptedPartLen)
1466 {
1467     SFTKSessionContext *context;
1468     unsigned int outlen, i;
1469     unsigned int padoutlen = 0;
1470     unsigned int maxout = *pulEncryptedPartLen;
1471     CK_RV crv;
1472     SECStatus rv;
1473 
1474     CHECK_FORK();
1475 
1476     /* make sure we're legal */
1477     crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, NULL);
1478     if (crv != CKR_OK)
1479         return crv;
1480 
1481     if (!pEncryptedPart) {
1482         if (context->doPad) {
1483             CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength;
1484             CK_ULONG blocksToSend = totalDataAvailable / context->blockSize;
1485 
1486             *pulEncryptedPartLen = blocksToSend * context->blockSize;
1487             return CKR_OK;
1488         }
1489         *pulEncryptedPartLen = ulPartLen;
1490         return CKR_OK;
1491     }
1492 
1493     /* do padding */
1494     if (context->doPad) {
1495         /* deal with previous buffered data */
1496         if (context->padDataLength != 0) {
1497             /* fill in the padded to a full block size */
1498             for (i = context->padDataLength;
1499                  (ulPartLen != 0) && i < context->blockSize; i++) {
1500                 context->padBuf[i] = *pPart++;
1501                 ulPartLen--;
1502                 context->padDataLength++;
1503             }
1504 
1505             /* not enough data to encrypt yet? then return */
1506             if (context->padDataLength != context->blockSize) {
1507                 *pulEncryptedPartLen = 0;
1508                 return CKR_OK;
1509             }
1510             /* encrypt the current padded data */
1511             rv = (*context->update)(context->cipherInfo, pEncryptedPart,
1512                                     &padoutlen, maxout, context->padBuf,
1513                                     context->blockSize);
1514             if (rv != SECSuccess) {
1515                 return sftk_MapCryptError(PORT_GetError());
1516             }
1517             pEncryptedPart += padoutlen;
1518             maxout -= padoutlen;
1519         }
1520         /* save the residual */
1521         context->padDataLength = ulPartLen % context->blockSize;
1522         if (context->padDataLength) {
1523             PORT_Memcpy(context->padBuf,
1524                         &pPart[ulPartLen - context->padDataLength],
1525                         context->padDataLength);
1526             ulPartLen -= context->padDataLength;
1527         }
1528         /* if we've exhausted our new buffer, we're done */
1529         if (ulPartLen == 0) {
1530             *pulEncryptedPartLen = padoutlen;
1531             return CKR_OK;
1532         }
1533     }
1534 
1535     /* do it: NOTE: this assumes buf size in is >= buf size out! */
1536     rv = (*context->update)(context->cipherInfo, pEncryptedPart,
1537                             &outlen, maxout, pPart, ulPartLen);
1538     if (rv != SECSuccess) {
1539         return sftk_MapCryptError(PORT_GetError());
1540     }
1541     *pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen);
1542     return CKR_OK;
1543 }
1544 
1545 /* NSC_EncryptFinal finishes a multiple-part encryption operation. */
1546 CK_RV
NSC_EncryptFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pLastEncryptedPart,CK_ULONG_PTR pulLastEncryptedPartLen)1547 NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
1548                  CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
1549 {
1550     SFTKSession *session;
1551     SFTKSessionContext *context;
1552     unsigned int outlen, i;
1553     unsigned int maxout = *pulLastEncryptedPartLen;
1554     CK_RV crv;
1555     SECStatus rv = SECSuccess;
1556     PRBool contextFinished = PR_TRUE;
1557 
1558     CHECK_FORK();
1559 
1560     /* make sure we're legal */
1561     crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session);
1562     if (crv != CKR_OK)
1563         return crv;
1564 
1565     *pulLastEncryptedPartLen = 0;
1566     if (!pLastEncryptedPart) {
1567         /* caller is checking the amount of remaining data */
1568         if (context->blockSize > 0 && context->doPad) {
1569             *pulLastEncryptedPartLen = context->blockSize;
1570             contextFinished = PR_FALSE; /* still have padding to go */
1571         }
1572         goto finish;
1573     }
1574 
1575     /* do padding */
1576     if (context->doPad) {
1577         unsigned char padbyte = (unsigned char)(context->blockSize - context->padDataLength);
1578         /* fill out rest of pad buffer with pad magic*/
1579         for (i = context->padDataLength; i < context->blockSize; i++) {
1580             context->padBuf[i] = padbyte;
1581         }
1582         rv = (*context->update)(context->cipherInfo, pLastEncryptedPart,
1583                                 &outlen, maxout, context->padBuf, context->blockSize);
1584         if (rv == SECSuccess)
1585             *pulLastEncryptedPartLen = (CK_ULONG)outlen;
1586     }
1587 
1588 finish:
1589     if (contextFinished)
1590         sftk_TerminateOp(session, SFTK_ENCRYPT, context);
1591     sftk_FreeSession(session);
1592     return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1593 }
1594 
1595 /* NSC_Encrypt encrypts single-part data. */
1596 CK_RV
NSC_Encrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen)1597 NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
1598             CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
1599             CK_ULONG_PTR pulEncryptedDataLen)
1600 {
1601     SFTKSession *session;
1602     SFTKSessionContext *context;
1603     unsigned int outlen;
1604     unsigned int maxoutlen = *pulEncryptedDataLen;
1605     CK_RV crv;
1606     CK_RV crv2;
1607     SECStatus rv = SECSuccess;
1608     SECItem pText;
1609 
1610     pText.type = siBuffer;
1611     pText.data = pData;
1612     pText.len = ulDataLen;
1613 
1614     CHECK_FORK();
1615 
1616     /* make sure we're legal */
1617     crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, &session);
1618     if (crv != CKR_OK)
1619         return crv;
1620 
1621     if (!pEncryptedData) {
1622         outlen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize;
1623         goto done;
1624     }
1625 
1626     if (context->doPad) {
1627         if (context->multi) {
1628             CK_ULONG updateLen = maxoutlen;
1629             CK_ULONG finalLen;
1630             /* padding is fairly complicated, have the update and final
1631              * code deal with it */
1632             sftk_FreeSession(session);
1633             crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData,
1634                                     &updateLen);
1635             if (crv != CKR_OK) {
1636                 updateLen = 0;
1637             }
1638             maxoutlen -= updateLen;
1639             pEncryptedData += updateLen;
1640             finalLen = maxoutlen;
1641             crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
1642             if (crv == CKR_OK && crv2 == CKR_OK) {
1643                 *pulEncryptedDataLen = updateLen + finalLen;
1644             }
1645             return crv == CKR_OK ? crv2 : crv;
1646         }
1647         /* doPad without multi means that padding must be done on the first
1648         ** and only update.  There will be no final.
1649         */
1650         PORT_Assert(context->blockSize > 1);
1651         if (context->blockSize > 1) {
1652             CK_ULONG remainder = ulDataLen % context->blockSize;
1653             CK_ULONG padding = context->blockSize - remainder;
1654             pText.len += padding;
1655             pText.data = PORT_ZAlloc(pText.len);
1656             if (pText.data) {
1657                 memcpy(pText.data, pData, ulDataLen);
1658                 memset(pText.data + ulDataLen, padding, padding);
1659             } else {
1660                 crv = CKR_HOST_MEMORY;
1661                 goto fail;
1662             }
1663         }
1664     }
1665 
1666     /* do it: NOTE: this assumes buf size is big enough. */
1667     rv = (*context->update)(context->cipherInfo, pEncryptedData,
1668                             &outlen, maxoutlen, pText.data, pText.len);
1669     crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1670     if (pText.data != pData)
1671         PORT_ZFree(pText.data, pText.len);
1672 fail:
1673     sftk_TerminateOp(session, SFTK_ENCRYPT, context);
1674 done:
1675     sftk_FreeSession(session);
1676     if (crv == CKR_OK) {
1677         *pulEncryptedDataLen = (CK_ULONG)outlen;
1678     }
1679     return crv;
1680 }
1681 
1682 /*
1683  ************** Crypto Functions:     Decrypt ************************
1684  */
1685 
1686 /* NSC_DecryptInit initializes a decryption operation. */
1687 CK_RV
NSC_DecryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)1688 NSC_DecryptInit(CK_SESSION_HANDLE hSession,
1689                 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1690 {
1691     CHECK_FORK();
1692     return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT,
1693                           SFTK_DECRYPT, PR_FALSE);
1694 }
1695 
1696 /* NSC_DecryptUpdate continues a multiple-part decryption operation. */
1697 CK_RV
NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedPart,CK_ULONG ulEncryptedPartLen,CK_BYTE_PTR pPart,CK_ULONG_PTR pulPartLen)1698 NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
1699                   CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
1700                   CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
1701 {
1702     SFTKSessionContext *context;
1703     unsigned int padoutlen = 0;
1704     unsigned int outlen;
1705     unsigned int maxout = *pulPartLen;
1706     CK_RV crv;
1707     SECStatus rv;
1708 
1709     CHECK_FORK();
1710 
1711     /* make sure we're legal */
1712     crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, NULL);
1713     if (crv != CKR_OK)
1714         return crv;
1715 
1716     /* this can only happen on an NSS programming error */
1717     PORT_Assert((context->padDataLength == 0) || context->padDataLength == context->blockSize);
1718 
1719     if (context->doPad) {
1720         /* Check the data length for block ciphers. If we are padding,
1721          * then we must be using a block cipher. In the non-padding case
1722          * the error will be returned by the underlying decryption
1723          * function when we do the actual decrypt. We need to do the
1724          * check here to avoid returning a negative length to the caller
1725          * or reading before the beginning of the pEncryptedPart buffer.
1726          */
1727         if ((ulEncryptedPartLen == 0) ||
1728             (ulEncryptedPartLen % context->blockSize) != 0) {
1729             return CKR_ENCRYPTED_DATA_LEN_RANGE;
1730         }
1731     }
1732 
1733     if (!pPart) {
1734         if (context->doPad) {
1735             *pulPartLen =
1736                 ulEncryptedPartLen + context->padDataLength - context->blockSize;
1737             return CKR_OK;
1738         }
1739         /* for stream ciphers there is are no constraints on ulEncryptedPartLen.
1740          * for block ciphers, it must be a multiple of blockSize. The error is
1741          * detected when this function is called again do decrypt the output.
1742          */
1743         *pulPartLen = ulEncryptedPartLen;
1744         return CKR_OK;
1745     }
1746 
1747     if (context->doPad) {
1748         /* first decrypt our saved buffer */
1749         if (context->padDataLength != 0) {
1750             rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
1751                                     maxout, context->padBuf, context->blockSize);
1752             if (rv != SECSuccess)
1753                 return sftk_MapDecryptError(PORT_GetError());
1754             pPart += padoutlen;
1755             maxout -= padoutlen;
1756         }
1757         /* now save the final block for the next decrypt or the final */
1758         PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - context->blockSize],
1759                     context->blockSize);
1760         context->padDataLength = context->blockSize;
1761         ulEncryptedPartLen -= context->padDataLength;
1762     }
1763 
1764     /* do it: NOTE: this assumes buf size in is >= buf size out! */
1765     rv = (*context->update)(context->cipherInfo, pPart, &outlen,
1766                             maxout, pEncryptedPart, ulEncryptedPartLen);
1767     if (rv != SECSuccess) {
1768         return sftk_MapDecryptError(PORT_GetError());
1769     }
1770     *pulPartLen = (CK_ULONG)(outlen + padoutlen);
1771     return CKR_OK;
1772 }
1773 
1774 /* NSC_DecryptFinal finishes a multiple-part decryption operation. */
1775 CK_RV
NSC_DecryptFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pLastPart,CK_ULONG_PTR pulLastPartLen)1776 NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
1777                  CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
1778 {
1779     SFTKSession *session;
1780     SFTKSessionContext *context;
1781     unsigned int outlen;
1782     unsigned int maxout = *pulLastPartLen;
1783     CK_RV crv;
1784     SECStatus rv = SECSuccess;
1785 
1786     CHECK_FORK();
1787 
1788     /* make sure we're legal */
1789     crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session);
1790     if (crv != CKR_OK)
1791         return crv;
1792 
1793     *pulLastPartLen = 0;
1794     if (!pLastPart) {
1795         /* caller is checking the amount of remaining data */
1796         if (context->padDataLength > 0) {
1797             *pulLastPartLen = context->padDataLength;
1798         }
1799         goto finish;
1800     }
1801 
1802     if (context->doPad) {
1803         /* decrypt our saved buffer */
1804         if (context->padDataLength != 0) {
1805             /* this assumes that pLastPart is big enough to hold the *whole*
1806              * buffer!!! */
1807             rv = (*context->update)(context->cipherInfo, pLastPart, &outlen,
1808                                     maxout, context->padBuf, context->blockSize);
1809             if (rv != SECSuccess) {
1810                 crv = sftk_MapDecryptError(PORT_GetError());
1811             } else {
1812                 unsigned int padSize = 0;
1813                 crv = sftk_CheckCBCPadding(pLastPart, outlen,
1814                                            context->blockSize, &padSize);
1815                 /* Update pulLastPartLen, in constant time, if crv is OK */
1816                 *pulLastPartLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulLastPartLen);
1817             }
1818         }
1819     }
1820 
1821     sftk_TerminateOp(session, SFTK_DECRYPT, context);
1822 finish:
1823     sftk_FreeSession(session);
1824     return crv;
1825 }
1826 
1827 /* NSC_Decrypt decrypts encrypted data in a single part. */
1828 CK_RV
NSC_Decrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)1829 NSC_Decrypt(CK_SESSION_HANDLE hSession,
1830             CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
1831             CK_ULONG_PTR pulDataLen)
1832 {
1833     SFTKSession *session;
1834     SFTKSessionContext *context;
1835     unsigned int outlen;
1836     unsigned int maxoutlen = *pulDataLen;
1837     CK_RV crv;
1838     CK_RV crv2;
1839     SECStatus rv = SECSuccess;
1840 
1841     CHECK_FORK();
1842 
1843     /* make sure we're legal */
1844     crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_FALSE, &session);
1845     if (crv != CKR_OK)
1846         return crv;
1847 
1848     if (!pData) {
1849         *pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize);
1850         goto done;
1851     }
1852 
1853     if (context->doPad && context->multi) {
1854         CK_ULONG updateLen = maxoutlen;
1855         CK_ULONG finalLen;
1856         /* padding is fairly complicated, have the update and final
1857          * code deal with it */
1858         sftk_FreeSession(session);
1859         crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
1860                                 pData, &updateLen);
1861         if (crv == CKR_OK) {
1862             maxoutlen -= updateLen;
1863             pData += updateLen;
1864         }
1865         finalLen = maxoutlen;
1866         crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
1867         if (crv == CKR_OK) {
1868             *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv2), updateLen + finalLen, *pulDataLen);
1869             return crv2;
1870         } else {
1871             return crv;
1872         }
1873     }
1874 
1875     rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
1876                             pEncryptedData, ulEncryptedDataLen);
1877     /* XXX need to do MUCH better error mapping than this. */
1878     crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
1879     if (rv == SECSuccess) {
1880         if (context->doPad) {
1881             unsigned int padSize = 0;
1882             crv = sftk_CheckCBCPadding(pData, outlen, context->blockSize,
1883                                        &padSize);
1884             /* Update pulDataLen, in constant time, if crv is OK */
1885             *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulDataLen);
1886         } else {
1887             *pulDataLen = (CK_ULONG)outlen;
1888         }
1889     }
1890     sftk_TerminateOp(session, SFTK_DECRYPT, context);
1891 done:
1892     sftk_FreeSession(session);
1893     return crv;
1894 }
1895 
1896 /*
1897  ************** Crypto Functions:     Digest (HASH)  ************************
1898  */
1899 
1900 /* NSC_DigestInit initializes a message-digesting operation. */
1901 CK_RV
NSC_DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism)1902 NSC_DigestInit(CK_SESSION_HANDLE hSession,
1903                CK_MECHANISM_PTR pMechanism)
1904 {
1905     SFTKSession *session;
1906     SFTKSessionContext *context;
1907     CK_RV crv = CKR_OK;
1908 
1909     CHECK_FORK();
1910 
1911     session = sftk_SessionFromHandle(hSession);
1912     if (session == NULL)
1913         return CKR_SESSION_HANDLE_INVALID;
1914     crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_HASH,
1915                            NULL, 0, NULL, 0, CKA_DIGEST);
1916     if (crv != CKR_OK) {
1917         sftk_FreeSession(session);
1918         return crv;
1919     }
1920 
1921 #define INIT_MECH(mmm)                                         \
1922     case CKM_##mmm: {                                          \
1923         mmm##Context *mmm##_ctx = mmm##_NewContext();          \
1924         context->cipherInfo = (void *)mmm##_ctx;               \
1925         context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \
1926         context->currentMech = CKM_##mmm;                      \
1927         context->hashUpdate = (SFTKHash)mmm##_Update;          \
1928         context->end = (SFTKEnd)mmm##_End;                     \
1929         context->destroy = (SFTKDestroy)mmm##_DestroyContext;  \
1930         context->maxLen = mmm##_LENGTH;                        \
1931         if (mmm##_ctx)                                         \
1932             mmm##_Begin(mmm##_ctx);                            \
1933         else                                                   \
1934             crv = CKR_HOST_MEMORY;                             \
1935         break;                                                 \
1936     }
1937 
1938     switch (pMechanism->mechanism) {
1939         INIT_MECH(MD2)
1940         INIT_MECH(MD5)
1941         INIT_MECH(SHA1)
1942         INIT_MECH(SHA224)
1943         INIT_MECH(SHA256)
1944         INIT_MECH(SHA384)
1945         INIT_MECH(SHA512)
1946 
1947         default:
1948             crv = CKR_MECHANISM_INVALID;
1949             break;
1950     }
1951 
1952     if (crv != CKR_OK) {
1953         sftk_FreeContext(context);
1954         sftk_FreeSession(session);
1955         return crv;
1956     }
1957     sftk_SetContextByType(session, SFTK_HASH, context);
1958     sftk_FreeSession(session);
1959     return CKR_OK;
1960 }
1961 
1962 /* NSC_Digest digests data in a single part. */
1963 CK_RV
NSC_Digest(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)1964 NSC_Digest(CK_SESSION_HANDLE hSession,
1965            CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
1966            CK_ULONG_PTR pulDigestLen)
1967 {
1968     SFTKSession *session;
1969     SFTKSessionContext *context;
1970     unsigned int digestLen;
1971     unsigned int maxout = *pulDigestLen;
1972     CK_RV crv;
1973 
1974     CHECK_FORK();
1975 
1976     /* make sure we're legal */
1977     crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_FALSE, &session);
1978     if (crv != CKR_OK)
1979         return crv;
1980 
1981     if (pDigest == NULL) {
1982         *pulDigestLen = context->maxLen;
1983         goto finish;
1984     }
1985 
1986     /* do it: */
1987     (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
1988     /*  NOTE: this assumes buf size is bigenough for the algorithm */
1989     (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
1990     *pulDigestLen = digestLen;
1991 
1992     sftk_TerminateOp(session, SFTK_HASH, context);
1993 finish:
1994     sftk_FreeSession(session);
1995     return CKR_OK;
1996 }
1997 
1998 /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
1999 CK_RV
NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)2000 NSC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
2001                  CK_ULONG ulPartLen)
2002 {
2003     SFTKSessionContext *context;
2004     CK_RV crv;
2005 
2006     CHECK_FORK();
2007 
2008     /* make sure we're legal */
2009     crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, NULL);
2010     if (crv != CKR_OK)
2011         return crv;
2012     /* do it: */
2013     (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);
2014     return CKR_OK;
2015 }
2016 
2017 /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
2018 CK_RV
NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)2019 NSC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
2020                 CK_ULONG_PTR pulDigestLen)
2021 {
2022     SFTKSession *session;
2023     SFTKSessionContext *context;
2024     unsigned int maxout = *pulDigestLen;
2025     unsigned int digestLen;
2026     CK_RV crv;
2027 
2028     CHECK_FORK();
2029 
2030     /* make sure we're legal */
2031     crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
2032     if (crv != CKR_OK)
2033         return crv;
2034 
2035     if (pDigest != NULL) {
2036         (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
2037         *pulDigestLen = digestLen;
2038         sftk_TerminateOp(session, SFTK_HASH, context);
2039     } else {
2040         *pulDigestLen = context->maxLen;
2041     }
2042 
2043     sftk_FreeSession(session);
2044     return CKR_OK;
2045 }
2046 
2047 /*
2048  * these helper functions are used by Generic Macing and Signing functions
2049  * that use hashes as part of their operations.
2050  */
2051 #define DOSUB(mmm)                                                \
2052     static CK_RV                                                  \
2053         sftk_doSub##mmm(SFTKSessionContext *context)              \
2054     {                                                             \
2055         mmm##Context *mmm##_ctx = mmm##_NewContext();             \
2056         context->hashInfo = (void *)mmm##_ctx;                    \
2057         context->hashUpdate = (SFTKHash)mmm##_Update;             \
2058         context->end = (SFTKEnd)mmm##_End;                        \
2059         context->hashdestroy = (SFTKDestroy)mmm##_DestroyContext; \
2060         if (!context->hashInfo) {                                 \
2061             return CKR_HOST_MEMORY;                               \
2062         }                                                         \
2063         mmm##_Begin(mmm##_ctx);                                   \
2064         return CKR_OK;                                            \
2065     }
2066 
2067 DOSUB(MD2)
DOSUB(MD5)2068 DOSUB(MD5)
2069 DOSUB(SHA1)
2070 DOSUB(SHA224)
2071 DOSUB(SHA256)
2072 DOSUB(SHA384)
2073 DOSUB(SHA512)
2074 
2075 static SECStatus
2076 sftk_SignCopy(
2077     CK_ULONG *copyLen,
2078     void *out, unsigned int *outLength,
2079     unsigned int maxLength,
2080     const unsigned char *hashResult,
2081     unsigned int hashResultLength)
2082 {
2083     unsigned int toCopy = *copyLen;
2084     if (toCopy > maxLength) {
2085         toCopy = maxLength;
2086     }
2087     if (toCopy > hashResultLength) {
2088         toCopy = hashResultLength;
2089     }
2090     memcpy(out, hashResult, toCopy);
2091     if (outLength) {
2092         *outLength = toCopy;
2093     }
2094     return SECSuccess;
2095 }
2096 
2097 /* Verify is just a compare for HMAC */
2098 static SECStatus
sftk_HMACCmp(CK_ULONG * copyLen,unsigned char * sig,unsigned int sigLen,unsigned char * hash,unsigned int hashLen)2099 sftk_HMACCmp(CK_ULONG *copyLen, unsigned char *sig, unsigned int sigLen,
2100              unsigned char *hash, unsigned int hashLen)
2101 {
2102     return (NSS_SecureMemcmp(sig, hash, *copyLen) == 0) ? SECSuccess : SECFailure;
2103 }
2104 
2105 /*
2106  * common HMAC + CMAC initialization routine
2107  */
2108 static CK_RV
sftk_doMACInit(CK_MECHANISM_TYPE mech,SFTKSessionContext * session,SFTKObject * key,CK_ULONG mac_size)2109 sftk_doMACInit(CK_MECHANISM_TYPE mech, SFTKSessionContext *session,
2110                SFTKObject *key, CK_ULONG mac_size)
2111 {
2112     CK_RV crv;
2113     sftk_MACCtx *context;
2114     CK_ULONG *intpointer;
2115     PRBool isFIPS = sftk_isFIPS(key->slot->slotID);
2116 
2117     /* Set up the initial context. */
2118     crv = sftk_MAC_Create(mech, key, &context);
2119     if (crv != CKR_OK) {
2120         return crv;
2121     }
2122 
2123     session->hashInfo = context;
2124     session->multi = PR_TRUE;
2125 
2126     /* Required by FIPS 198 Section 4. Delay this check until after the MAC
2127      * has been initialized to steal the output size of the MAC. */
2128     if (isFIPS && (mac_size < 4 || mac_size < context->mac_size / 2)) {
2129         sftk_MAC_Destroy(context, PR_TRUE);
2130         return CKR_BUFFER_TOO_SMALL;
2131     }
2132 
2133     /* Configure our helper functions appropriately. Note that these casts
2134      * ignore the return values. */
2135     session->hashUpdate = (SFTKHash)sftk_MAC_Update;
2136     session->end = (SFTKEnd)sftk_MAC_Finish;
2137     session->hashdestroy = (SFTKDestroy)sftk_MAC_Destroy;
2138 
2139     intpointer = PORT_New(CK_ULONG);
2140     if (intpointer == NULL) {
2141         sftk_MAC_Destroy(context, PR_TRUE);
2142         return CKR_HOST_MEMORY;
2143     }
2144     *intpointer = mac_size;
2145     session->cipherInfo = intpointer;
2146 
2147     /* Since we're only "hashing", copy the result from session->end to the
2148      * caller using sftk_SignCopy. */
2149     session->update = (SFTKCipher)sftk_SignCopy;
2150     session->verify = (SFTKVerify)sftk_HMACCmp;
2151     session->destroy = (SFTKDestroy)sftk_Space;
2152 
2153     session->maxLen = context->mac_size;
2154 
2155     return CKR_OK;
2156 }
2157 
2158 /*
2159  *  SSL Macing support. SSL Macs are inited, then update with the base
2160  * hashing algorithm, then finalized in sign and verify
2161  */
2162 
2163 /*
2164  * FROM SSL:
2165  * 60 bytes is 3 times the maximum length MAC size that is supported.
2166  * We probably should have one copy of this table. We still need this table
2167  * in ssl to 'sign' the handshake hashes.
2168  */
2169 static unsigned char ssl_pad_1[60] = {
2170     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2171     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2172     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2173     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2174     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2175     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2176     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2177     0x36, 0x36, 0x36, 0x36
2178 };
2179 static unsigned char ssl_pad_2[60] = {
2180     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2181     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2182     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2183     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2184     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2185     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2186     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2187     0x5c, 0x5c, 0x5c, 0x5c
2188 };
2189 
2190 static SECStatus
sftk_SSLMACSign(SFTKSSLMACInfo * info,unsigned char * sig,unsigned int * sigLen,unsigned int maxLen,unsigned char * hash,unsigned int hashLen)2191 sftk_SSLMACSign(SFTKSSLMACInfo *info, unsigned char *sig, unsigned int *sigLen,
2192                 unsigned int maxLen, unsigned char *hash, unsigned int hashLen)
2193 {
2194     unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
2195     unsigned int out;
2196 
2197     info->begin(info->hashContext);
2198     info->update(info->hashContext, info->key, info->keySize);
2199     info->update(info->hashContext, ssl_pad_2, info->padSize);
2200     info->update(info->hashContext, hash, hashLen);
2201     info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH);
2202     PORT_Memcpy(sig, tmpBuf, info->macSize);
2203     PORT_Memset(tmpBuf, 0, info->macSize);
2204     *sigLen = info->macSize;
2205     return SECSuccess;
2206 }
2207 
2208 static SECStatus
sftk_SSLMACVerify(SFTKSSLMACInfo * info,unsigned char * sig,unsigned int sigLen,unsigned char * hash,unsigned int hashLen)2209 sftk_SSLMACVerify(SFTKSSLMACInfo *info, unsigned char *sig, unsigned int sigLen,
2210                   unsigned char *hash, unsigned int hashLen)
2211 {
2212     unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
2213     unsigned int out;
2214     int cmp;
2215 
2216     info->begin(info->hashContext);
2217     info->update(info->hashContext, info->key, info->keySize);
2218     info->update(info->hashContext, ssl_pad_2, info->padSize);
2219     info->update(info->hashContext, hash, hashLen);
2220     info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH);
2221     cmp = NSS_SecureMemcmp(sig, tmpBuf, info->macSize);
2222     PORT_Memset(tmpBuf, 0, info->macSize);
2223     return (cmp == 0) ? SECSuccess : SECFailure;
2224 }
2225 
2226 /*
2227  * common HMAC initalization routine
2228  */
2229 static CK_RV
sftk_doSSLMACInit(SFTKSessionContext * context,SECOidTag oid,SFTKObject * key,CK_ULONG mac_size)2230 sftk_doSSLMACInit(SFTKSessionContext *context, SECOidTag oid,
2231                   SFTKObject *key, CK_ULONG mac_size)
2232 {
2233     SFTKAttribute *keyval;
2234     SFTKBegin begin;
2235     int padSize;
2236     SFTKSSLMACInfo *sslmacinfo;
2237     CK_RV crv = CKR_MECHANISM_INVALID;
2238 
2239     if (oid == SEC_OID_SHA1) {
2240         crv = sftk_doSubSHA1(context);
2241         if (crv != CKR_OK)
2242             return crv;
2243         begin = (SFTKBegin)SHA1_Begin;
2244         padSize = 40;
2245     } else {
2246         crv = sftk_doSubMD5(context);
2247         if (crv != CKR_OK)
2248             return crv;
2249         begin = (SFTKBegin)MD5_Begin;
2250         padSize = 48;
2251     }
2252     context->multi = PR_TRUE;
2253 
2254     keyval = sftk_FindAttribute(key, CKA_VALUE);
2255     if (keyval == NULL)
2256         return CKR_KEY_SIZE_RANGE;
2257 
2258     context->hashUpdate(context->hashInfo, keyval->attrib.pValue,
2259                         keyval->attrib.ulValueLen);
2260     context->hashUpdate(context->hashInfo, ssl_pad_1, padSize);
2261     sslmacinfo = (SFTKSSLMACInfo *)PORT_Alloc(sizeof(SFTKSSLMACInfo));
2262     if (sslmacinfo == NULL) {
2263         sftk_FreeAttribute(keyval);
2264         return CKR_HOST_MEMORY;
2265     }
2266     sslmacinfo->size = sizeof(SFTKSSLMACInfo);
2267     sslmacinfo->macSize = mac_size;
2268     sslmacinfo->hashContext = context->hashInfo;
2269     PORT_Memcpy(sslmacinfo->key, keyval->attrib.pValue,
2270                 keyval->attrib.ulValueLen);
2271     sslmacinfo->keySize = keyval->attrib.ulValueLen;
2272     sslmacinfo->begin = begin;
2273     sslmacinfo->end = context->end;
2274     sslmacinfo->update = context->hashUpdate;
2275     sslmacinfo->padSize = padSize;
2276     sftk_FreeAttribute(keyval);
2277     context->cipherInfo = (void *)sslmacinfo;
2278     context->destroy = (SFTKDestroy)sftk_ZSpace;
2279     context->update = (SFTKCipher)sftk_SSLMACSign;
2280     context->verify = (SFTKVerify)sftk_SSLMACVerify;
2281     context->maxLen = mac_size;
2282     return CKR_OK;
2283 }
2284 
2285 /*
2286  ************** Crypto Functions:     Sign  ************************
2287  */
2288 
2289 /**
2290  * Check if We're using CBCMacing and initialize the session context if we are.
2291  *  @param contextType SFTK_SIGN or SFTK_VERIFY
2292  *  @param keyUsage    check whether key allows this usage
2293  */
2294 static CK_RV
sftk_InitCBCMac(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey,CK_ATTRIBUTE_TYPE keyUsage,SFTKContextType contextType)2295 sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
2296                 CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,
2297                 SFTKContextType contextType)
2298 
2299 {
2300     CK_MECHANISM cbc_mechanism;
2301     CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
2302 #ifndef NSS_DISABLE_DEPRECATED_RC2
2303     CK_RC2_CBC_PARAMS rc2_params;
2304 #endif
2305 #if NSS_SOFTOKEN_DOES_RC5
2306     CK_RC5_CBC_PARAMS rc5_params;
2307     CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
2308 #endif
2309     unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
2310     unsigned char k2[SFTK_MAX_BLOCK_SIZE];
2311     unsigned char k3[SFTK_MAX_BLOCK_SIZE];
2312     SFTKSessionContext *context;
2313     CK_RV crv;
2314     unsigned int blockSize;
2315     PRBool isXCBC = PR_FALSE;
2316 
2317     if (!pMechanism) {
2318         return CKR_MECHANISM_PARAM_INVALID;
2319     }
2320 
2321     switch (pMechanism->mechanism) {
2322 #ifndef NSS_DISABLE_DEPRECATED_RC2
2323         case CKM_RC2_MAC_GENERAL:
2324             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) {
2325                 return CKR_MECHANISM_PARAM_INVALID;
2326             }
2327             mac_bytes =
2328                 ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
2329         /* fall through */
2330         case CKM_RC2_MAC:
2331             /* this works because ulEffectiveBits is in the same place in both the
2332              * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */
2333             rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *)
2334                                               pMechanism->pParameter)
2335                                              ->ulEffectiveBits;
2336             PORT_Memset(rc2_params.iv, 0, sizeof(rc2_params.iv));
2337             cbc_mechanism.mechanism = CKM_RC2_CBC;
2338             cbc_mechanism.pParameter = &rc2_params;
2339             cbc_mechanism.ulParameterLen = sizeof(rc2_params);
2340             blockSize = 8;
2341             break;
2342 #endif /* NSS_DISABLE_DEPRECATED_RC2 */
2343 
2344 #if NSS_SOFTOKEN_DOES_RC5
2345         case CKM_RC5_MAC_GENERAL:
2346             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
2347                 return CKR_MECHANISM_PARAM_INVALID;
2348             }
2349             mac_bytes =
2350                 ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
2351         /* fall through */
2352         case CKM_RC5_MAC:
2353             /* this works because ulEffectiveBits is in the same place in both the
2354              * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
2355             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
2356                 return CKR_MECHANISM_PARAM_INVALID;
2357             }
2358             rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
2359             rc5_params.ulWordsize = rc5_mac->ulWordsize;
2360             rc5_params.ulRounds = rc5_mac->ulRounds;
2361             rc5_params.pIv = ivBlock;
2362             if ((blockSize = rc5_mac->ulWordsize * 2) > SFTK_MAX_BLOCK_SIZE)
2363                 return CKR_MECHANISM_PARAM_INVALID;
2364             rc5_params.ulIvLen = blockSize;
2365             PORT_Memset(ivBlock, 0, blockSize);
2366             cbc_mechanism.mechanism = CKM_RC5_CBC;
2367             cbc_mechanism.pParameter = &rc5_params;
2368             cbc_mechanism.ulParameterLen = sizeof(rc5_params);
2369             break;
2370 #endif
2371         /* add cast and idea later */
2372         case CKM_DES_MAC_GENERAL:
2373             mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2374         /* fall through */
2375         case CKM_DES_MAC:
2376             blockSize = 8;
2377             PORT_Memset(ivBlock, 0, blockSize);
2378             cbc_mechanism.mechanism = CKM_DES_CBC;
2379             cbc_mechanism.pParameter = &ivBlock;
2380             cbc_mechanism.ulParameterLen = blockSize;
2381             break;
2382         case CKM_DES3_MAC_GENERAL:
2383             mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2384         /* fall through */
2385         case CKM_DES3_MAC:
2386             blockSize = 8;
2387             PORT_Memset(ivBlock, 0, blockSize);
2388             cbc_mechanism.mechanism = CKM_DES3_CBC;
2389             cbc_mechanism.pParameter = &ivBlock;
2390             cbc_mechanism.ulParameterLen = blockSize;
2391             break;
2392         case CKM_CDMF_MAC_GENERAL:
2393             mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2394         /* fall through */
2395         case CKM_CDMF_MAC:
2396             blockSize = 8;
2397             PORT_Memset(ivBlock, 0, blockSize);
2398             cbc_mechanism.mechanism = CKM_CDMF_CBC;
2399             cbc_mechanism.pParameter = &ivBlock;
2400             cbc_mechanism.ulParameterLen = blockSize;
2401             break;
2402 #ifndef NSS_DISABLE_DEPRECATED_SEED
2403         case CKM_SEED_MAC_GENERAL:
2404             mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2405         /* fall through */
2406         case CKM_SEED_MAC:
2407             blockSize = 16;
2408             PORT_Memset(ivBlock, 0, blockSize);
2409             cbc_mechanism.mechanism = CKM_SEED_CBC;
2410             cbc_mechanism.pParameter = &ivBlock;
2411             cbc_mechanism.ulParameterLen = blockSize;
2412             break;
2413 #endif /* NSS_DISABLE_DEPRECATED_SEED */
2414         case CKM_CAMELLIA_MAC_GENERAL:
2415             mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2416         /* fall through */
2417         case CKM_CAMELLIA_MAC:
2418             blockSize = 16;
2419             PORT_Memset(ivBlock, 0, blockSize);
2420             cbc_mechanism.mechanism = CKM_CAMELLIA_CBC;
2421             cbc_mechanism.pParameter = &ivBlock;
2422             cbc_mechanism.ulParameterLen = blockSize;
2423             break;
2424         case CKM_AES_MAC_GENERAL:
2425             mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2426         /* fall through */
2427         case CKM_AES_MAC:
2428             blockSize = 16;
2429             PORT_Memset(ivBlock, 0, blockSize);
2430             cbc_mechanism.mechanism = CKM_AES_CBC;
2431             cbc_mechanism.pParameter = &ivBlock;
2432             cbc_mechanism.ulParameterLen = blockSize;
2433             break;
2434         case CKM_AES_XCBC_MAC_96:
2435         case CKM_AES_XCBC_MAC:
2436             /* The only difference between CKM_AES_XCBC_MAC
2437              * and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */
2438             mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16;
2439             blockSize = 16;
2440             PORT_Memset(ivBlock, 0, blockSize);
2441             cbc_mechanism.mechanism = CKM_AES_CBC;
2442             cbc_mechanism.pParameter = &ivBlock;
2443             cbc_mechanism.ulParameterLen = blockSize;
2444             /* is XCBC requires extra processing at the end of the operation */
2445             isXCBC = PR_TRUE;
2446             /* The input key is used to generate k1, k2, and k3. k2 and k3
2447              * are used at the end in the pad step. k1 replaces the input
2448              * key in the aes cbc mac */
2449             crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3);
2450             if (crv != CKR_OK) {
2451                 return crv;
2452             }
2453             break;
2454         default:
2455             return CKR_FUNCTION_NOT_SUPPORTED;
2456     }
2457 
2458     /* if MAC size is externally supplied, it should be checked.
2459      */
2460     if (mac_bytes == SFTK_INVALID_MAC_SIZE)
2461         mac_bytes = blockSize >> 1;
2462     else {
2463         if (mac_bytes > blockSize) {
2464             crv = CKR_MECHANISM_PARAM_INVALID;
2465             goto fail;
2466         }
2467     }
2468 
2469     crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
2470                          CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
2471                          keyUsage, contextType, PR_TRUE);
2472     if (crv != CKR_OK)
2473         goto fail;
2474     crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
2475 
2476     /* this shouldn't happen! */
2477     PORT_Assert(crv == CKR_OK);
2478     if (crv != CKR_OK)
2479         goto fail;
2480     context->blockSize = blockSize;
2481     context->macSize = mac_bytes;
2482     context->isXCBC = isXCBC;
2483     if (isXCBC) {
2484         /* save the xcbc specific parameters */
2485         PORT_Memcpy(context->k2, k2, blockSize);
2486         PORT_Memcpy(context->k3, k3, blockSize);
2487         PORT_Memset(k2, 0, blockSize);
2488         PORT_Memset(k3, 0, blockSize);
2489         /* get rid of the temp key now that the context has been created */
2490         NSC_DestroyObject(hSession, hKey);
2491     }
2492     return CKR_OK;
2493 fail:
2494     if (isXCBC) {
2495         PORT_Memset(k2, 0, blockSize);
2496         PORT_Memset(k3, 0, blockSize);
2497         NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */
2498     }
2499     return crv;
2500 }
2501 
2502 /*
2503  * encode RSA PKCS #1 Signature data before signing...
2504  */
2505 static SECStatus
sftk_RSAHashSign(SFTKHashSignInfo * info,unsigned char * sig,unsigned int * sigLen,unsigned int maxLen,const unsigned char * hash,unsigned int hashLen)2506 sftk_RSAHashSign(SFTKHashSignInfo *info, unsigned char *sig,
2507                  unsigned int *sigLen, unsigned int maxLen,
2508                  const unsigned char *hash, unsigned int hashLen)
2509 {
2510     PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2511     if (info->key->keyType != NSSLOWKEYRSAKey) {
2512         PORT_SetError(SEC_ERROR_INVALID_KEY);
2513         return SECFailure;
2514     }
2515 
2516     return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen,
2517                         hash, hashLen);
2518 }
2519 
2520 /* XXX Old template; want to expunge it eventually. */
2521 static DERTemplate SECAlgorithmIDTemplate[] = {
2522     { DER_SEQUENCE,
2523       0, NULL, sizeof(SECAlgorithmID) },
2524     { DER_OBJECT_ID,
2525       offsetof(SECAlgorithmID, algorithm) },
2526     { DER_OPTIONAL | DER_ANY,
2527       offsetof(SECAlgorithmID, parameters) },
2528     { 0 }
2529 };
2530 
2531 /*
2532  * XXX OLD Template.  Once all uses have been switched over to new one,
2533  * remove this.
2534  */
2535 static DERTemplate SGNDigestInfoTemplate[] = {
2536     { DER_SEQUENCE,
2537       0, NULL, sizeof(SGNDigestInfo) },
2538     { DER_INLINE,
2539       offsetof(SGNDigestInfo, digestAlgorithm),
2540       SECAlgorithmIDTemplate },
2541     { DER_OCTET_STRING,
2542       offsetof(SGNDigestInfo, digest) },
2543     { 0 }
2544 };
2545 
2546 /*
2547  * encode RSA PKCS #1 Signature data before signing...
2548  */
2549 SECStatus
RSA_HashSign(SECOidTag hashOid,NSSLOWKEYPrivateKey * key,unsigned char * sig,unsigned int * sigLen,unsigned int maxLen,const unsigned char * hash,unsigned int hashLen)2550 RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
2551              unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
2552              const unsigned char *hash, unsigned int hashLen)
2553 {
2554     SECStatus rv = SECFailure;
2555     SECItem digder;
2556     PLArenaPool *arena = NULL;
2557     SGNDigestInfo *di = NULL;
2558 
2559     digder.data = NULL;
2560 
2561     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2562     if (!arena) {
2563         goto loser;
2564     }
2565 
2566     /* Construct digest info */
2567     di = SGN_CreateDigestInfo(hashOid, hash, hashLen);
2568     if (!di) {
2569         goto loser;
2570     }
2571 
2572     /* Der encode the digest as a DigestInfo */
2573     rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
2574     if (rv != SECSuccess) {
2575         goto loser;
2576     }
2577 
2578     /*
2579     ** Encrypt signature after constructing appropriate PKCS#1 signature
2580     ** block
2581     */
2582     rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data,
2583                   digder.len);
2584     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2585         sftk_fatalError = PR_TRUE;
2586     }
2587 
2588 loser:
2589     SGN_DestroyDigestInfo(di);
2590     if (arena != NULL) {
2591         PORT_FreeArena(arena, PR_TRUE);
2592     }
2593     return rv;
2594 }
2595 
2596 static SECStatus
sftk_RSASign(NSSLOWKEYPrivateKey * key,unsigned char * output,unsigned int * outputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)2597 sftk_RSASign(NSSLOWKEYPrivateKey *key, unsigned char *output,
2598              unsigned int *outputLen, unsigned int maxOutputLen,
2599              const unsigned char *input, unsigned int inputLen)
2600 {
2601     SECStatus rv = SECFailure;
2602 
2603     PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2604     if (key->keyType != NSSLOWKEYRSAKey) {
2605         PORT_SetError(SEC_ERROR_INVALID_KEY);
2606         return SECFailure;
2607     }
2608 
2609     rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input,
2610                   inputLen);
2611     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2612         sftk_fatalError = PR_TRUE;
2613     }
2614     return rv;
2615 }
2616 
2617 static SECStatus
sftk_RSASignRaw(NSSLOWKEYPrivateKey * key,unsigned char * output,unsigned int * outputLen,unsigned int maxOutputLen,const unsigned char * input,unsigned int inputLen)2618 sftk_RSASignRaw(NSSLOWKEYPrivateKey *key, unsigned char *output,
2619                 unsigned int *outputLen, unsigned int maxOutputLen,
2620                 const unsigned char *input, unsigned int inputLen)
2621 {
2622     SECStatus rv = SECFailure;
2623 
2624     PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2625     if (key->keyType != NSSLOWKEYRSAKey) {
2626         PORT_SetError(SEC_ERROR_INVALID_KEY);
2627         return SECFailure;
2628     }
2629 
2630     rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input,
2631                      inputLen);
2632     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2633         sftk_fatalError = PR_TRUE;
2634     }
2635     return rv;
2636 }
2637 
2638 static SECStatus
sftk_RSASignPSS(SFTKPSSSignInfo * info,unsigned char * sig,unsigned int * sigLen,unsigned int maxLen,const unsigned char * hash,unsigned int hashLen)2639 sftk_RSASignPSS(SFTKPSSSignInfo *info, unsigned char *sig,
2640                 unsigned int *sigLen, unsigned int maxLen,
2641                 const unsigned char *hash, unsigned int hashLen)
2642 {
2643     SECStatus rv = SECFailure;
2644     HASH_HashType hashAlg;
2645     HASH_HashType maskHashAlg;
2646     CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
2647 
2648     PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2649     if (info->key->keyType != NSSLOWKEYRSAKey) {
2650         PORT_SetError(SEC_ERROR_INVALID_KEY);
2651         return SECFailure;
2652     }
2653 
2654     hashAlg = GetHashTypeFromMechanism(params->hashAlg);
2655     maskHashAlg = GetHashTypeFromMechanism(params->mgf);
2656 
2657     rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL,
2658                      params->sLen, sig, sigLen, maxLen, hash, hashLen);
2659     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2660         sftk_fatalError = PR_TRUE;
2661     }
2662     return rv;
2663 }
2664 
2665 static SECStatus
nsc_DSA_Verify_Stub(void * ctx,void * sigBuf,unsigned int sigLen,void * dataBuf,unsigned int dataLen)2666 nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen,
2667                     void *dataBuf, unsigned int dataLen)
2668 {
2669     SECItem signature, digest;
2670     NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
2671 
2672     signature.data = (unsigned char *)sigBuf;
2673     signature.len = sigLen;
2674     digest.data = (unsigned char *)dataBuf;
2675     digest.len = dataLen;
2676     return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest);
2677 }
2678 
2679 static SECStatus
nsc_DSA_Sign_Stub(void * ctx,void * sigBuf,unsigned int * sigLen,unsigned int maxSigLen,void * dataBuf,unsigned int dataLen)2680 nsc_DSA_Sign_Stub(void *ctx, void *sigBuf,
2681                   unsigned int *sigLen, unsigned int maxSigLen,
2682                   void *dataBuf, unsigned int dataLen)
2683 {
2684     SECItem signature, digest;
2685     SECStatus rv;
2686     NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
2687 
2688     signature.data = (unsigned char *)sigBuf;
2689     signature.len = maxSigLen;
2690     digest.data = (unsigned char *)dataBuf;
2691     digest.len = dataLen;
2692     rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest);
2693     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2694         sftk_fatalError = PR_TRUE;
2695     }
2696     *sigLen = signature.len;
2697     return rv;
2698 }
2699 
2700 static SECStatus
nsc_ECDSAVerifyStub(void * ctx,void * sigBuf,unsigned int sigLen,void * dataBuf,unsigned int dataLen)2701 nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen,
2702                     void *dataBuf, unsigned int dataLen)
2703 {
2704     SECItem signature, digest;
2705     NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
2706 
2707     signature.data = (unsigned char *)sigBuf;
2708     signature.len = sigLen;
2709     digest.data = (unsigned char *)dataBuf;
2710     digest.len = dataLen;
2711     return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest);
2712 }
2713 
2714 static SECStatus
nsc_ECDSASignStub(void * ctx,void * sigBuf,unsigned int * sigLen,unsigned int maxSigLen,void * dataBuf,unsigned int dataLen)2715 nsc_ECDSASignStub(void *ctx, void *sigBuf,
2716                   unsigned int *sigLen, unsigned int maxSigLen,
2717                   void *dataBuf, unsigned int dataLen)
2718 {
2719     SECItem signature, digest;
2720     SECStatus rv;
2721     NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
2722 
2723     signature.data = (unsigned char *)sigBuf;
2724     signature.len = maxSigLen;
2725     digest.data = (unsigned char *)dataBuf;
2726     digest.len = dataLen;
2727     rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest);
2728     if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2729         sftk_fatalError = PR_TRUE;
2730     }
2731     *sigLen = signature.len;
2732     return rv;
2733 }
2734 
2735 /* NSC_SignInit setups up the signing operations. There are three basic
2736  * types of signing:
2737  *      (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
2738  *  to data in a single Sign operation (which often looks a lot like an
2739  *  encrypt, with data coming in and data going out).
2740  *      (2) Hash based signing, where we continually hash the data, then apply
2741  *  some sort of signature to the end.
2742  *      (3) Block Encryption CBC MAC's, where the Data is encrypted with a key,
2743  *  and only the final block is part of the mac.
2744  *
2745  *  For case number 3, we initialize a context much like the Encryption Context
2746  *  (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and
2747  *  C_Final by the following method... if it's not multi-part, and it's doesn't
2748  *  have a hash context, it must be a block Encryption CBC MAC.
2749  *
2750  *  For case number 2, we initialize a hash structure, as well as make it
2751  *  multi-part. Updates are simple calls to the hash update function. Final
2752  *  calls the hashend, then passes the result to the 'update' function (which
2753  *  operates as a final signature function). In some hash based MAC'ing (as
2754  *  opposed to hash base signatures), the update function is can be simply a
2755  *  copy (as is the case with HMAC).
2756  */
2757 CK_RV
NSC_SignInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)2758 NSC_SignInit(CK_SESSION_HANDLE hSession,
2759              CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2760 {
2761     SFTKSession *session;
2762     SFTKObject *key;
2763     SFTKSessionContext *context;
2764     CK_KEY_TYPE key_type;
2765     CK_RV crv = CKR_OK;
2766     NSSLOWKEYPrivateKey *privKey;
2767     SFTKHashSignInfo *info = NULL;
2768     SFTKPSSSignInfo *pinfo = NULL;
2769 
2770     CHECK_FORK();
2771 
2772     /* Block Cipher MACing Algorithms use a different Context init method..*/
2773     crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN);
2774     if (crv != CKR_FUNCTION_NOT_SUPPORTED)
2775         return crv;
2776 
2777     /* we're not using a block cipher mac */
2778     session = sftk_SessionFromHandle(hSession);
2779     if (session == NULL)
2780         return CKR_SESSION_HANDLE_INVALID;
2781     crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_SIGN, &key,
2782                            hKey, &key_type, CKO_PRIVATE_KEY, CKA_SIGN);
2783     if (crv != CKR_OK) {
2784         sftk_FreeSession(session);
2785         return crv;
2786     }
2787 
2788     context->multi = PR_FALSE;
2789 
2790 #define INIT_RSA_SIGN_MECH(mmm)                         \
2791     case CKM_##mmm##_RSA_PKCS:                          \
2792         context->multi = PR_TRUE;                       \
2793         crv = sftk_doSub##mmm(context);                 \
2794         if (crv != CKR_OK)                              \
2795             break;                                      \
2796         context->update = (SFTKCipher)sftk_RSAHashSign; \
2797         info = PORT_New(SFTKHashSignInfo);              \
2798         if (info == NULL) {                             \
2799             crv = CKR_HOST_MEMORY;                      \
2800             break;                                      \
2801         }                                               \
2802         info->hashOid = SEC_OID_##mmm;                  \
2803         goto finish_rsa;
2804 
2805     switch (pMechanism->mechanism) {
2806         INIT_RSA_SIGN_MECH(MD5)
2807         INIT_RSA_SIGN_MECH(MD2)
2808         INIT_RSA_SIGN_MECH(SHA1)
2809         INIT_RSA_SIGN_MECH(SHA224)
2810         INIT_RSA_SIGN_MECH(SHA256)
2811         INIT_RSA_SIGN_MECH(SHA384)
2812         INIT_RSA_SIGN_MECH(SHA512)
2813 
2814         case CKM_RSA_PKCS:
2815             context->update = (SFTKCipher)sftk_RSASign;
2816             goto finish_rsa;
2817         case CKM_RSA_X_509:
2818             context->update = (SFTKCipher)sftk_RSASignRaw;
2819         finish_rsa:
2820             if (key_type != CKK_RSA) {
2821                 crv = CKR_KEY_TYPE_INCONSISTENT;
2822                 break;
2823             }
2824             context->rsa = PR_TRUE;
2825             privKey = sftk_GetPrivKey(key, CKK_RSA, &crv);
2826             if (privKey == NULL) {
2827                 crv = CKR_KEY_TYPE_INCONSISTENT;
2828                 break;
2829             }
2830             /* OK, info is allocated only if we're doing hash and sign mechanism.
2831              * It's necessary to be able to set the correct OID in the final
2832              * signature.
2833              */
2834             if (info) {
2835                 info->key = privKey;
2836                 context->cipherInfo = info;
2837                 context->destroy = (SFTKDestroy)sftk_Space;
2838             } else {
2839                 context->cipherInfo = privKey;
2840                 context->destroy = (SFTKDestroy)sftk_Null;
2841             }
2842             context->maxLen = nsslowkey_PrivateModulusLen(privKey);
2843             break;
2844 
2845 #define INIT_RSA_PSS_SIG_MECH(mmm)                                                            \
2846     case CKM_##mmm##_RSA_PKCS_PSS:                                                            \
2847         context->multi = PR_TRUE;                                                             \
2848         crv = sftk_doSub##mmm(context);                                                       \
2849         if (crv != CKR_OK)                                                                    \
2850             break;                                                                            \
2851         if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) {                   \
2852             crv = CKR_MECHANISM_PARAM_INVALID;                                                \
2853             break;                                                                            \
2854         }                                                                                     \
2855         if (((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)->hashAlg != CKM_##mmm) { \
2856             crv = CKR_MECHANISM_PARAM_INVALID;                                                \
2857             break;                                                                            \
2858         }                                                                                     \
2859         goto finish_rsa_pss;
2860             INIT_RSA_PSS_SIG_MECH(SHA1)
2861             INIT_RSA_PSS_SIG_MECH(SHA224)
2862             INIT_RSA_PSS_SIG_MECH(SHA256)
2863             INIT_RSA_PSS_SIG_MECH(SHA384)
2864             INIT_RSA_PSS_SIG_MECH(SHA512)
2865         case CKM_RSA_PKCS_PSS:
2866         finish_rsa_pss:
2867             if (key_type != CKK_RSA) {
2868                 crv = CKR_KEY_TYPE_INCONSISTENT;
2869                 break;
2870             }
2871             context->rsa = PR_TRUE;
2872             if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
2873                 !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) {
2874                 crv = CKR_MECHANISM_PARAM_INVALID;
2875                 break;
2876             }
2877             pinfo = PORT_New(SFTKPSSSignInfo);
2878             if (pinfo == NULL) {
2879                 crv = CKR_HOST_MEMORY;
2880                 break;
2881             }
2882             pinfo->size = sizeof(SFTKPSSSignInfo);
2883             pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
2884             pinfo->key = sftk_GetPrivKey(key, CKK_RSA, &crv);
2885             if (pinfo->key == NULL) {
2886                 crv = CKR_KEY_TYPE_INCONSISTENT;
2887                 break;
2888             }
2889             context->cipherInfo = pinfo;
2890             context->destroy = (SFTKDestroy)sftk_ZSpace;
2891             context->update = (SFTKCipher)sftk_RSASignPSS;
2892             context->maxLen = nsslowkey_PrivateModulusLen(pinfo->key);
2893             break;
2894 
2895 #define INIT_DSA_SIG_MECH(mmm)          \
2896     case CKM_DSA_##mmm:                 \
2897         context->multi = PR_TRUE;       \
2898         crv = sftk_doSub##mmm(context); \
2899         if (crv != CKR_OK)              \
2900             break;                      \
2901         goto finish_dsa;
2902             INIT_DSA_SIG_MECH(SHA1)
2903             INIT_DSA_SIG_MECH(SHA224)
2904             INIT_DSA_SIG_MECH(SHA256)
2905             INIT_DSA_SIG_MECH(SHA384)
2906             INIT_DSA_SIG_MECH(SHA512)
2907         case CKM_DSA:
2908         finish_dsa:
2909             if (key_type != CKK_DSA) {
2910                 crv = CKR_KEY_TYPE_INCONSISTENT;
2911                 break;
2912             }
2913             privKey = sftk_GetPrivKey(key, CKK_DSA, &crv);
2914             if (privKey == NULL) {
2915                 break;
2916             }
2917             context->cipherInfo = privKey;
2918             context->update = (SFTKCipher)nsc_DSA_Sign_Stub;
2919             context->destroy = (privKey == key->objectInfo) ? (SFTKDestroy)sftk_Null : (SFTKDestroy)sftk_FreePrivKey;
2920             context->maxLen = DSA_MAX_SIGNATURE_LEN;
2921 
2922             break;
2923 
2924 #define INIT_ECDSA_SIG_MECH(mmm)        \
2925     case CKM_ECDSA_##mmm:               \
2926         context->multi = PR_TRUE;       \
2927         crv = sftk_doSub##mmm(context); \
2928         if (crv != CKR_OK)              \
2929             break;                      \
2930         goto finish_ecdsa;
2931             INIT_ECDSA_SIG_MECH(SHA1)
2932             INIT_ECDSA_SIG_MECH(SHA224)
2933             INIT_ECDSA_SIG_MECH(SHA256)
2934             INIT_ECDSA_SIG_MECH(SHA384)
2935             INIT_ECDSA_SIG_MECH(SHA512)
2936         case CKM_ECDSA:
2937         finish_ecdsa:
2938             if (key_type != CKK_EC) {
2939                 crv = CKR_KEY_TYPE_INCONSISTENT;
2940                 break;
2941             }
2942             privKey = sftk_GetPrivKey(key, CKK_EC, &crv);
2943             if (privKey == NULL) {
2944                 crv = CKR_HOST_MEMORY;
2945                 break;
2946             }
2947             context->cipherInfo = privKey;
2948             context->update = (SFTKCipher)nsc_ECDSASignStub;
2949             context->destroy = (privKey == key->objectInfo) ? (SFTKDestroy)sftk_Null : (SFTKDestroy)sftk_FreePrivKey;
2950             context->maxLen = MAX_ECKEY_LEN * 2;
2951 
2952             break;
2953 
2954 #define INIT_HMAC_MECH(mmm)                                        \
2955     case CKM_##mmm##_HMAC_GENERAL:                                 \
2956         PORT_Assert(pMechanism->pParameter);                       \
2957         if (!pMechanism->pParameter) {                             \
2958             crv = CKR_MECHANISM_PARAM_INVALID;                     \
2959             break;                                                 \
2960         }                                                          \
2961         crv = sftk_doMACInit(pMechanism->mechanism, context, key,  \
2962                              *(CK_ULONG *)pMechanism->pParameter); \
2963         break;                                                     \
2964     case CKM_##mmm##_HMAC:                                         \
2965         crv = sftk_doMACInit(pMechanism->mechanism, context, key,  \
2966                              mmm##_LENGTH);                        \
2967         break;
2968 
2969             INIT_HMAC_MECH(MD2)
2970             INIT_HMAC_MECH(MD5)
2971             INIT_HMAC_MECH(SHA1)
2972             INIT_HMAC_MECH(SHA224)
2973             INIT_HMAC_MECH(SHA256)
2974             INIT_HMAC_MECH(SHA384)
2975             INIT_HMAC_MECH(SHA512)
2976 
2977         case CKM_AES_CMAC_GENERAL:
2978             PORT_Assert(pMechanism->pParameter);
2979             if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) {
2980                 crv = CKR_MECHANISM_PARAM_INVALID;
2981                 break;
2982             }
2983             crv = sftk_doMACInit(pMechanism->mechanism, context, key, *(CK_ULONG *)pMechanism->pParameter);
2984             break;
2985         case CKM_AES_CMAC:
2986             crv = sftk_doMACInit(pMechanism->mechanism, context, key, AES_BLOCK_SIZE);
2987             break;
2988         case CKM_SSL3_MD5_MAC:
2989             PORT_Assert(pMechanism->pParameter);
2990             if (!pMechanism->pParameter) {
2991                 crv = CKR_MECHANISM_PARAM_INVALID;
2992                 break;
2993             }
2994             crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key,
2995                                     *(CK_ULONG *)pMechanism->pParameter);
2996             break;
2997         case CKM_SSL3_SHA1_MAC:
2998             PORT_Assert(pMechanism->pParameter);
2999             if (!pMechanism->pParameter) {
3000                 crv = CKR_MECHANISM_PARAM_INVALID;
3001                 break;
3002             }
3003             crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key,
3004                                     *(CK_ULONG *)pMechanism->pParameter);
3005             break;
3006         case CKM_TLS_PRF_GENERAL:
3007             crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0);
3008             break;
3009         case CKM_TLS_MAC: {
3010             CK_TLS_MAC_PARAMS *tls12_mac_params;
3011             HASH_HashType tlsPrfHash;
3012             const char *label;
3013 
3014             if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) {
3015                 crv = CKR_MECHANISM_PARAM_INVALID;
3016                 break;
3017             }
3018             tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter;
3019             if (tls12_mac_params->prfHashMechanism == CKM_TLS_PRF) {
3020                 /* The TLS 1.0 and 1.1 PRF */
3021                 tlsPrfHash = HASH_AlgNULL;
3022                 if (tls12_mac_params->ulMacLength != 12) {
3023                     crv = CKR_MECHANISM_PARAM_INVALID;
3024                     break;
3025                 }
3026             } else {
3027                 /* The hash function for the TLS 1.2 PRF */
3028                 tlsPrfHash =
3029                     GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism);
3030                 if (tlsPrfHash == HASH_AlgNULL ||
3031                     tls12_mac_params->ulMacLength < 12) {
3032                     crv = CKR_MECHANISM_PARAM_INVALID;
3033                     break;
3034                 }
3035             }
3036             if (tls12_mac_params->ulServerOrClient == 1) {
3037                 label = "server finished";
3038             } else if (tls12_mac_params->ulServerOrClient == 2) {
3039                 label = "client finished";
3040             } else {
3041                 crv = CKR_MECHANISM_PARAM_INVALID;
3042                 break;
3043             }
3044             crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash,
3045                                   tls12_mac_params->ulMacLength);
3046             if (crv == CKR_OK) {
3047                 context->hashUpdate(context->hashInfo, label, 15);
3048             }
3049             break;
3050         }
3051         case CKM_NSS_TLS_PRF_GENERAL_SHA256:
3052             crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0);
3053             break;
3054 
3055         case CKM_NSS_HMAC_CONSTANT_TIME: {
3056             sftk_MACConstantTimeCtx *ctx =
3057                 sftk_HMACConstantTime_New(pMechanism, key);
3058             CK_ULONG *intpointer;
3059 
3060             if (ctx == NULL) {
3061                 crv = CKR_ARGUMENTS_BAD;
3062                 break;
3063             }
3064             intpointer = PORT_New(CK_ULONG);
3065             if (intpointer == NULL) {
3066                 PORT_Free(ctx);
3067                 crv = CKR_HOST_MEMORY;
3068                 break;
3069             }
3070             *intpointer = ctx->hash->length;
3071 
3072             context->cipherInfo = intpointer;
3073             context->hashInfo = ctx;
3074             context->currentMech = pMechanism->mechanism;
3075             context->hashUpdate = sftk_HMACConstantTime_Update;
3076             context->hashdestroy = sftk_MACConstantTime_DestroyContext;
3077             context->end = sftk_MACConstantTime_EndHash;
3078             context->update = (SFTKCipher)sftk_SignCopy;
3079             context->destroy = sftk_Space;
3080             context->maxLen = 64;
3081             context->multi = PR_TRUE;
3082             break;
3083         }
3084 
3085         case CKM_NSS_SSL3_MAC_CONSTANT_TIME: {
3086             sftk_MACConstantTimeCtx *ctx =
3087                 sftk_SSLv3MACConstantTime_New(pMechanism, key);
3088             CK_ULONG *intpointer;
3089 
3090             if (ctx == NULL) {
3091                 crv = CKR_ARGUMENTS_BAD;
3092                 break;
3093             }
3094             intpointer = PORT_New(CK_ULONG);
3095             if (intpointer == NULL) {
3096                 PORT_Free(ctx);
3097                 crv = CKR_HOST_MEMORY;
3098                 break;
3099             }
3100             *intpointer = ctx->hash->length;
3101 
3102             context->cipherInfo = intpointer;
3103             context->hashInfo = ctx;
3104             context->currentMech = pMechanism->mechanism;
3105             context->hashUpdate = sftk_SSLv3MACConstantTime_Update;
3106             context->hashdestroy = sftk_MACConstantTime_DestroyContext;
3107             context->end = sftk_MACConstantTime_EndHash;
3108             context->update = (SFTKCipher)sftk_SignCopy;
3109             context->destroy = sftk_Space;
3110             context->maxLen = 64;
3111             context->multi = PR_TRUE;
3112             break;
3113         }
3114 
3115         default:
3116             crv = CKR_MECHANISM_INVALID;
3117             break;
3118     }
3119 
3120     if (crv != CKR_OK) {
3121         if (info)
3122             PORT_Free(info);
3123         if (pinfo)
3124             PORT_ZFree(pinfo, pinfo->size);
3125         sftk_FreeContext(context);
3126         sftk_FreeSession(session);
3127         return crv;
3128     }
3129     sftk_SetContextByType(session, SFTK_SIGN, context);
3130     sftk_FreeSession(session);
3131     return CKR_OK;
3132 }
3133 
3134 /** MAC one block of data by block cipher
3135  */
3136 static CK_RV
sftk_MACBlock(SFTKSessionContext * ctx,void * blk)3137 sftk_MACBlock(SFTKSessionContext *ctx, void *blk)
3138 {
3139     unsigned int outlen;
3140     return (SECSuccess == (ctx->update)(ctx->cipherInfo, ctx->macBuf, &outlen,
3141                                         SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize))
3142                ? CKR_OK
3143                : sftk_MapCryptError(PORT_GetError());
3144 }
3145 
3146 /** MAC last (incomplete) block of data by block cipher
3147  *
3148  *  Call once, then terminate MACing operation.
3149  */
3150 static CK_RV
sftk_MACFinal(SFTKSessionContext * ctx)3151 sftk_MACFinal(SFTKSessionContext *ctx)
3152 {
3153     unsigned int padLen = ctx->padDataLength;
3154     /* pad and proceed the residual */
3155     if (ctx->isXCBC) {
3156         CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize,
3157                                       ctx->k2, ctx->k3);
3158         if (crv != CKR_OK)
3159             return crv;
3160         return sftk_MACBlock(ctx, ctx->padBuf);
3161     }
3162     if (padLen) {
3163         /* shd clr ctx->padLen to make sftk_MACFinal idempotent */
3164         PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen);
3165         return sftk_MACBlock(ctx, ctx->padBuf);
3166     } else
3167         return CKR_OK;
3168 }
3169 
3170 /** The common implementation for {Sign,Verify}Update. (S/V only vary in their
3171  * setup and final operations).
3172  *
3173  * A call which results in an error terminates the operation [PKCS#11,v2.11]
3174  */
3175 static CK_RV
sftk_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen,SFTKContextType type)3176 sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3177                CK_ULONG ulPartLen, SFTKContextType type)
3178 {
3179     SFTKSession *session;
3180     SFTKSessionContext *context;
3181     CK_RV crv;
3182 
3183     /* make sure we're legal */
3184     crv = sftk_GetContext(hSession, &context, type, PR_TRUE, &session);
3185     if (crv != CKR_OK)
3186         return crv;
3187 
3188     if (context->hashInfo) {
3189         (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen);
3190     } else {
3191         /* must be block cipher MACing */
3192 
3193         unsigned int blkSize = context->blockSize;
3194         unsigned char *residual = /* free room in context->padBuf */
3195             context->padBuf + context->padDataLength;
3196         unsigned int minInput = /* min input for MACing at least one block */
3197             blkSize - context->padDataLength;
3198 
3199         /* not enough data even for one block */
3200         if (ulPartLen <= minInput) {
3201             PORT_Memcpy(residual, pPart, ulPartLen);
3202             context->padDataLength += ulPartLen;
3203             goto cleanup;
3204         }
3205         /* MACing residual */
3206         if (context->padDataLength) {
3207             PORT_Memcpy(residual, pPart, minInput);
3208             ulPartLen -= minInput;
3209             pPart += minInput;
3210             if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf)))
3211                 goto terminate;
3212         }
3213         /* MACing full blocks */
3214         while (ulPartLen > blkSize) {
3215             if (CKR_OK != (crv = sftk_MACBlock(context, pPart)))
3216                 goto terminate;
3217             ulPartLen -= blkSize;
3218             pPart += blkSize;
3219         }
3220         /* save the residual */
3221         if ((context->padDataLength = ulPartLen))
3222             PORT_Memcpy(context->padBuf, pPart, ulPartLen);
3223     } /* blk cipher MACing */
3224 
3225     goto cleanup;
3226 
3227 terminate:
3228     sftk_TerminateOp(session, type, context);
3229 cleanup:
3230     sftk_FreeSession(session);
3231     return crv;
3232 }
3233 
3234 /* NSC_SignUpdate continues a multiple-part signature operation,
3235  * where the signature is (will be) an appendix to the data,
3236  * and plaintext cannot be recovered from the signature
3237  *
3238  * A call which results in an error terminates the operation [PKCS#11,v2.11]
3239  */
3240 CK_RV
NSC_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)3241 NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3242                CK_ULONG ulPartLen)
3243 {
3244     CHECK_FORK();
3245     return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN);
3246 }
3247 
3248 struct SFTK_SESSION_FLAGS {
3249     CK_FLAGS flag;
3250     SFTKContextType type;
3251 };
3252 
3253 const static struct SFTK_SESSION_FLAGS sftk_session_flags[] = {
3254     { CKF_ENCRYPT, SFTK_ENCRYPT },
3255     { CKF_DECRYPT, SFTK_DECRYPT },
3256     { CKF_DIGEST, SFTK_HASH },
3257     { CKF_SIGN, SFTK_SIGN },
3258     { CKF_SIGN_RECOVER, SFTK_SIGN_RECOVER },
3259     { CKF_VERIFY, SFTK_VERIFY },
3260     { CKF_VERIFY_RECOVER, SFTK_VERIFY_RECOVER },
3261     { CKF_MESSAGE_ENCRYPT, SFTK_MESSAGE_ENCRYPT },
3262     { CKF_MESSAGE_DECRYPT, SFTK_MESSAGE_DECRYPT },
3263     { CKF_MESSAGE_SIGN, SFTK_MESSAGE_SIGN },
3264     { CKF_MESSAGE_VERIFY, SFTK_MESSAGE_VERIFY },
3265 };
3266 const static int sftk_flag_count = PR_ARRAY_SIZE(sftk_session_flags);
3267 
3268 /*
3269  * Cancel one or more operations running on the existing session.
3270  */
3271 CK_RV
NSC_SessionCancel(CK_SESSION_HANDLE hSession,CK_FLAGS flags)3272 NSC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags)
3273 {
3274     SFTKSession *session;
3275     SFTKSessionContext *context;
3276     CK_RV gcrv = CKR_OK;
3277     CK_RV crv;
3278     int i;
3279 
3280     for (i = 0; i < sftk_flag_count; i++) {
3281         if (flags & sftk_session_flags[i].flag) {
3282             flags &= ~sftk_session_flags[i].flag;
3283             crv = sftk_GetContext(hSession, &context, sftk_session_flags[i].type, PR_TRUE, &session);
3284             if (crv != CKR_OK) {
3285                 gcrv = CKR_OPERATION_CANCEL_FAILED;
3286                 continue;
3287             }
3288             sftk_TerminateOp(session, sftk_session_flags[i].type, context);
3289         }
3290     }
3291     if (flags & CKF_FIND_OBJECTS) {
3292         flags &= ~CKF_FIND_OBJECTS;
3293         crv = NSC_FindObjectsFinal(hSession);
3294         if (crv != CKR_OK) {
3295             gcrv = CKR_OPERATION_CANCEL_FAILED;
3296         }
3297     }
3298     if (flags) {
3299         gcrv = CKR_OPERATION_CANCEL_FAILED;
3300     }
3301     return gcrv;
3302 }
3303 
3304 /* NSC_SignFinal finishes a multiple-part signature operation,
3305  * returning the signature. */
3306 CK_RV
NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)3307 NSC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
3308               CK_ULONG_PTR pulSignatureLen)
3309 {
3310     SFTKSession *session;
3311     SFTKSessionContext *context;
3312     unsigned int outlen;
3313     unsigned int maxoutlen = *pulSignatureLen;
3314     CK_RV crv;
3315 
3316     CHECK_FORK();
3317 
3318     /* make sure we're legal */
3319     crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_TRUE, &session);
3320     if (crv != CKR_OK)
3321         return crv;
3322 
3323     if (context->hashInfo) {
3324         unsigned int digestLen;
3325         unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
3326 
3327         if (!pSignature) {
3328             outlen = context->maxLen;
3329             goto finish;
3330         }
3331         (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
3332         if (SECSuccess != (context->update)(context->cipherInfo, pSignature,
3333                                             &outlen, maxoutlen, tmpbuf, digestLen))
3334             crv = sftk_MapCryptError(PORT_GetError());
3335         /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate.
3336          * Keeping "too small" CK_RV intact is a standard violation, but allows
3337          * application read EXACT signature length */
3338         PORT_Memset(tmpbuf, 0, sizeof tmpbuf);
3339     } else {
3340         /* must be block cipher MACing */
3341         outlen = context->macSize;
3342         /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/
3343         if (!pSignature || maxoutlen < outlen) {
3344             if (pSignature)
3345                 crv = CKR_BUFFER_TOO_SMALL;
3346             goto finish;
3347         }
3348         if (CKR_OK == (crv = sftk_MACFinal(context)))
3349             PORT_Memcpy(pSignature, context->macBuf, outlen);
3350     }
3351 
3352     sftk_TerminateOp(session, SFTK_SIGN, context);
3353 finish:
3354     *pulSignatureLen = outlen;
3355     sftk_FreeSession(session);
3356     return crv;
3357 }
3358 
3359 /* NSC_Sign signs (encrypts with private key) data in a single part,
3360  * where the signature is (will be) an appendix to the data,
3361  * and plaintext cannot be recovered from the signature */
3362 CK_RV
NSC_Sign(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)3363 NSC_Sign(CK_SESSION_HANDLE hSession,
3364          CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
3365          CK_ULONG_PTR pulSignatureLen)
3366 {
3367     SFTKSession *session;
3368     SFTKSessionContext *context;
3369     CK_RV crv;
3370 
3371     CHECK_FORK();
3372 
3373     /* make sure we're legal */
3374     crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_FALSE, &session);
3375     if (crv != CKR_OK)
3376         return crv;
3377 
3378     if (!pSignature) {
3379         /* see also how C_SignUpdate implements this */
3380         *pulSignatureLen = (!context->multi || context->hashInfo)
3381                                ? context->maxLen
3382                                : context->macSize; /* must be block cipher MACing */
3383         goto finish;
3384     }
3385 
3386     /* multi part Signing are completely implemented by SignUpdate and
3387      * sign Final */
3388     if (context->multi) {
3389         /* SignFinal can't follow failed SignUpdate */
3390         if (CKR_OK == (crv = NSC_SignUpdate(hSession, pData, ulDataLen)))
3391             crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen);
3392     } else {
3393         /* single-part PKC signature (e.g. CKM_ECDSA) */
3394         unsigned int outlen;
3395         unsigned int maxoutlen = *pulSignatureLen;
3396         if (SECSuccess != (*context->update)(context->cipherInfo, pSignature,
3397                                              &outlen, maxoutlen, pData, ulDataLen))
3398             crv = sftk_MapCryptError(PORT_GetError());
3399         *pulSignatureLen = (CK_ULONG)outlen;
3400         /*  "too small" here is certainly continuable */
3401         if (crv != CKR_BUFFER_TOO_SMALL)
3402             sftk_TerminateOp(session, SFTK_SIGN, context);
3403     } /* single-part */
3404 
3405 finish:
3406     sftk_FreeSession(session);
3407     return crv;
3408 }
3409 
3410 /*
3411  ************** Crypto Functions:     Sign Recover  ************************
3412  */
3413 /* NSC_SignRecoverInit initializes a signature operation,
3414  * where the (digest) data can be recovered from the signature.
3415  * E.g. encryption with the user's private key */
3416 CK_RV
NSC_SignRecoverInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)3417 NSC_SignRecoverInit(CK_SESSION_HANDLE hSession,
3418                     CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3419 {
3420     CHECK_FORK();
3421 
3422     switch (pMechanism->mechanism) {
3423         case CKM_RSA_PKCS:
3424         case CKM_RSA_X_509:
3425             return NSC_SignInit(hSession, pMechanism, hKey);
3426         default:
3427             break;
3428     }
3429     return CKR_MECHANISM_INVALID;
3430 }
3431 
3432 /* NSC_SignRecover signs data in a single operation
3433  * where the (digest) data can be recovered from the signature.
3434  * E.g. encryption with the user's private key */
3435 CK_RV
NSC_SignRecover(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)3436 NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
3437                 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
3438 {
3439     CHECK_FORK();
3440 
3441     return NSC_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
3442 }
3443 
3444 /*
3445  ************** Crypto Functions:     verify  ************************
3446  */
3447 
3448 /* Handle RSA Signature formatting */
3449 static SECStatus
sftk_hashCheckSign(SFTKHashVerifyInfo * info,const unsigned char * sig,unsigned int sigLen,const unsigned char * digest,unsigned int digestLen)3450 sftk_hashCheckSign(SFTKHashVerifyInfo *info, const unsigned char *sig,
3451                    unsigned int sigLen, const unsigned char *digest,
3452                    unsigned int digestLen)
3453 {
3454     PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
3455     if (info->key->keyType != NSSLOWKEYRSAKey) {
3456         PORT_SetError(SEC_ERROR_INVALID_KEY);
3457         return SECFailure;
3458     }
3459 
3460     return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest,
3461                              digestLen);
3462 }
3463 
3464 SECStatus
RSA_HashCheckSign(SECOidTag digestOid,NSSLOWKEYPublicKey * key,const unsigned char * sig,unsigned int sigLen,const unsigned char * digestData,unsigned int digestLen)3465 RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key,
3466                   const unsigned char *sig, unsigned int sigLen,
3467                   const unsigned char *digestData, unsigned int digestLen)
3468 {
3469     unsigned char *pkcs1DigestInfoData;
3470     SECItem pkcs1DigestInfo;
3471     SECItem digest;
3472     unsigned int bufferSize;
3473     SECStatus rv;
3474 
3475     /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */
3476     bufferSize = key->u.rsa.modulus.len;
3477     pkcs1DigestInfoData = PORT_ZAlloc(bufferSize);
3478     if (!pkcs1DigestInfoData) {
3479         PORT_SetError(SEC_ERROR_NO_MEMORY);
3480         return SECFailure;
3481     }
3482 
3483     pkcs1DigestInfo.data = pkcs1DigestInfoData;
3484     pkcs1DigestInfo.len = bufferSize;
3485 
3486     /* decrypt the block */
3487     rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data,
3488                               &pkcs1DigestInfo.len, pkcs1DigestInfo.len,
3489                               sig, sigLen);
3490     if (rv != SECSuccess) {
3491         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
3492     } else {
3493         digest.data = (PRUint8 *)digestData;
3494         digest.len = digestLen;
3495         rv = _SGN_VerifyPKCS1DigestInfo(
3496             digestOid, &digest, &pkcs1DigestInfo,
3497             PR_FALSE /*XXX: unsafeAllowMissingParameters*/);
3498     }
3499 
3500     PORT_ZFree(pkcs1DigestInfoData, bufferSize);
3501     return rv;
3502 }
3503 
3504 static SECStatus
sftk_RSACheckSign(NSSLOWKEYPublicKey * key,const unsigned char * sig,unsigned int sigLen,const unsigned char * digest,unsigned int digestLen)3505 sftk_RSACheckSign(NSSLOWKEYPublicKey *key, const unsigned char *sig,
3506                   unsigned int sigLen, const unsigned char *digest,
3507                   unsigned int digestLen)
3508 {
3509     PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3510     if (key->keyType != NSSLOWKEYRSAKey) {
3511         PORT_SetError(SEC_ERROR_INVALID_KEY);
3512         return SECFailure;
3513     }
3514 
3515     return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen);
3516 }
3517 
3518 static SECStatus
sftk_RSACheckSignRaw(NSSLOWKEYPublicKey * key,const unsigned char * sig,unsigned int sigLen,const unsigned char * digest,unsigned int digestLen)3519 sftk_RSACheckSignRaw(NSSLOWKEYPublicKey *key, const unsigned char *sig,
3520                      unsigned int sigLen, const unsigned char *digest,
3521                      unsigned int digestLen)
3522 {
3523     PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3524     if (key->keyType != NSSLOWKEYRSAKey) {
3525         PORT_SetError(SEC_ERROR_INVALID_KEY);
3526         return SECFailure;
3527     }
3528 
3529     return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen);
3530 }
3531 
3532 static SECStatus
sftk_RSACheckSignPSS(SFTKPSSVerifyInfo * info,const unsigned char * sig,unsigned int sigLen,const unsigned char * digest,unsigned int digestLen)3533 sftk_RSACheckSignPSS(SFTKPSSVerifyInfo *info, const unsigned char *sig,
3534                      unsigned int sigLen, const unsigned char *digest,
3535                      unsigned int digestLen)
3536 {
3537     HASH_HashType hashAlg;
3538     HASH_HashType maskHashAlg;
3539     CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
3540 
3541     PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
3542     if (info->key->keyType != NSSLOWKEYRSAKey) {
3543         PORT_SetError(SEC_ERROR_INVALID_KEY);
3544         return SECFailure;
3545     }
3546 
3547     hashAlg = GetHashTypeFromMechanism(params->hashAlg);
3548     maskHashAlg = GetHashTypeFromMechanism(params->mgf);
3549 
3550     return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg,
3551                             params->sLen, sig, sigLen, digest, digestLen);
3552 }
3553 
3554 /* NSC_VerifyInit initializes a verification operation,
3555  * where the signature is an appendix to the data,
3556  * and plaintext cannot be recovered from the signature (e.g. DSA) */
3557 CK_RV
NSC_VerifyInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)3558 NSC_VerifyInit(CK_SESSION_HANDLE hSession,
3559                CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3560 {
3561     SFTKSession *session;
3562     SFTKObject *key;
3563     SFTKSessionContext *context;
3564     CK_KEY_TYPE key_type;
3565     CK_RV crv = CKR_OK;
3566     NSSLOWKEYPublicKey *pubKey;
3567     SFTKHashVerifyInfo *info = NULL;
3568     SFTKPSSVerifyInfo *pinfo = NULL;
3569 
3570     CHECK_FORK();
3571 
3572     /* Block Cipher MACing Algorithms use a different Context init method..*/
3573     crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY);
3574     if (crv != CKR_FUNCTION_NOT_SUPPORTED)
3575         return crv;
3576 
3577     session = sftk_SessionFromHandle(hSession);
3578     if (session == NULL)
3579         return CKR_SESSION_HANDLE_INVALID;
3580     crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY, &key,
3581                            hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY);
3582     if (crv != CKR_OK) {
3583         sftk_FreeSession(session);
3584         return crv;
3585     }
3586 
3587     context->multi = PR_FALSE;
3588 
3589 #define INIT_RSA_VFY_MECH(mmm)                            \
3590     case CKM_##mmm##_RSA_PKCS:                            \
3591         context->multi = PR_TRUE;                         \
3592         crv = sftk_doSub##mmm(context);                   \
3593         if (crv != CKR_OK)                                \
3594             break;                                        \
3595         context->verify = (SFTKVerify)sftk_hashCheckSign; \
3596         info = PORT_New(SFTKHashVerifyInfo);              \
3597         if (info == NULL) {                               \
3598             crv = CKR_HOST_MEMORY;                        \
3599             break;                                        \
3600         }                                                 \
3601         info->hashOid = SEC_OID_##mmm;                    \
3602         goto finish_rsa;
3603 
3604     switch (pMechanism->mechanism) {
3605         INIT_RSA_VFY_MECH(MD5)
3606         INIT_RSA_VFY_MECH(MD2)
3607         INIT_RSA_VFY_MECH(SHA1)
3608         INIT_RSA_VFY_MECH(SHA224)
3609         INIT_RSA_VFY_MECH(SHA256)
3610         INIT_RSA_VFY_MECH(SHA384)
3611         INIT_RSA_VFY_MECH(SHA512)
3612 
3613         case CKM_RSA_PKCS:
3614             context->verify = (SFTKVerify)sftk_RSACheckSign;
3615             goto finish_rsa;
3616         case CKM_RSA_X_509:
3617             context->verify = (SFTKVerify)sftk_RSACheckSignRaw;
3618         finish_rsa:
3619             if (key_type != CKK_RSA) {
3620                 crv = CKR_KEY_TYPE_INCONSISTENT;
3621                 break;
3622             }
3623             context->rsa = PR_TRUE;
3624             pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
3625             if (pubKey == NULL) {
3626                 crv = CKR_KEY_TYPE_INCONSISTENT;
3627                 break;
3628             }
3629             if (info) {
3630                 info->key = pubKey;
3631                 context->cipherInfo = info;
3632                 context->destroy = sftk_Space;
3633             } else {
3634                 context->cipherInfo = pubKey;
3635                 context->destroy = sftk_Null;
3636             }
3637             break;
3638 
3639             INIT_RSA_PSS_SIG_MECH(SHA1)
3640             INIT_RSA_PSS_SIG_MECH(SHA224)
3641             INIT_RSA_PSS_SIG_MECH(SHA256)
3642             INIT_RSA_PSS_SIG_MECH(SHA384)
3643             INIT_RSA_PSS_SIG_MECH(SHA512)
3644         case CKM_RSA_PKCS_PSS:
3645         finish_rsa_pss:
3646             if (key_type != CKK_RSA) {
3647                 crv = CKR_KEY_TYPE_INCONSISTENT;
3648                 break;
3649             }
3650             context->rsa = PR_TRUE;
3651             if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
3652                 !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) {
3653                 crv = CKR_MECHANISM_PARAM_INVALID;
3654                 break;
3655             }
3656             pinfo = PORT_New(SFTKPSSVerifyInfo);
3657             if (pinfo == NULL) {
3658                 crv = CKR_HOST_MEMORY;
3659                 break;
3660             }
3661             pinfo->size = sizeof(SFTKPSSVerifyInfo);
3662             pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
3663             pinfo->key = sftk_GetPubKey(key, CKK_RSA, &crv);
3664             if (pinfo->key == NULL) {
3665                 crv = CKR_KEY_TYPE_INCONSISTENT;
3666                 break;
3667             }
3668             context->cipherInfo = pinfo;
3669             context->destroy = (SFTKDestroy)sftk_ZSpace;
3670             context->verify = (SFTKVerify)sftk_RSACheckSignPSS;
3671             break;
3672 
3673             INIT_DSA_SIG_MECH(SHA1)
3674             INIT_DSA_SIG_MECH(SHA224)
3675             INIT_DSA_SIG_MECH(SHA256)
3676             INIT_DSA_SIG_MECH(SHA384)
3677             INIT_DSA_SIG_MECH(SHA512)
3678         case CKM_DSA:
3679         finish_dsa:
3680             if (key_type != CKK_DSA) {
3681                 crv = CKR_KEY_TYPE_INCONSISTENT;
3682                 break;
3683             }
3684             pubKey = sftk_GetPubKey(key, CKK_DSA, &crv);
3685             if (pubKey == NULL) {
3686                 break;
3687             }
3688             context->cipherInfo = pubKey;
3689             context->verify = (SFTKVerify)nsc_DSA_Verify_Stub;
3690             context->destroy = sftk_Null;
3691             break;
3692 
3693             INIT_ECDSA_SIG_MECH(SHA1)
3694             INIT_ECDSA_SIG_MECH(SHA224)
3695             INIT_ECDSA_SIG_MECH(SHA256)
3696             INIT_ECDSA_SIG_MECH(SHA384)
3697             INIT_ECDSA_SIG_MECH(SHA512)
3698         case CKM_ECDSA:
3699         finish_ecdsa:
3700             if (key_type != CKK_EC) {
3701                 crv = CKR_KEY_TYPE_INCONSISTENT;
3702                 break;
3703             }
3704             pubKey = sftk_GetPubKey(key, CKK_EC, &crv);
3705             if (pubKey == NULL) {
3706                 crv = CKR_HOST_MEMORY;
3707                 break;
3708             }
3709             context->cipherInfo = pubKey;
3710             context->verify = (SFTKVerify)nsc_ECDSAVerifyStub;
3711             context->destroy = sftk_Null;
3712             break;
3713 
3714             INIT_HMAC_MECH(MD2)
3715             INIT_HMAC_MECH(MD5)
3716             INIT_HMAC_MECH(SHA1)
3717             INIT_HMAC_MECH(SHA224)
3718             INIT_HMAC_MECH(SHA256)
3719             INIT_HMAC_MECH(SHA384)
3720             INIT_HMAC_MECH(SHA512)
3721 
3722         case CKM_SSL3_MD5_MAC:
3723             PORT_Assert(pMechanism->pParameter);
3724             if (!pMechanism->pParameter) {
3725                 crv = CKR_MECHANISM_PARAM_INVALID;
3726                 break;
3727             }
3728             crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key,
3729                                     *(CK_ULONG *)pMechanism->pParameter);
3730             break;
3731         case CKM_SSL3_SHA1_MAC:
3732             PORT_Assert(pMechanism->pParameter);
3733             if (!pMechanism->pParameter) {
3734                 crv = CKR_MECHANISM_PARAM_INVALID;
3735                 break;
3736             }
3737             crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key,
3738                                     *(CK_ULONG *)pMechanism->pParameter);
3739             break;
3740         case CKM_TLS_PRF_GENERAL:
3741             crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0);
3742             break;
3743         case CKM_NSS_TLS_PRF_GENERAL_SHA256:
3744             crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0);
3745             break;
3746 
3747         default:
3748             crv = CKR_MECHANISM_INVALID;
3749             break;
3750     }
3751 
3752     if (crv != CKR_OK) {
3753         if (info)
3754             PORT_Free(info);
3755         if (pinfo)
3756             PORT_ZFree(pinfo, pinfo->size);
3757         sftk_FreeContext(context);
3758         sftk_FreeSession(session);
3759         return crv;
3760     }
3761     sftk_SetContextByType(session, SFTK_VERIFY, context);
3762     sftk_FreeSession(session);
3763     return CKR_OK;
3764 }
3765 
3766 /* NSC_Verify verifies a signature in a single-part operation,
3767  * where the signature is an appendix to the data,
3768  * and plaintext cannot be recovered from the signature */
3769 CK_RV
NSC_Verify(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)3770 NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
3771            CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
3772 {
3773     SFTKSession *session;
3774     SFTKSessionContext *context;
3775     CK_RV crv;
3776 
3777     CHECK_FORK();
3778 
3779     /* make sure we're legal */
3780     crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session);
3781     if (crv != CKR_OK)
3782         return crv;
3783 
3784     /* multi part Verifying are completely implemented by VerifyUpdate and
3785      * VerifyFinal */
3786     if (context->multi) {
3787         /* VerifyFinal can't follow failed VerifyUpdate */
3788         if (CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen)))
3789             crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen);
3790     } else {
3791         if (SECSuccess != (*context->verify)(context->cipherInfo, pSignature,
3792                                              ulSignatureLen, pData, ulDataLen))
3793             crv = sftk_MapCryptError(PORT_GetError());
3794 
3795         sftk_TerminateOp(session, SFTK_VERIFY, context);
3796     }
3797     sftk_FreeSession(session);
3798     return crv;
3799 }
3800 
3801 /* NSC_VerifyUpdate continues a multiple-part verification operation,
3802  * where the signature is an appendix to the data,
3803  * and plaintext cannot be recovered from the signature
3804  *
3805  * A call which results in an error terminates the operation [PKCS#11,v2.11]
3806  */
3807 CK_RV
NSC_VerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)3808 NSC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3809                  CK_ULONG ulPartLen)
3810 {
3811     CHECK_FORK();
3812     return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY);
3813 }
3814 
3815 /* NSC_VerifyFinal finishes a multiple-part verification operation,
3816  * checking the signature. */
3817 CK_RV
NSC_VerifyFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)3818 NSC_VerifyFinal(CK_SESSION_HANDLE hSession,
3819                 CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
3820 {
3821     SFTKSession *session;
3822     SFTKSessionContext *context;
3823     CK_RV crv;
3824 
3825     CHECK_FORK();
3826 
3827     if (!pSignature)
3828         return CKR_ARGUMENTS_BAD;
3829 
3830     /* make sure we're legal */
3831     crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session);
3832     if (crv != CKR_OK)
3833         return crv;
3834 
3835     if (context->hashInfo) {
3836         unsigned int digestLen;
3837         unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
3838 
3839         (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
3840         if (SECSuccess != (context->verify)(context->cipherInfo, pSignature,
3841                                             ulSignatureLen, tmpbuf, digestLen))
3842             crv = sftk_MapCryptError(PORT_GetError());
3843         PORT_Memset(tmpbuf, 0, sizeof tmpbuf);
3844     } else if (ulSignatureLen != context->macSize) {
3845         /* must be block cipher MACing */
3846         crv = CKR_SIGNATURE_LEN_RANGE;
3847     } else if (CKR_OK == (crv = sftk_MACFinal(context))) {
3848         if (NSS_SecureMemcmp(pSignature, context->macBuf, ulSignatureLen))
3849             crv = CKR_SIGNATURE_INVALID;
3850     }
3851 
3852     sftk_TerminateOp(session, SFTK_VERIFY, context);
3853     sftk_FreeSession(session);
3854     return crv;
3855 }
3856 
3857 /*
3858  ************** Crypto Functions:     Verify  Recover ************************
3859  */
3860 static SECStatus
sftk_RSACheckSignRecover(NSSLOWKEYPublicKey * key,unsigned char * data,unsigned int * dataLen,unsigned int maxDataLen,const unsigned char * sig,unsigned int sigLen)3861 sftk_RSACheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char *data,
3862                          unsigned int *dataLen, unsigned int maxDataLen,
3863                          const unsigned char *sig, unsigned int sigLen)
3864 {
3865     PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3866     if (key->keyType != NSSLOWKEYRSAKey) {
3867         PORT_SetError(SEC_ERROR_INVALID_KEY);
3868         return SECFailure;
3869     }
3870 
3871     return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen,
3872                                 sig, sigLen);
3873 }
3874 
3875 static SECStatus
sftk_RSACheckSignRecoverRaw(NSSLOWKEYPublicKey * key,unsigned char * data,unsigned int * dataLen,unsigned int maxDataLen,const unsigned char * sig,unsigned int sigLen)3876 sftk_RSACheckSignRecoverRaw(NSSLOWKEYPublicKey *key, unsigned char *data,
3877                             unsigned int *dataLen, unsigned int maxDataLen,
3878                             const unsigned char *sig, unsigned int sigLen)
3879 {
3880     PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3881     if (key->keyType != NSSLOWKEYRSAKey) {
3882         PORT_SetError(SEC_ERROR_INVALID_KEY);
3883         return SECFailure;
3884     }
3885 
3886     return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen,
3887                                    sig, sigLen);
3888 }
3889 
3890 /* NSC_VerifyRecoverInit initializes a signature verification operation,
3891  * where the data is recovered from the signature.
3892  * E.g. Decryption with the user's public key */
3893 CK_RV
NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)3894 NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
3895                       CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3896 {
3897     SFTKSession *session;
3898     SFTKObject *key;
3899     SFTKSessionContext *context;
3900     CK_KEY_TYPE key_type;
3901     CK_RV crv = CKR_OK;
3902     NSSLOWKEYPublicKey *pubKey;
3903 
3904     CHECK_FORK();
3905 
3906     session = sftk_SessionFromHandle(hSession);
3907     if (session == NULL)
3908         return CKR_SESSION_HANDLE_INVALID;
3909     crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY_RECOVER,
3910                            &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER);
3911     if (crv != CKR_OK) {
3912         sftk_FreeSession(session);
3913         return crv;
3914     }
3915 
3916     context->multi = PR_TRUE;
3917 
3918     switch (pMechanism->mechanism) {
3919         case CKM_RSA_PKCS:
3920         case CKM_RSA_X_509:
3921             if (key_type != CKK_RSA) {
3922                 crv = CKR_KEY_TYPE_INCONSISTENT;
3923                 break;
3924             }
3925             context->multi = PR_FALSE;
3926             context->rsa = PR_TRUE;
3927             pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
3928             if (pubKey == NULL) {
3929                 break;
3930             }
3931             context->cipherInfo = pubKey;
3932             context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509
3933                                                ? sftk_RSACheckSignRecoverRaw
3934                                                : sftk_RSACheckSignRecover);
3935             context->destroy = sftk_Null;
3936             break;
3937         default:
3938             crv = CKR_MECHANISM_INVALID;
3939             break;
3940     }
3941 
3942     if (crv != CKR_OK) {
3943         PORT_Free(context);
3944         sftk_FreeSession(session);
3945         return crv;
3946     }
3947     sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context);
3948     sftk_FreeSession(session);
3949     return CKR_OK;
3950 }
3951 
3952 /* NSC_VerifyRecover verifies a signature in a single-part operation,
3953  * where the data is recovered from the signature.
3954  * E.g. Decryption with the user's public key */
3955 CK_RV
NSC_VerifyRecover(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)3956 NSC_VerifyRecover(CK_SESSION_HANDLE hSession,
3957                   CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen,
3958                   CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3959 {
3960     SFTKSession *session;
3961     SFTKSessionContext *context;
3962     unsigned int outlen;
3963     unsigned int maxoutlen = *pulDataLen;
3964     CK_RV crv;
3965     SECStatus rv;
3966 
3967     CHECK_FORK();
3968 
3969     /* make sure we're legal */
3970     crv = sftk_GetContext(hSession, &context, SFTK_VERIFY_RECOVER,
3971                           PR_FALSE, &session);
3972     if (crv != CKR_OK)
3973         return crv;
3974     if (pData == NULL) {
3975         /* to return the actual size, we need  to do the decrypt, just return
3976          * the max size, which is the size of the input signature. */
3977         *pulDataLen = ulSignatureLen;
3978         rv = SECSuccess;
3979         goto finish;
3980     }
3981 
3982     rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
3983                             pSignature, ulSignatureLen);
3984     *pulDataLen = (CK_ULONG)outlen;
3985 
3986     sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context);
3987 finish:
3988     sftk_FreeSession(session);
3989     return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError());
3990 }
3991 
3992 /*
3993  **************************** Random Functions:  ************************
3994  */
3995 
3996 /* NSC_SeedRandom mixes additional seed material into the token's random number
3997  * generator. */
3998 CK_RV
NSC_SeedRandom(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSeed,CK_ULONG ulSeedLen)3999 NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
4000                CK_ULONG ulSeedLen)
4001 {
4002     SECStatus rv;
4003 
4004     CHECK_FORK();
4005 
4006     rv = RNG_RandomUpdate(pSeed, ulSeedLen);
4007     return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
4008 }
4009 
4010 /* NSC_GenerateRandom generates random data. */
4011 CK_RV
NSC_GenerateRandom(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pRandomData,CK_ULONG ulRandomLen)4012 NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
4013                    CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
4014 {
4015     SECStatus rv;
4016 
4017     CHECK_FORK();
4018 
4019     rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen);
4020     /*
4021      * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't
4022      * seeded with enough entropy.
4023      */
4024     return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
4025 }
4026 
4027 /*
4028  **************************** Key Functions:  ************************
4029  */
4030 
4031 /*
4032  * generate a password based encryption key. This code uses
4033  * PKCS5 to do the work.
4034  */
4035 static CK_RV
nsc_pbe_key_gen(NSSPKCS5PBEParameter * pkcs5_pbe,CK_MECHANISM_PTR pMechanism,void * buf,CK_ULONG * key_length,PRBool faulty3DES)4036 nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
4037                 void *buf, CK_ULONG *key_length, PRBool faulty3DES)
4038 {
4039     SECItem *pbe_key = NULL, iv, pwitem;
4040     CK_PBE_PARAMS *pbe_params = NULL;
4041     CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
4042 
4043     *key_length = 0;
4044     iv.data = NULL;
4045     iv.len = 0;
4046 
4047     if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
4048         if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) {
4049             return CKR_MECHANISM_PARAM_INVALID;
4050         }
4051         pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
4052         pwitem.data = (unsigned char *)pbkd2_params->pPassword;
4053         /* was this a typo in the PKCS #11 spec? */
4054         pwitem.len = *pbkd2_params->ulPasswordLen;
4055     } else {
4056         if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
4057             return CKR_MECHANISM_PARAM_INVALID;
4058         }
4059         pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
4060         pwitem.data = (unsigned char *)pbe_params->pPassword;
4061         pwitem.len = pbe_params->ulPasswordLen;
4062     }
4063     pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES);
4064     if (pbe_key == NULL) {
4065         return CKR_HOST_MEMORY;
4066     }
4067 
4068     PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
4069     *key_length = pbe_key->len;
4070     SECITEM_ZfreeItem(pbe_key, PR_TRUE);
4071     pbe_key = NULL;
4072 
4073     if (iv.data) {
4074         if (pbe_params && pbe_params->pInitVector != NULL) {
4075             PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len);
4076         }
4077         PORT_Free(iv.data);
4078     }
4079 
4080     return CKR_OK;
4081 }
4082 
4083 /*
4084  * this is coded for "full" support. These selections will be limitted to
4085  * the official subset by freebl.
4086  */
4087 static unsigned int
sftk_GetSubPrimeFromPrime(unsigned int primeBits)4088 sftk_GetSubPrimeFromPrime(unsigned int primeBits)
4089 {
4090     if (primeBits <= 1024) {
4091         return 160;
4092     } else if (primeBits <= 2048) {
4093         return 224;
4094     } else if (primeBits <= 3072) {
4095         return 256;
4096     } else if (primeBits <= 7680) {
4097         return 384;
4098     } else {
4099         return 512;
4100     }
4101 }
4102 
4103 static CK_RV
nsc_parameter_gen(CK_KEY_TYPE key_type,SFTKObject * key)4104 nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
4105 {
4106     SFTKAttribute *attribute;
4107     CK_ULONG counter;
4108     unsigned int seedBits = 0;
4109     unsigned int subprimeBits = 0;
4110     unsigned int primeBits;
4111     unsigned int j = 8; /* default to 1024 bits */
4112     CK_RV crv = CKR_OK;
4113     PQGParams *params = NULL;
4114     PQGVerify *vfy = NULL;
4115     SECStatus rv;
4116 
4117     attribute = sftk_FindAttribute(key, CKA_PRIME_BITS);
4118     if (attribute == NULL) {
4119         attribute = sftk_FindAttribute(key, CKA_PRIME);
4120         if (attribute == NULL) {
4121             return CKR_TEMPLATE_INCOMPLETE;
4122         } else {
4123             primeBits = attribute->attrib.ulValueLen;
4124             sftk_FreeAttribute(attribute);
4125         }
4126     } else {
4127         primeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4128         sftk_FreeAttribute(attribute);
4129     }
4130     if (primeBits < 1024) {
4131         j = PQG_PBITS_TO_INDEX(primeBits);
4132         if (j == (unsigned int)-1) {
4133             return CKR_ATTRIBUTE_VALUE_INVALID;
4134         }
4135     }
4136 
4137     attribute = sftk_FindAttribute(key, CKA_NSS_PQG_SEED_BITS);
4138     if (attribute != NULL) {
4139         seedBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4140         sftk_FreeAttribute(attribute);
4141     }
4142 
4143     attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS);
4144     if (attribute != NULL) {
4145         subprimeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4146         sftk_FreeAttribute(attribute);
4147     }
4148 
4149     /* if P and Q are supplied, we want to generate a new G */
4150     attribute = sftk_FindAttribute(key, CKA_PRIME);
4151     if (attribute != NULL) {
4152         PLArenaPool *arena;
4153 
4154         sftk_FreeAttribute(attribute);
4155         arena = PORT_NewArena(1024);
4156         if (arena == NULL) {
4157             crv = CKR_HOST_MEMORY;
4158             goto loser;
4159         }
4160         params = PORT_ArenaAlloc(arena, sizeof(*params));
4161         if (params == NULL) {
4162             crv = CKR_HOST_MEMORY;
4163             goto loser;
4164         }
4165         params->arena = arena;
4166         crv = sftk_Attribute2SSecItem(arena, &params->prime, key, CKA_PRIME);
4167         if (crv != CKR_OK) {
4168             goto loser;
4169         }
4170         crv = sftk_Attribute2SSecItem(arena, &params->subPrime,
4171                                       key, CKA_SUBPRIME);
4172         if (crv != CKR_OK) {
4173             goto loser;
4174         }
4175 
4176         arena = PORT_NewArena(1024);
4177         if (arena == NULL) {
4178             crv = CKR_HOST_MEMORY;
4179             goto loser;
4180         }
4181         vfy = PORT_ArenaAlloc(arena, sizeof(*vfy));
4182         if (vfy == NULL) {
4183             crv = CKR_HOST_MEMORY;
4184             goto loser;
4185         }
4186         vfy->arena = arena;
4187         crv = sftk_Attribute2SSecItem(arena, &vfy->seed, key, CKA_NSS_PQG_SEED);
4188         if (crv != CKR_OK) {
4189             goto loser;
4190         }
4191         crv = sftk_Attribute2SSecItem(arena, &vfy->h, key, CKA_NSS_PQG_H);
4192         if (crv != CKR_OK) {
4193             goto loser;
4194         }
4195         sftk_DeleteAttributeType(key, CKA_PRIME);
4196         sftk_DeleteAttributeType(key, CKA_SUBPRIME);
4197         sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED);
4198         sftk_DeleteAttributeType(key, CKA_NSS_PQG_H);
4199     }
4200 
4201     sftk_DeleteAttributeType(key, CKA_PRIME_BITS);
4202     sftk_DeleteAttributeType(key, CKA_SUBPRIME_BITS);
4203     sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED_BITS);
4204 
4205     /* use the old PQG interface if we have old input data */
4206     if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) {
4207         if (seedBits == 0) {
4208             rv = PQG_ParamGen(j, &params, &vfy);
4209         } else {
4210             rv = PQG_ParamGenSeedLen(j, seedBits / 8, &params, &vfy);
4211         }
4212     } else {
4213         if (subprimeBits == 0) {
4214             subprimeBits = sftk_GetSubPrimeFromPrime(primeBits);
4215         }
4216         if (seedBits == 0) {
4217             seedBits = primeBits;
4218         }
4219         rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits / 8, &params, &vfy);
4220     }
4221 
4222     if (rv != SECSuccess) {
4223         if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4224             sftk_fatalError = PR_TRUE;
4225         }
4226         return sftk_MapCryptError(PORT_GetError());
4227     }
4228     crv = sftk_AddAttributeType(key, CKA_PRIME,
4229                                 params->prime.data, params->prime.len);
4230     if (crv != CKR_OK)
4231         goto loser;
4232     crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
4233                                 params->subPrime.data, params->subPrime.len);
4234     if (crv != CKR_OK)
4235         goto loser;
4236     crv = sftk_AddAttributeType(key, CKA_BASE,
4237                                 params->base.data, params->base.len);
4238     if (crv != CKR_OK)
4239         goto loser;
4240     counter = vfy->counter;
4241     crv = sftk_AddAttributeType(key, CKA_NSS_PQG_COUNTER,
4242                                 &counter, sizeof(counter));
4243     crv = sftk_AddAttributeType(key, CKA_NSS_PQG_SEED,
4244                                 vfy->seed.data, vfy->seed.len);
4245     if (crv != CKR_OK)
4246         goto loser;
4247     crv = sftk_AddAttributeType(key, CKA_NSS_PQG_H,
4248                                 vfy->h.data, vfy->h.len);
4249     if (crv != CKR_OK)
4250         goto loser;
4251 
4252 loser:
4253     if (params) {
4254         PQG_DestroyParams(params);
4255     }
4256 
4257     if (vfy) {
4258         PQG_DestroyVerify(vfy);
4259     }
4260     return crv;
4261 }
4262 
4263 static CK_RV
nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism,CK_KEY_TYPE * key_type,CK_ULONG * key_length)4264 nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
4265                     CK_ULONG *key_length)
4266 {
4267     CK_RV crv = CKR_OK;
4268 
4269     switch (mechanism) {
4270 #ifndef NSS_DISABLE_DEPRECATED_RC2
4271         case CKM_RC2_KEY_GEN:
4272             *key_type = CKK_RC2;
4273             if (*key_length == 0)
4274                 crv = CKR_TEMPLATE_INCOMPLETE;
4275             break;
4276 #endif /* NSS_DISABLE_DEPRECATED_RC2 */
4277 #if NSS_SOFTOKEN_DOES_RC5
4278         case CKM_RC5_KEY_GEN:
4279             *key_type = CKK_RC5;
4280             if (*key_length == 0)
4281                 crv = CKR_TEMPLATE_INCOMPLETE;
4282             break;
4283 #endif
4284         case CKM_RC4_KEY_GEN:
4285             *key_type = CKK_RC4;
4286             if (*key_length == 0)
4287                 crv = CKR_TEMPLATE_INCOMPLETE;
4288             break;
4289         case CKM_GENERIC_SECRET_KEY_GEN:
4290             *key_type = CKK_GENERIC_SECRET;
4291             if (*key_length == 0)
4292                 crv = CKR_TEMPLATE_INCOMPLETE;
4293             break;
4294         case CKM_CDMF_KEY_GEN:
4295             *key_type = CKK_CDMF;
4296             *key_length = 8;
4297             break;
4298         case CKM_DES_KEY_GEN:
4299             *key_type = CKK_DES;
4300             *key_length = 8;
4301             break;
4302         case CKM_DES2_KEY_GEN:
4303             *key_type = CKK_DES2;
4304             *key_length = 16;
4305             break;
4306         case CKM_DES3_KEY_GEN:
4307             *key_type = CKK_DES3;
4308             *key_length = 24;
4309             break;
4310 #ifndef NSS_DISABLE_DEPRECATED_SEED
4311         case CKM_SEED_KEY_GEN:
4312             *key_type = CKK_SEED;
4313             *key_length = 16;
4314             break;
4315 #endif /* NSS_DISABLE_DEPRECATED_SEED */
4316         case CKM_CAMELLIA_KEY_GEN:
4317             *key_type = CKK_CAMELLIA;
4318             if (*key_length == 0)
4319                 crv = CKR_TEMPLATE_INCOMPLETE;
4320             break;
4321         case CKM_AES_KEY_GEN:
4322             *key_type = CKK_AES;
4323             if (*key_length == 0)
4324                 crv = CKR_TEMPLATE_INCOMPLETE;
4325             break;
4326         case CKM_NSS_CHACHA20_KEY_GEN:
4327             *key_type = CKK_NSS_CHACHA20;
4328             *key_length = 32;
4329             break;
4330         case CKM_CHACHA20_KEY_GEN:
4331             *key_type = CKK_CHACHA20;
4332             *key_length = 32;
4333             break;
4334         case CKM_HKDF_KEY_GEN:
4335             *key_type = CKK_HKDF;
4336             if (*key_length == 0)
4337                 crv = CKR_TEMPLATE_INCOMPLETE;
4338             break;
4339         default:
4340             PORT_Assert(0);
4341             crv = CKR_MECHANISM_INVALID;
4342             break;
4343     }
4344 
4345     return crv;
4346 }
4347 
4348 CK_RV
nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism,NSSPKCS5PBEParameter ** pbe)4349 nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
4350 {
4351     SECItem salt;
4352     CK_PBE_PARAMS *pbe_params = NULL;
4353     NSSPKCS5PBEParameter *params;
4354     PLArenaPool *arena = NULL;
4355     SECStatus rv;
4356 
4357     *pbe = NULL;
4358 
4359     arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
4360     if (arena == NULL) {
4361         return CKR_HOST_MEMORY;
4362     }
4363 
4364     params = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena,
4365                                                       sizeof(NSSPKCS5PBEParameter));
4366     if (params == NULL) {
4367         PORT_FreeArena(arena, PR_TRUE);
4368         return CKR_HOST_MEMORY;
4369     }
4370     if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
4371         PORT_FreeArena(arena, PR_TRUE);
4372         return CKR_MECHANISM_PARAM_INVALID;
4373     }
4374 
4375     params->poolp = arena;
4376     params->ivLen = 0;
4377     params->pbeType = NSSPKCS5_PKCS12_V2;
4378     params->hashType = HASH_AlgSHA1;
4379     params->encAlg = SEC_OID_SHA1; /* any invalid value */
4380     params->is2KeyDES = PR_FALSE;
4381     params->keyID = pbeBitGenIntegrityKey;
4382     pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
4383     params->iter = pbe_params->ulIteration;
4384 
4385     salt.data = (unsigned char *)pbe_params->pSalt;
4386     salt.len = (unsigned int)pbe_params->ulSaltLen;
4387     salt.type = siBuffer;
4388     rv = SECITEM_CopyItem(arena, &params->salt, &salt);
4389     if (rv != SECSuccess) {
4390         PORT_FreeArena(arena, PR_TRUE);
4391         return CKR_HOST_MEMORY;
4392     }
4393     switch (pMechanism->mechanism) {
4394         case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
4395         case CKM_PBA_SHA1_WITH_SHA1_HMAC:
4396             params->hashType = HASH_AlgSHA1;
4397             params->keyLen = 20;
4398             break;
4399         case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
4400             params->hashType = HASH_AlgMD5;
4401             params->keyLen = 16;
4402             break;
4403         case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
4404             params->hashType = HASH_AlgMD2;
4405             params->keyLen = 16;
4406             break;
4407         case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
4408             params->hashType = HASH_AlgSHA224;
4409             params->keyLen = 28;
4410             break;
4411         case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
4412             params->hashType = HASH_AlgSHA256;
4413             params->keyLen = 32;
4414             break;
4415         case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
4416             params->hashType = HASH_AlgSHA384;
4417             params->keyLen = 48;
4418             break;
4419         case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
4420             params->hashType = HASH_AlgSHA512;
4421             params->keyLen = 64;
4422             break;
4423         default:
4424             PORT_FreeArena(arena, PR_TRUE);
4425             return CKR_MECHANISM_INVALID;
4426     }
4427     *pbe = params;
4428     return CKR_OK;
4429 }
4430 
4431 /* maybe this should be table driven? */
4432 static CK_RV
nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism,NSSPKCS5PBEParameter ** pbe,CK_KEY_TYPE * key_type,CK_ULONG * key_length)4433 nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
4434                    CK_KEY_TYPE *key_type, CK_ULONG *key_length)
4435 {
4436     CK_RV crv = CKR_OK;
4437     SECOidData *oid;
4438     CK_PBE_PARAMS *pbe_params = NULL;
4439     NSSPKCS5PBEParameter *params = NULL;
4440     HASH_HashType hashType = HASH_AlgSHA1;
4441     CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
4442     SECItem salt;
4443     CK_ULONG iteration = 0;
4444 
4445     *pbe = NULL;
4446 
4447     oid = SECOID_FindOIDByMechanism(pMechanism->mechanism);
4448     if (oid == NULL) {
4449         return CKR_MECHANISM_INVALID;
4450     }
4451 
4452     if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
4453         if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) {
4454             return CKR_MECHANISM_PARAM_INVALID;
4455         }
4456         pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
4457         switch (pbkd2_params->prf) {
4458             case CKP_PKCS5_PBKD2_HMAC_SHA1:
4459                 hashType = HASH_AlgSHA1;
4460                 break;
4461             case CKP_PKCS5_PBKD2_HMAC_SHA224:
4462                 hashType = HASH_AlgSHA224;
4463                 break;
4464             case CKP_PKCS5_PBKD2_HMAC_SHA256:
4465                 hashType = HASH_AlgSHA256;
4466                 break;
4467             case CKP_PKCS5_PBKD2_HMAC_SHA384:
4468                 hashType = HASH_AlgSHA384;
4469                 break;
4470             case CKP_PKCS5_PBKD2_HMAC_SHA512:
4471                 hashType = HASH_AlgSHA512;
4472                 break;
4473             default:
4474                 return CKR_MECHANISM_PARAM_INVALID;
4475         }
4476         if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) {
4477             return CKR_MECHANISM_PARAM_INVALID;
4478         }
4479         salt.data = (unsigned char *)pbkd2_params->pSaltSourceData;
4480         salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen;
4481         iteration = pbkd2_params->iterations;
4482     } else {
4483         if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
4484             return CKR_MECHANISM_PARAM_INVALID;
4485         }
4486         pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
4487         salt.data = (unsigned char *)pbe_params->pSalt;
4488         salt.len = (unsigned int)pbe_params->ulSaltLen;
4489         iteration = pbe_params->ulIteration;
4490     }
4491     params = nsspkcs5_NewParam(oid->offset, hashType, &salt, iteration);
4492     if (params == NULL) {
4493         return CKR_MECHANISM_INVALID;
4494     }
4495 
4496     switch (params->encAlg) {
4497         case SEC_OID_DES_CBC:
4498             *key_type = CKK_DES;
4499             *key_length = params->keyLen;
4500             break;
4501         case SEC_OID_DES_EDE3_CBC:
4502             *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3;
4503             *key_length = params->keyLen;
4504             break;
4505 #ifndef NSS_DISABLE_DEPRECATED_RC2
4506         case SEC_OID_RC2_CBC:
4507             *key_type = CKK_RC2;
4508             *key_length = params->keyLen;
4509             break;
4510 #endif /* NSS_DISABLE_DEPRECATED_RC2 */
4511         case SEC_OID_RC4:
4512             *key_type = CKK_RC4;
4513             *key_length = params->keyLen;
4514             break;
4515         case SEC_OID_PKCS5_PBKDF2:
4516             /* key type must already be set */
4517             if (*key_type == CKK_INVALID_KEY_TYPE) {
4518                 crv = CKR_TEMPLATE_INCOMPLETE;
4519                 break;
4520             }
4521             /* PBKDF2 needs to calculate the key length from the other parameters
4522              */
4523             if (*key_length == 0) {
4524                 *key_length = sftk_MapKeySize(*key_type);
4525             }
4526             if (*key_length == 0) {
4527                 crv = CKR_TEMPLATE_INCOMPLETE;
4528                 break;
4529             }
4530             params->keyLen = *key_length;
4531             break;
4532         default:
4533             crv = CKR_MECHANISM_INVALID;
4534             break;
4535     }
4536     if (crv == CKR_OK) {
4537         *pbe = params;
4538     } else {
4539         nsspkcs5_DestroyPBEParameter(params);
4540     }
4541     return crv;
4542 }
4543 
4544 /* NSC_GenerateKey generates a secret key, creating a new key object. */
4545 CK_RV
NSC_GenerateKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phKey)4546 NSC_GenerateKey(CK_SESSION_HANDLE hSession,
4547                 CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
4548                 CK_OBJECT_HANDLE_PTR phKey)
4549 {
4550     SFTKObject *key;
4551     SFTKSession *session;
4552     PRBool checkWeak = PR_FALSE;
4553     CK_ULONG key_length = 0;
4554     CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE;
4555     CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
4556     CK_RV crv = CKR_OK;
4557     CK_BBOOL cktrue = CK_TRUE;
4558     NSSPKCS5PBEParameter *pbe_param = NULL;
4559     int i;
4560     SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
4561     unsigned char buf[MAX_KEY_LEN];
4562     enum { nsc_pbe,
4563            nsc_ssl,
4564            nsc_bulk,
4565            nsc_param,
4566            nsc_jpake } key_gen_type;
4567     SSL3RSAPreMasterSecret *rsa_pms;
4568     CK_VERSION *version;
4569     /* in very old versions of NSS, there were implementation errors with key
4570      * generation methods.  We want to beable to read these, but not
4571      * produce them any more.  The affected algorithm was 3DES.
4572      */
4573     PRBool faultyPBE3DES = PR_FALSE;
4574     HASH_HashType hashType = HASH_AlgNULL;
4575 
4576     CHECK_FORK();
4577 
4578     if (!slot) {
4579         return CKR_SESSION_HANDLE_INVALID;
4580     }
4581     /*
4582      * now lets create an object to hang the attributes off of
4583      */
4584     key = sftk_NewObject(slot); /* fill in the handle later */
4585     if (key == NULL) {
4586         return CKR_HOST_MEMORY;
4587     }
4588 
4589     /*
4590      * load the template values into the object
4591      */
4592     for (i = 0; i < (int)ulCount; i++) {
4593         if (pTemplate[i].type == CKA_VALUE_LEN) {
4594             key_length = *(CK_ULONG *)pTemplate[i].pValue;
4595             continue;
4596         }
4597         /* some algorithms need keytype specified */
4598         if (pTemplate[i].type == CKA_KEY_TYPE) {
4599             key_type = *(CK_ULONG *)pTemplate[i].pValue;
4600             continue;
4601         }
4602 
4603         crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
4604         if (crv != CKR_OK) {
4605             break;
4606         }
4607     }
4608     if (crv != CKR_OK) {
4609         goto loser;
4610     }
4611 
4612     /* make sure we don't have any class, key_type, or value fields */
4613     sftk_DeleteAttributeType(key, CKA_CLASS);
4614     sftk_DeleteAttributeType(key, CKA_KEY_TYPE);
4615     sftk_DeleteAttributeType(key, CKA_VALUE);
4616 
4617     /* Now Set up the parameters to generate the key (based on mechanism) */
4618     key_gen_type = nsc_bulk; /* bulk key by default */
4619     switch (pMechanism->mechanism) {
4620         case CKM_CDMF_KEY_GEN:
4621         case CKM_DES_KEY_GEN:
4622         case CKM_DES2_KEY_GEN:
4623         case CKM_DES3_KEY_GEN:
4624             checkWeak = PR_TRUE;
4625 /* fall through */
4626 #ifndef NSS_DISABLE_DEPRECATED_RC2
4627         case CKM_RC2_KEY_GEN:
4628 #endif
4629         case CKM_RC4_KEY_GEN:
4630         case CKM_GENERIC_SECRET_KEY_GEN:
4631 #ifndef NSS_DISABLE_DEPRECATED_SEED
4632         case CKM_SEED_KEY_GEN:
4633 #endif
4634         case CKM_CAMELLIA_KEY_GEN:
4635         case CKM_AES_KEY_GEN:
4636         case CKM_NSS_CHACHA20_KEY_GEN:
4637         case CKM_CHACHA20_KEY_GEN:
4638 #if NSS_SOFTOKEN_DOES_RC5
4639         case CKM_RC5_KEY_GEN:
4640 #endif
4641             crv = nsc_SetupBulkKeyGen(pMechanism->mechanism, &key_type, &key_length);
4642             break;
4643         case CKM_SSL3_PRE_MASTER_KEY_GEN:
4644             key_type = CKK_GENERIC_SECRET;
4645             key_length = 48;
4646             key_gen_type = nsc_ssl;
4647             break;
4648         case CKM_PBA_SHA1_WITH_SHA1_HMAC:
4649         case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
4650         case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
4651         case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
4652         case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
4653         case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
4654         case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
4655         case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
4656             key_gen_type = nsc_pbe;
4657             key_type = CKK_GENERIC_SECRET;
4658             crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param);
4659             break;
4660         case CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC:
4661             faultyPBE3DES = PR_TRUE;
4662         /* fall through */
4663         case CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC:
4664 #ifndef NSS_DISABLE_DEPRECATED_RC2
4665         case CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC:
4666         case CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC:
4667         case CKM_PBE_SHA1_RC2_128_CBC:
4668         case CKM_PBE_SHA1_RC2_40_CBC:
4669 #endif
4670         case CKM_NSS_PBE_SHA1_DES_CBC:
4671         case CKM_NSS_PBE_SHA1_40_BIT_RC4:
4672         case CKM_NSS_PBE_SHA1_128_BIT_RC4:
4673         case CKM_PBE_SHA1_DES3_EDE_CBC:
4674         case CKM_PBE_SHA1_DES2_EDE_CBC:
4675         case CKM_PBE_SHA1_RC4_128:
4676         case CKM_PBE_SHA1_RC4_40:
4677         case CKM_PBE_MD5_DES_CBC:
4678         case CKM_PBE_MD2_DES_CBC:
4679         case CKM_PKCS5_PBKD2:
4680             key_gen_type = nsc_pbe;
4681             crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length);
4682             break;
4683         case CKM_DSA_PARAMETER_GEN:
4684             key_gen_type = nsc_param;
4685             key_type = CKK_DSA;
4686             objclass = CKO_DOMAIN_PARAMETERS;
4687             crv = CKR_OK;
4688             break;
4689         case CKM_NSS_JPAKE_ROUND1_SHA1:
4690             hashType = HASH_AlgSHA1;
4691             goto jpake1;
4692         case CKM_NSS_JPAKE_ROUND1_SHA256:
4693             hashType = HASH_AlgSHA256;
4694             goto jpake1;
4695         case CKM_NSS_JPAKE_ROUND1_SHA384:
4696             hashType = HASH_AlgSHA384;
4697             goto jpake1;
4698         case CKM_NSS_JPAKE_ROUND1_SHA512:
4699             hashType = HASH_AlgSHA512;
4700             goto jpake1;
4701         jpake1:
4702             key_gen_type = nsc_jpake;
4703             key_type = CKK_NSS_JPAKE_ROUND1;
4704             objclass = CKO_PRIVATE_KEY;
4705             if (pMechanism->pParameter == NULL ||
4706                 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) {
4707                 crv = CKR_MECHANISM_PARAM_INVALID;
4708                 break;
4709             }
4710             if (sftk_isTrue(key, CKA_TOKEN)) {
4711                 crv = CKR_TEMPLATE_INCONSISTENT;
4712                 break;
4713             }
4714             crv = CKR_OK;
4715             break;
4716         default:
4717             crv = CKR_MECHANISM_INVALID;
4718             break;
4719     }
4720 
4721     /* make sure we aren't going to overflow the buffer */
4722     if (sizeof(buf) < key_length) {
4723         /* someone is getting pretty optimistic about how big their key can
4724          * be... */
4725         crv = CKR_TEMPLATE_INCONSISTENT;
4726     }
4727 
4728     if (crv != CKR_OK) {
4729         if (pbe_param) {
4730             nsspkcs5_DestroyPBEParameter(pbe_param);
4731         }
4732         goto loser;
4733     }
4734 
4735     /* if there was no error,
4736      * key_type *MUST* be set in the switch statement above */
4737     PORT_Assert(key_type != CKK_INVALID_KEY_TYPE);
4738 
4739     /*
4740      * now to the actual key gen.
4741      */
4742     switch (key_gen_type) {
4743         case nsc_pbe:
4744             crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length,
4745                                   faultyPBE3DES);
4746             nsspkcs5_DestroyPBEParameter(pbe_param);
4747             break;
4748         case nsc_ssl:
4749             rsa_pms = (SSL3RSAPreMasterSecret *)buf;
4750             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_VERSION))) {
4751                 crv = CKR_MECHANISM_PARAM_INVALID;
4752                 goto loser;
4753             }
4754             version = (CK_VERSION *)pMechanism->pParameter;
4755             rsa_pms->client_version[0] = version->major;
4756             rsa_pms->client_version[1] = version->minor;
4757             crv =
4758                 NSC_GenerateRandom(0, &rsa_pms->random[0], sizeof(rsa_pms->random));
4759             break;
4760         case nsc_bulk:
4761             /* get the key, check for weak keys and repeat if found */
4762             do {
4763                 crv = NSC_GenerateRandom(0, buf, key_length);
4764             } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf, key_type));
4765             break;
4766         case nsc_param:
4767             /* generate parameters */
4768             *buf = 0;
4769             crv = nsc_parameter_gen(key_type, key);
4770             break;
4771         case nsc_jpake:
4772             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_NSS_JPAKERound1Params))) {
4773                 crv = CKR_MECHANISM_PARAM_INVALID;
4774                 goto loser;
4775             }
4776             crv = jpake_Round1(hashType,
4777                                (CK_NSS_JPAKERound1Params *)pMechanism->pParameter,
4778                                key);
4779             break;
4780     }
4781 
4782     if (crv != CKR_OK) {
4783         goto loser;
4784     }
4785 
4786     /* Add the class, key_type, and value */
4787     crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS));
4788     if (crv != CKR_OK) {
4789         goto loser;
4790     }
4791     crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE));
4792     if (crv != CKR_OK) {
4793         goto loser;
4794     }
4795     if (key_length != 0) {
4796         crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
4797         if (crv != CKR_OK) {
4798             goto loser;
4799         }
4800     }
4801 
4802     /* get the session */
4803     session = sftk_SessionFromHandle(hSession);
4804     if (session == NULL) {
4805         crv = CKR_SESSION_HANDLE_INVALID;
4806         goto loser;
4807     }
4808 
4809     /*
4810      * handle the base object stuff
4811      */
4812     crv = sftk_handleObject(key, session);
4813     sftk_FreeSession(session);
4814     if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) {
4815         crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL));
4816     }
4817     if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) {
4818         crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL));
4819     }
4820     if (crv == CKR_OK) {
4821         *phKey = key->handle;
4822     }
4823 loser:
4824     PORT_Memset(buf, 0, sizeof buf);
4825     sftk_FreeObject(key);
4826     return crv;
4827 }
4828 
4829 #define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */
4830 #define PAIRWISE_MESSAGE_LENGTH 20         /* 160-bits */
4831 
4832 /*
4833  * FIPS 140-2 pairwise consistency check utilized to validate key pair.
4834  *
4835  * This function returns
4836  *   CKR_OK               if pairwise consistency check passed
4837  *   CKR_GENERAL_ERROR    if pairwise consistency check failed
4838  *   other error codes    if paiswise consistency check could not be
4839  *                        performed, for example, CKR_HOST_MEMORY.
4840  */
4841 static CK_RV
sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,SFTKSlot * slot,SFTKObject * publicKey,SFTKObject * privateKey,CK_KEY_TYPE keyType)4842 sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, SFTKSlot *slot,
4843                               SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType)
4844 {
4845     /*
4846      *                      Key type    Mechanism type
4847      *                      --------------------------------
4848      * For encrypt/decrypt: CKK_RSA  => CKM_RSA_PKCS
4849      *                      others   => CKM_INVALID_MECHANISM
4850      *
4851      * For sign/verify:     CKK_RSA  => CKM_RSA_PKCS
4852      *                      CKK_DSA  => CKM_DSA
4853      *                      CKK_EC   => CKM_ECDSA
4854      *                      others   => CKM_INVALID_MECHANISM
4855      *
4856      * None of these mechanisms has a parameter.
4857      *
4858      * For derive           CKK_DH   => CKM_DH_PKCS_DERIVE
4859      *                      CKK_EC   => CKM_ECDH1_DERIVE
4860      *                      others   => CKM_INVALID_MECHANISM
4861      *
4862      * The parameters for these mechanisms is the public key.
4863      */
4864     CK_MECHANISM mech = { 0, NULL, 0 };
4865 
4866     CK_ULONG modulusLen = 0;
4867     CK_ULONG subPrimeLen = 0;
4868     PRBool isEncryptable = PR_FALSE;
4869     PRBool canSignVerify = PR_FALSE;
4870     PRBool isDerivable = PR_FALSE;
4871     CK_RV crv;
4872 
4873     /* Variables used for Encrypt/Decrypt functions. */
4874     unsigned char *known_message = (unsigned char *)"Known Crypto Message";
4875     unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH];
4876     CK_ULONG bytes_decrypted;
4877     unsigned char *ciphertext;
4878     unsigned char *text_compared;
4879     CK_ULONG bytes_encrypted;
4880     CK_ULONG bytes_compared;
4881     CK_ULONG pairwise_digest_length = PAIRWISE_DIGEST_LENGTH;
4882 
4883     /* Variables used for Signature/Verification functions. */
4884     /* Must be at least 256 bits for DSA2 digest */
4885     unsigned char *known_digest = (unsigned char *)"Mozilla Rules the World through NSS!";
4886     unsigned char *signature;
4887     CK_ULONG signature_length;
4888 
4889     if (keyType == CKK_RSA) {
4890         SFTKAttribute *attribute;
4891 
4892         /* Get modulus length of private key. */
4893         attribute = sftk_FindAttribute(privateKey, CKA_MODULUS);
4894         if (attribute == NULL) {
4895             return CKR_DEVICE_ERROR;
4896         }
4897         modulusLen = attribute->attrib.ulValueLen;
4898         if (*(unsigned char *)attribute->attrib.pValue == 0) {
4899             modulusLen--;
4900         }
4901         sftk_FreeAttribute(attribute);
4902     } else if (keyType == CKK_DSA) {
4903         SFTKAttribute *attribute;
4904 
4905         /* Get subprime length of private key. */
4906         attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME);
4907         if (attribute == NULL) {
4908             return CKR_DEVICE_ERROR;
4909         }
4910         subPrimeLen = attribute->attrib.ulValueLen;
4911         if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) {
4912             subPrimeLen--;
4913         }
4914         sftk_FreeAttribute(attribute);
4915     }
4916 
4917     /**************************************************/
4918     /* Pairwise Consistency Check of Encrypt/Decrypt. */
4919     /**************************************************/
4920 
4921     isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT);
4922 
4923     /*
4924      * If the decryption attribute is set, attempt to encrypt
4925      * with the public key and decrypt with the private key.
4926      */
4927     if (isEncryptable) {
4928         if (keyType != CKK_RSA) {
4929             return CKR_DEVICE_ERROR;
4930         }
4931         bytes_encrypted = modulusLen;
4932         mech.mechanism = CKM_RSA_PKCS;
4933 
4934         /* Allocate space for ciphertext. */
4935         ciphertext = (unsigned char *)PORT_ZAlloc(bytes_encrypted);
4936         if (ciphertext == NULL) {
4937             return CKR_HOST_MEMORY;
4938         }
4939 
4940         /* Prepare for encryption using the public key. */
4941         crv = NSC_EncryptInit(hSession, &mech, publicKey->handle);
4942         if (crv != CKR_OK) {
4943             PORT_Free(ciphertext);
4944             return crv;
4945         }
4946 
4947         /* Encrypt using the public key. */
4948         crv = NSC_Encrypt(hSession,
4949                           known_message,
4950                           PAIRWISE_MESSAGE_LENGTH,
4951                           ciphertext,
4952                           &bytes_encrypted);
4953         if (crv != CKR_OK) {
4954             PORT_Free(ciphertext);
4955             return crv;
4956         }
4957 
4958         /* Always use the smaller of these two values . . . */
4959         bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH);
4960 
4961         /*
4962          * If there was a failure, the plaintext
4963          * goes at the end, therefore . . .
4964          */
4965         text_compared = ciphertext + bytes_encrypted - bytes_compared;
4966 
4967         /*
4968          * Check to ensure that ciphertext does
4969          * NOT EQUAL known input message text
4970          * per FIPS PUB 140-2 directive.
4971          */
4972         if (PORT_Memcmp(text_compared, known_message,
4973                         bytes_compared) == 0) {
4974             /* Set error to Invalid PRIVATE Key. */
4975             PORT_SetError(SEC_ERROR_INVALID_KEY);
4976             PORT_Free(ciphertext);
4977             return CKR_GENERAL_ERROR;
4978         }
4979 
4980         /* Prepare for decryption using the private key. */
4981         crv = NSC_DecryptInit(hSession, &mech, privateKey->handle);
4982         if (crv != CKR_OK) {
4983             PORT_Free(ciphertext);
4984             return crv;
4985         }
4986 
4987         memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH);
4988 
4989         /*
4990          * Initialize bytes decrypted to be the
4991          * expected PAIRWISE_MESSAGE_LENGTH.
4992          */
4993         bytes_decrypted = PAIRWISE_MESSAGE_LENGTH;
4994 
4995         /*
4996          * Decrypt using the private key.
4997          * NOTE:  No need to reset the
4998          *        value of bytes_encrypted.
4999          */
5000         crv = NSC_Decrypt(hSession,
5001                           ciphertext,
5002                           bytes_encrypted,
5003                           plaintext,
5004                           &bytes_decrypted);
5005 
5006         /* Finished with ciphertext; free it. */
5007         PORT_Free(ciphertext);
5008 
5009         if (crv != CKR_OK) {
5010             return crv;
5011         }
5012 
5013         /*
5014          * Check to ensure that the output plaintext
5015          * does EQUAL known input message text.
5016          */
5017         if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) ||
5018             (PORT_Memcmp(plaintext, known_message,
5019                          PAIRWISE_MESSAGE_LENGTH) != 0)) {
5020             /* Set error to Bad PUBLIC Key. */
5021             PORT_SetError(SEC_ERROR_BAD_KEY);
5022             return CKR_GENERAL_ERROR;
5023         }
5024     }
5025 
5026     /**********************************************/
5027     /* Pairwise Consistency Check of Sign/Verify. */
5028     /**********************************************/
5029 
5030     canSignVerify = sftk_isTrue(privateKey, CKA_SIGN);
5031     /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the
5032      * actual curve to determine if we can do sign/verify. */
5033     if (canSignVerify && keyType == CKK_EC) {
5034         NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv);
5035         if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) {
5036             canSignVerify = PR_FALSE;
5037         }
5038     }
5039 
5040     if (canSignVerify) {
5041         /* Determine length of signature. */
5042         switch (keyType) {
5043             case CKK_RSA:
5044                 signature_length = modulusLen;
5045                 mech.mechanism = CKM_RSA_PKCS;
5046                 break;
5047             case CKK_DSA:
5048                 signature_length = DSA_MAX_SIGNATURE_LEN;
5049                 pairwise_digest_length = subPrimeLen;
5050                 mech.mechanism = CKM_DSA;
5051                 break;
5052             case CKK_EC:
5053                 signature_length = MAX_ECKEY_LEN * 2;
5054                 mech.mechanism = CKM_ECDSA;
5055                 break;
5056             default:
5057                 return CKR_DEVICE_ERROR;
5058         }
5059 
5060         /* Allocate space for signature data. */
5061         signature = (unsigned char *)PORT_ZAlloc(signature_length);
5062         if (signature == NULL) {
5063             return CKR_HOST_MEMORY;
5064         }
5065 
5066         /* Sign the known hash using the private key. */
5067         crv = NSC_SignInit(hSession, &mech, privateKey->handle);
5068         if (crv != CKR_OK) {
5069             PORT_Free(signature);
5070             return crv;
5071         }
5072 
5073         crv = NSC_Sign(hSession,
5074                        known_digest,
5075                        pairwise_digest_length,
5076                        signature,
5077                        &signature_length);
5078         if (crv != CKR_OK) {
5079             PORT_Free(signature);
5080             return crv;
5081         }
5082 
5083         /* detect trivial signing transforms */
5084         if ((signature_length >= pairwise_digest_length) &&
5085             (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
5086             PORT_Free(signature);
5087             return CKR_DEVICE_ERROR;
5088         }
5089 
5090         /* Verify the known hash using the public key. */
5091         crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
5092         if (crv != CKR_OK) {
5093             PORT_Free(signature);
5094             return crv;
5095         }
5096 
5097         crv = NSC_Verify(hSession,
5098                          known_digest,
5099                          pairwise_digest_length,
5100                          signature,
5101                          signature_length);
5102 
5103         /* Free signature data. */
5104         PORT_Free(signature);
5105 
5106         if ((crv == CKR_SIGNATURE_LEN_RANGE) ||
5107             (crv == CKR_SIGNATURE_INVALID)) {
5108             return CKR_GENERAL_ERROR;
5109         }
5110         if (crv != CKR_OK) {
5111             return crv;
5112         }
5113     }
5114 
5115     /**********************************************/
5116     /* Pairwise Consistency Check for Derivation  */
5117     /**********************************************/
5118 
5119     isDerivable = sftk_isTrue(privateKey, CKA_DERIVE);
5120 
5121     if (isDerivable) {
5122         SFTKAttribute *pubAttribute = NULL;
5123         CK_OBJECT_HANDLE newKey;
5124         PRBool isFIPS = sftk_isFIPS(slot->slotID);
5125         CK_RV crv2;
5126         CK_OBJECT_CLASS secret = CKO_SECRET_KEY;
5127         CK_KEY_TYPE generic = CKK_GENERIC_SECRET;
5128         CK_ULONG keyLen = 128;
5129         CK_BBOOL ckTrue = CK_TRUE;
5130         CK_ATTRIBUTE template[] = {
5131             { CKA_CLASS, &secret, sizeof(secret) },
5132             { CKA_KEY_TYPE, &generic, sizeof(generic) },
5133             { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) },
5134             { CKA_DERIVE, &ckTrue, sizeof(ckTrue) }
5135         };
5136         CK_ULONG templateCount = PR_ARRAY_SIZE(template);
5137         CK_ECDH1_DERIVE_PARAMS ecParams;
5138 
5139         crv = CKR_OK; /*paranoia, already get's set before we drop to the end */
5140         /* FIPS 140-2 requires we verify that the resulting key is a valid key.
5141          * The easiest way to do this is to do a derive operation, which checks
5142          * the validity of the key */
5143 
5144         switch (keyType) {
5145             case CKK_DH:
5146                 mech.mechanism = CKM_DH_PKCS_DERIVE;
5147                 pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE);
5148                 if (pubAttribute == NULL) {
5149                     return CKR_DEVICE_ERROR;
5150                 }
5151                 mech.pParameter = pubAttribute->attrib.pValue;
5152                 mech.ulParameterLen = pubAttribute->attrib.ulValueLen;
5153                 break;
5154             case CKK_EC:
5155                 mech.mechanism = CKM_ECDH1_DERIVE;
5156                 pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT);
5157                 if (pubAttribute == NULL) {
5158                     return CKR_DEVICE_ERROR;
5159                 }
5160                 ecParams.kdf = CKD_NULL;
5161                 ecParams.ulSharedDataLen = 0;
5162                 ecParams.pSharedData = NULL;
5163                 ecParams.ulPublicDataLen = pubAttribute->attrib.ulValueLen;
5164                 ecParams.pPublicData = pubAttribute->attrib.pValue;
5165                 mech.pParameter = &ecParams;
5166                 mech.ulParameterLen = sizeof(ecParams);
5167                 break;
5168             default:
5169                 return CKR_DEVICE_ERROR;
5170         }
5171 
5172         crv = NSC_DeriveKey(hSession, &mech, privateKey->handle, template, templateCount, &newKey);
5173         if (crv != CKR_OK) {
5174             sftk_FreeAttribute(pubAttribute);
5175             return crv;
5176         }
5177         /* FIPS requires full validation, but in fipx mode NSC_Derive
5178          * only does partial validation with approved primes, now handle
5179          * full validation */
5180         if (isFIPS && keyType == CKK_DH) {
5181             SECItem pubKey;
5182             SECItem prime;
5183             SECItem subPrime;
5184             const SECItem *subPrimePtr = &subPrime;
5185 
5186             pubKey.data = pubAttribute->attrib.pValue;
5187             pubKey.len = pubAttribute->attrib.ulValueLen;
5188             prime.data = subPrime.data = NULL;
5189             prime.len = subPrime.len = 0;
5190             crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
5191             if (crv != CKR_OK) {
5192                 goto done;
5193             }
5194             crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
5195             /* we ignore the return code an only look at the length */
5196             if (subPrime.len == 0) {
5197                 /* subprime not supplied, In this case look it up.
5198                  * This only works with approved primes, but in FIPS mode
5199                  * that's the only kine of prime that will get here */
5200                 subPrimePtr = sftk_VerifyDH_Prime(&prime, isFIPS);
5201                 if (subPrimePtr == NULL) {
5202                     crv = CKR_GENERAL_ERROR;
5203                     goto done;
5204                 }
5205             }
5206             if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) {
5207                 crv = CKR_GENERAL_ERROR;
5208             }
5209         done:
5210             SECITEM_ZfreeItem(&subPrime, PR_FALSE);
5211             SECITEM_ZfreeItem(&prime, PR_FALSE);
5212         }
5213         /* clean up before we return */
5214         sftk_FreeAttribute(pubAttribute);
5215         crv2 = NSC_DestroyObject(hSession, newKey);
5216         if (crv != CKR_OK) {
5217             return crv;
5218         }
5219         if (crv2 != CKR_OK) {
5220             return crv2;
5221         }
5222     }
5223 
5224     return CKR_OK;
5225 }
5226 
5227 /* NSC_GenerateKeyPair generates a public-key/private-key pair,
5228  * creating new key objects. */
5229 CK_RV
NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey)5230 NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
5231                     CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
5232                     CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
5233                     CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
5234                     CK_OBJECT_HANDLE_PTR phPrivateKey)
5235 {
5236     SFTKObject *publicKey, *privateKey;
5237     SFTKSession *session;
5238     CK_KEY_TYPE key_type;
5239     CK_RV crv = CKR_OK;
5240     CK_BBOOL cktrue = CK_TRUE;
5241     SECStatus rv;
5242     CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
5243     CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
5244     int i;
5245     SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5246     unsigned int bitSize;
5247 
5248     /* RSA */
5249     int public_modulus_bits = 0;
5250     SECItem pubExp;
5251     RSAPrivateKey *rsaPriv;
5252 
5253     /* DSA */
5254     PQGParams pqgParam;
5255     DHParams dhParam;
5256     DSAPrivateKey *dsaPriv;
5257 
5258     /* Diffie Hellman */
5259     DHPrivateKey *dhPriv;
5260 
5261     /* Elliptic Curve Cryptography */
5262     SECItem ecEncodedParams; /* DER Encoded parameters */
5263     ECPrivateKey *ecPriv;
5264     ECParams *ecParams;
5265 
5266     CHECK_FORK();
5267 
5268     if (!slot) {
5269         return CKR_SESSION_HANDLE_INVALID;
5270     }
5271     /*
5272      * now lets create an object to hang the attributes off of
5273      */
5274     publicKey = sftk_NewObject(slot); /* fill in the handle later */
5275     if (publicKey == NULL) {
5276         return CKR_HOST_MEMORY;
5277     }
5278 
5279     /*
5280      * load the template values into the publicKey
5281      */
5282     for (i = 0; i < (int)ulPublicKeyAttributeCount; i++) {
5283         if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {
5284             public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
5285             continue;
5286         }
5287 
5288         crv = sftk_AddAttributeType(publicKey,
5289                                     sftk_attr_expand(&pPublicKeyTemplate[i]));
5290         if (crv != CKR_OK)
5291             break;
5292     }
5293 
5294     if (crv != CKR_OK) {
5295         sftk_FreeObject(publicKey);
5296         return CKR_HOST_MEMORY;
5297     }
5298 
5299     privateKey = sftk_NewObject(slot); /* fill in the handle later */
5300     if (privateKey == NULL) {
5301         sftk_FreeObject(publicKey);
5302         return CKR_HOST_MEMORY;
5303     }
5304     /*
5305      * now load the private key template
5306      */
5307     for (i = 0; i < (int)ulPrivateKeyAttributeCount; i++) {
5308         if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {
5309             continue;
5310         }
5311 
5312         crv = sftk_AddAttributeType(privateKey,
5313                                     sftk_attr_expand(&pPrivateKeyTemplate[i]));
5314         if (crv != CKR_OK)
5315             break;
5316     }
5317 
5318     if (crv != CKR_OK) {
5319         sftk_FreeObject(publicKey);
5320         sftk_FreeObject(privateKey);
5321         return CKR_HOST_MEMORY;
5322     }
5323     sftk_DeleteAttributeType(privateKey, CKA_CLASS);
5324     sftk_DeleteAttributeType(privateKey, CKA_KEY_TYPE);
5325     sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5326     sftk_DeleteAttributeType(publicKey, CKA_CLASS);
5327     sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE);
5328     sftk_DeleteAttributeType(publicKey, CKA_VALUE);
5329 
5330     /* Now Set up the parameters to generate the key (based on mechanism) */
5331     switch (pMechanism->mechanism) {
5332         case CKM_RSA_PKCS_KEY_PAIR_GEN:
5333             /* format the keys */
5334             sftk_DeleteAttributeType(publicKey, CKA_MODULUS);
5335             sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5336             sftk_DeleteAttributeType(privateKey, CKA_MODULUS);
5337             sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT);
5338             sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT);
5339             sftk_DeleteAttributeType(privateKey, CKA_PRIME_1);
5340             sftk_DeleteAttributeType(privateKey, CKA_PRIME_2);
5341             sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_1);
5342             sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_2);
5343             sftk_DeleteAttributeType(privateKey, CKA_COEFFICIENT);
5344             key_type = CKK_RSA;
5345             if (public_modulus_bits == 0) {
5346                 crv = CKR_TEMPLATE_INCOMPLETE;
5347                 break;
5348             }
5349             if (public_modulus_bits < RSA_MIN_MODULUS_BITS) {
5350                 crv = CKR_ATTRIBUTE_VALUE_INVALID;
5351                 break;
5352             }
5353             if (public_modulus_bits % 2 != 0) {
5354                 crv = CKR_ATTRIBUTE_VALUE_INVALID;
5355                 break;
5356             }
5357 
5358             /* extract the exponent */
5359             crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT);
5360             if (crv != CKR_OK)
5361                 break;
5362             bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len);
5363             if (bitSize < 2) {
5364                 crv = CKR_ATTRIBUTE_VALUE_INVALID;
5365                 SECITEM_ZfreeItem(&pubExp, PR_FALSE);
5366                 break;
5367             }
5368             crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT,
5369                                         sftk_item_expand(&pubExp));
5370             if (crv != CKR_OK) {
5371                 SECITEM_ZfreeItem(&pubExp, PR_FALSE);
5372                 break;
5373             }
5374 
5375             rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);
5376             SECITEM_ZfreeItem(&pubExp, PR_FALSE);
5377             if (rsaPriv == NULL) {
5378                 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5379                     sftk_fatalError = PR_TRUE;
5380                 }
5381                 crv = sftk_MapCryptError(PORT_GetError());
5382                 break;
5383             }
5384             /* now fill in the RSA dependent paramenters in the public key */
5385             crv = sftk_AddAttributeType(publicKey, CKA_MODULUS,
5386                                         sftk_item_expand(&rsaPriv->modulus));
5387             if (crv != CKR_OK)
5388                 goto kpg_done;
5389             /* now fill in the RSA dependent paramenters in the private key */
5390             crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5391                                         sftk_item_expand(&rsaPriv->modulus));
5392             if (crv != CKR_OK)
5393                 goto kpg_done;
5394             crv = sftk_AddAttributeType(privateKey, CKA_MODULUS,
5395                                         sftk_item_expand(&rsaPriv->modulus));
5396             if (crv != CKR_OK)
5397                 goto kpg_done;
5398             crv = sftk_AddAttributeType(privateKey, CKA_PRIVATE_EXPONENT,
5399                                         sftk_item_expand(&rsaPriv->privateExponent));
5400             if (crv != CKR_OK)
5401                 goto kpg_done;
5402             crv = sftk_AddAttributeType(privateKey, CKA_PRIME_1,
5403                                         sftk_item_expand(&rsaPriv->prime1));
5404             if (crv != CKR_OK)
5405                 goto kpg_done;
5406             crv = sftk_AddAttributeType(privateKey, CKA_PRIME_2,
5407                                         sftk_item_expand(&rsaPriv->prime2));
5408             if (crv != CKR_OK)
5409                 goto kpg_done;
5410             crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_1,
5411                                         sftk_item_expand(&rsaPriv->exponent1));
5412             if (crv != CKR_OK)
5413                 goto kpg_done;
5414             crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_2,
5415                                         sftk_item_expand(&rsaPriv->exponent2));
5416             if (crv != CKR_OK)
5417                 goto kpg_done;
5418             crv = sftk_AddAttributeType(privateKey, CKA_COEFFICIENT,
5419                                         sftk_item_expand(&rsaPriv->coefficient));
5420         kpg_done:
5421             /* Should zeroize the contents first, since this func doesn't. */
5422             PORT_FreeArena(rsaPriv->arena, PR_TRUE);
5423             break;
5424         case CKM_DSA_KEY_PAIR_GEN:
5425             sftk_DeleteAttributeType(publicKey, CKA_VALUE);
5426             sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5427             sftk_DeleteAttributeType(privateKey, CKA_PRIME);
5428             sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME);
5429             sftk_DeleteAttributeType(privateKey, CKA_BASE);
5430             key_type = CKK_DSA;
5431 
5432             /* extract the necessary parameters and copy them to the private key */
5433             crv = sftk_Attribute2SSecItem(NULL, &pqgParam.prime, publicKey, CKA_PRIME);
5434             if (crv != CKR_OK)
5435                 break;
5436             crv = sftk_Attribute2SSecItem(NULL, &pqgParam.subPrime, publicKey,
5437                                           CKA_SUBPRIME);
5438             if (crv != CKR_OK) {
5439                 SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5440                 break;
5441             }
5442             crv = sftk_Attribute2SSecItem(NULL, &pqgParam.base, publicKey, CKA_BASE);
5443             if (crv != CKR_OK) {
5444                 SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5445                 SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5446                 break;
5447             }
5448             crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
5449                                         sftk_item_expand(&pqgParam.prime));
5450             if (crv != CKR_OK) {
5451                 SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5452                 SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5453                 SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5454                 break;
5455             }
5456             crv = sftk_AddAttributeType(privateKey, CKA_SUBPRIME,
5457                                         sftk_item_expand(&pqgParam.subPrime));
5458             if (crv != CKR_OK) {
5459                 SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5460                 SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5461                 SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5462                 break;
5463             }
5464             crv = sftk_AddAttributeType(privateKey, CKA_BASE,
5465                                         sftk_item_expand(&pqgParam.base));
5466             if (crv != CKR_OK) {
5467                 SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5468                 SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5469                 SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5470                 break;
5471             }
5472 
5473             /*
5474              * these are checked by DSA_NewKey
5475              */
5476             bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data,
5477                                            pqgParam.subPrime.len);
5478             if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) {
5479                 crv = CKR_TEMPLATE_INCOMPLETE;
5480                 SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5481                 SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5482                 SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5483                 break;
5484             }
5485             bitSize = sftk_GetLengthInBits(pqgParam.prime.data, pqgParam.prime.len);
5486             if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) {
5487                 crv = CKR_TEMPLATE_INCOMPLETE;
5488                 SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5489                 SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5490                 SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5491                 break;
5492             }
5493             bitSize = sftk_GetLengthInBits(pqgParam.base.data, pqgParam.base.len);
5494             if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) {
5495                 crv = CKR_TEMPLATE_INCOMPLETE;
5496                 SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5497                 SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5498                 SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5499                 break;
5500             }
5501 
5502             /* Generate the key */
5503             rv = DSA_NewKey(&pqgParam, &dsaPriv);
5504 
5505             SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5506             SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5507             SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5508 
5509             if (rv != SECSuccess) {
5510                 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5511                     sftk_fatalError = PR_TRUE;
5512                 }
5513                 crv = sftk_MapCryptError(PORT_GetError());
5514                 break;
5515             }
5516 
5517             /* store the generated key into the attributes */
5518             crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
5519                                         sftk_item_expand(&dsaPriv->publicValue));
5520             if (crv != CKR_OK)
5521                 goto dsagn_done;
5522 
5523             /* now fill in the RSA dependent paramenters in the private key */
5524             crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5525                                         sftk_item_expand(&dsaPriv->publicValue));
5526             if (crv != CKR_OK)
5527                 goto dsagn_done;
5528             crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5529                                         sftk_item_expand(&dsaPriv->privateValue));
5530 
5531         dsagn_done:
5532             /* should zeroize, since this function doesn't. */
5533             PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
5534             break;
5535 
5536         case CKM_DH_PKCS_KEY_PAIR_GEN:
5537             sftk_DeleteAttributeType(privateKey, CKA_PRIME);
5538             sftk_DeleteAttributeType(privateKey, CKA_BASE);
5539             sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5540             sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5541             key_type = CKK_DH;
5542 
5543             /* extract the necessary parameters and copy them to private keys */
5544             crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey,
5545                                           CKA_PRIME);
5546             if (crv != CKR_OK)
5547                 break;
5548             crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
5549             if (crv != CKR_OK) {
5550                 SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5551                 break;
5552             }
5553             crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
5554                                         sftk_item_expand(&dhParam.prime));
5555             if (crv != CKR_OK) {
5556                 SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5557                 SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5558                 break;
5559             }
5560             crv = sftk_AddAttributeType(privateKey, CKA_BASE,
5561                                         sftk_item_expand(&dhParam.base));
5562             if (crv != CKR_OK) {
5563                 SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5564                 SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5565                 break;
5566             }
5567             bitSize = sftk_GetLengthInBits(dhParam.prime.data, dhParam.prime.len);
5568             if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) {
5569                 crv = CKR_TEMPLATE_INCOMPLETE;
5570                 SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5571                 SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5572                 break;
5573             }
5574             bitSize = sftk_GetLengthInBits(dhParam.base.data, dhParam.base.len);
5575             if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) {
5576                 crv = CKR_TEMPLATE_INCOMPLETE;
5577                 SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5578                 SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5579                 break;
5580             }
5581 
5582             rv = DH_NewKey(&dhParam, &dhPriv);
5583             SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5584             SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5585             if (rv != SECSuccess) {
5586                 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5587                     sftk_fatalError = PR_TRUE;
5588                 }
5589                 crv = sftk_MapCryptError(PORT_GetError());
5590                 break;
5591             }
5592 
5593             crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
5594                                         sftk_item_expand(&dhPriv->publicValue));
5595             if (crv != CKR_OK)
5596                 goto dhgn_done;
5597 
5598             crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5599                                         sftk_item_expand(&dhPriv->publicValue));
5600             if (crv != CKR_OK)
5601                 goto dhgn_done;
5602 
5603             crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5604                                         sftk_item_expand(&dhPriv->privateValue));
5605 
5606         dhgn_done:
5607             /* should zeroize, since this function doesn't. */
5608             PORT_FreeArena(dhPriv->arena, PR_TRUE);
5609             break;
5610 
5611         case CKM_EC_KEY_PAIR_GEN:
5612             sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS);
5613             sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5614             sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5615             key_type = CKK_EC;
5616 
5617             /* extract the necessary parameters and copy them to private keys */
5618             crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
5619                                           CKA_EC_PARAMS);
5620             if (crv != CKR_OK)
5621                 break;
5622 
5623             crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
5624                                         sftk_item_expand(&ecEncodedParams));
5625             if (crv != CKR_OK) {
5626                 SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
5627                 break;
5628             }
5629 
5630             /* Decode ec params before calling EC_NewKey */
5631             rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
5632             SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
5633             if (rv != SECSuccess) {
5634                 crv = sftk_MapCryptError(PORT_GetError());
5635                 break;
5636             }
5637             rv = EC_NewKey(ecParams, &ecPriv);
5638             if (rv != SECSuccess) {
5639                 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5640                     sftk_fatalError = PR_TRUE;
5641                 }
5642                 PORT_FreeArena(ecParams->arena, PR_TRUE);
5643                 crv = sftk_MapCryptError(PORT_GetError());
5644                 break;
5645             }
5646 
5647             if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
5648                 ecParams->fieldID.type == ec_field_plain) {
5649                 PORT_FreeArena(ecParams->arena, PR_TRUE);
5650                 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
5651                                             sftk_item_expand(&ecPriv->publicValue));
5652             } else {
5653                 PORT_FreeArena(ecParams->arena, PR_TRUE);
5654                 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
5655                                                        &ecPriv->publicValue,
5656                                                        SEC_ASN1_GET(SEC_OctetStringTemplate));
5657                 if (!pubValue) {
5658                     crv = CKR_ARGUMENTS_BAD;
5659                     goto ecgn_done;
5660                 }
5661                 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
5662                                             sftk_item_expand(pubValue));
5663                 SECITEM_ZfreeItem(pubValue, PR_TRUE);
5664             }
5665             if (crv != CKR_OK)
5666                 goto ecgn_done;
5667 
5668             crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5669                                         sftk_item_expand(&ecPriv->privateValue));
5670             if (crv != CKR_OK)
5671                 goto ecgn_done;
5672 
5673             crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5674                                         sftk_item_expand(&ecPriv->publicValue));
5675         ecgn_done:
5676             /* should zeroize, since this function doesn't. */
5677             PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
5678             break;
5679 
5680         default:
5681             crv = CKR_MECHANISM_INVALID;
5682     }
5683 
5684     if (crv != CKR_OK) {
5685         sftk_FreeObject(privateKey);
5686         sftk_FreeObject(publicKey);
5687         return crv;
5688     }
5689 
5690     /* Add the class, key_type The loop lets us check errors blow out
5691      *  on errors and clean up at the bottom */
5692     session = NULL; /* make pedtantic happy... session cannot leave the*/
5693                     /* loop below NULL unless an error is set... */
5694     do {
5695         crv = sftk_AddAttributeType(privateKey, CKA_CLASS, &privClass,
5696                                     sizeof(CK_OBJECT_CLASS));
5697         if (crv != CKR_OK)
5698             break;
5699         crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &pubClass,
5700                                     sizeof(CK_OBJECT_CLASS));
5701         if (crv != CKR_OK)
5702             break;
5703         crv = sftk_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type,
5704                                     sizeof(CK_KEY_TYPE));
5705         if (crv != CKR_OK)
5706             break;
5707         crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &key_type,
5708                                     sizeof(CK_KEY_TYPE));
5709         if (crv != CKR_OK)
5710             break;
5711         session = sftk_SessionFromHandle(hSession);
5712         if (session == NULL)
5713             crv = CKR_SESSION_HANDLE_INVALID;
5714     } while (0);
5715 
5716     if (crv != CKR_OK) {
5717         sftk_FreeObject(privateKey);
5718         sftk_FreeObject(publicKey);
5719         return crv;
5720     }
5721 
5722     /*
5723      * handle the base object cleanup for the public Key
5724      */
5725     crv = sftk_handleObject(privateKey, session);
5726     if (crv != CKR_OK) {
5727         sftk_FreeSession(session);
5728         sftk_FreeObject(privateKey);
5729         sftk_FreeObject(publicKey);
5730         return crv;
5731     }
5732 
5733     /*
5734      * handle the base object cleanup for the private Key
5735      * If we have any problems, we destroy the public Key we've
5736      * created and linked.
5737      */
5738     crv = sftk_handleObject(publicKey, session);
5739     sftk_FreeSession(session);
5740     if (crv != CKR_OK) {
5741         sftk_FreeObject(publicKey);
5742         NSC_DestroyObject(hSession, privateKey->handle);
5743         sftk_FreeObject(privateKey);
5744         return crv;
5745     }
5746     if (sftk_isTrue(privateKey, CKA_SENSITIVE)) {
5747         crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE,
5748                                   &cktrue, sizeof(CK_BBOOL));
5749     }
5750     if (crv == CKR_OK && sftk_isTrue(publicKey, CKA_SENSITIVE)) {
5751         crv = sftk_forceAttribute(publicKey, CKA_ALWAYS_SENSITIVE,
5752                                   &cktrue, sizeof(CK_BBOOL));
5753     }
5754     if (crv == CKR_OK && !sftk_isTrue(privateKey, CKA_EXTRACTABLE)) {
5755         crv = sftk_forceAttribute(privateKey, CKA_NEVER_EXTRACTABLE,
5756                                   &cktrue, sizeof(CK_BBOOL));
5757     }
5758     if (crv == CKR_OK && !sftk_isTrue(publicKey, CKA_EXTRACTABLE)) {
5759         crv = sftk_forceAttribute(publicKey, CKA_NEVER_EXTRACTABLE,
5760                                   &cktrue, sizeof(CK_BBOOL));
5761     }
5762 
5763     if (crv == CKR_OK) {
5764         /* Perform FIPS 140-2 pairwise consistency check. */
5765         crv = sftk_PairwiseConsistencyCheck(hSession, slot,
5766                                             publicKey, privateKey, key_type);
5767         if (crv != CKR_OK) {
5768             if (sftk_audit_enabled) {
5769                 char msg[128];
5770                 PR_snprintf(msg, sizeof msg,
5771                             "C_GenerateKeyPair(hSession=0x%08lX, "
5772                             "pMechanism->mechanism=0x%08lX)=0x%08lX "
5773                             "self-test: pair-wise consistency test failed",
5774                             (PRUint32)hSession, (PRUint32)pMechanism->mechanism,
5775                             (PRUint32)crv);
5776                 sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg);
5777             }
5778         }
5779     }
5780 
5781     if (crv != CKR_OK) {
5782         NSC_DestroyObject(hSession, publicKey->handle);
5783         sftk_FreeObject(publicKey);
5784         NSC_DestroyObject(hSession, privateKey->handle);
5785         sftk_FreeObject(privateKey);
5786         return crv;
5787     }
5788 
5789     *phPrivateKey = privateKey->handle;
5790     *phPublicKey = publicKey->handle;
5791     sftk_FreeObject(publicKey);
5792     sftk_FreeObject(privateKey);
5793 
5794     return CKR_OK;
5795 }
5796 
5797 static SECItem *
sftk_PackagePrivateKey(SFTKObject * key,CK_RV * crvp)5798 sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp)
5799 {
5800     NSSLOWKEYPrivateKey *lk = NULL;
5801     NSSLOWKEYPrivateKeyInfo *pki = NULL;
5802     SFTKAttribute *attribute = NULL;
5803     PLArenaPool *arena = NULL;
5804     SECOidTag algorithm = SEC_OID_UNKNOWN;
5805     void *dummy, *param = NULL;
5806     SECStatus rv = SECSuccess;
5807     SECItem *encodedKey = NULL;
5808 #ifdef EC_DEBUG
5809     SECItem *fordebug;
5810 #endif
5811     int savelen;
5812 
5813     if (!key) {
5814         *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */
5815         return NULL;
5816     }
5817 
5818     attribute = sftk_FindAttribute(key, CKA_KEY_TYPE);
5819     if (!attribute) {
5820         *crvp = CKR_KEY_TYPE_INCONSISTENT;
5821         return NULL;
5822     }
5823 
5824     lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp);
5825     sftk_FreeAttribute(attribute);
5826     if (!lk) {
5827         return NULL;
5828     }
5829 
5830     arena = PORT_NewArena(2048); /* XXX different size? */
5831     if (!arena) {
5832         *crvp = CKR_HOST_MEMORY;
5833         rv = SECFailure;
5834         goto loser;
5835     }
5836 
5837     pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena,
5838                                                       sizeof(NSSLOWKEYPrivateKeyInfo));
5839     if (!pki) {
5840         *crvp = CKR_HOST_MEMORY;
5841         rv = SECFailure;
5842         goto loser;
5843     }
5844     pki->arena = arena;
5845 
5846     param = NULL;
5847     switch (lk->keyType) {
5848         case NSSLOWKEYRSAKey:
5849             prepare_low_rsa_priv_key_for_asn1(lk);
5850             dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
5851                                        nsslowkey_RSAPrivateKeyTemplate);
5852 
5853             /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */
5854             attribute = sftk_FindAttribute(key, CKA_PUBLIC_KEY_INFO);
5855             if (attribute) {
5856                 NSSLOWKEYSubjectPublicKeyInfo *publicKeyInfo;
5857                 SECItem spki;
5858 
5859                 spki.data = attribute->attrib.pValue;
5860                 spki.len = attribute->attrib.ulValueLen;
5861 
5862                 publicKeyInfo = PORT_ArenaZAlloc(arena,
5863                                                  sizeof(NSSLOWKEYSubjectPublicKeyInfo));
5864                 if (!publicKeyInfo) {
5865                     sftk_FreeAttribute(attribute);
5866                     *crvp = CKR_HOST_MEMORY;
5867                     rv = SECFailure;
5868                     goto loser;
5869                 }
5870                 rv = SEC_QuickDERDecodeItem(arena, publicKeyInfo,
5871                                             nsslowkey_SubjectPublicKeyInfoTemplate,
5872                                             &spki);
5873                 if (rv != SECSuccess) {
5874                     sftk_FreeAttribute(attribute);
5875                     *crvp = CKR_KEY_TYPE_INCONSISTENT;
5876                     goto loser;
5877                 }
5878                 algorithm = SECOID_GetAlgorithmTag(&publicKeyInfo->algorithm);
5879                 if (algorithm != SEC_OID_PKCS1_RSA_ENCRYPTION &&
5880                     algorithm != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
5881                     sftk_FreeAttribute(attribute);
5882                     rv = SECFailure;
5883                     *crvp = CKR_KEY_TYPE_INCONSISTENT;
5884                     goto loser;
5885                 }
5886                 param = SECITEM_DupItem(&publicKeyInfo->algorithm.parameters);
5887                 if (!param) {
5888                     sftk_FreeAttribute(attribute);
5889                     rv = SECFailure;
5890                     *crvp = CKR_HOST_MEMORY;
5891                     goto loser;
5892                 }
5893                 sftk_FreeAttribute(attribute);
5894             } else {
5895                 /* default to PKCS #1 */
5896                 algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
5897             }
5898             break;
5899         case NSSLOWKEYDSAKey:
5900             prepare_low_dsa_priv_key_export_for_asn1(lk);
5901             dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
5902                                        nsslowkey_DSAPrivateKeyExportTemplate);
5903             prepare_low_pqg_params_for_asn1(&lk->u.dsa.params);
5904             param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
5905                                        nsslowkey_PQGParamsTemplate);
5906             algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
5907             break;
5908         case NSSLOWKEYECKey:
5909             prepare_low_ec_priv_key_for_asn1(lk);
5910             /* Public value is encoded as a bit string so adjust length
5911              * to be in bits before ASN encoding and readjust
5912              * immediately after.
5913              *
5914              * Since the SECG specification recommends not including the
5915              * parameters as part of ECPrivateKey, we zero out the curveOID
5916              * length before encoding and restore it later.
5917              */
5918             lk->u.ec.publicValue.len <<= 3;
5919             savelen = lk->u.ec.ecParams.curveOID.len;
5920             lk->u.ec.ecParams.curveOID.len = 0;
5921             dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
5922                                        nsslowkey_ECPrivateKeyTemplate);
5923             lk->u.ec.ecParams.curveOID.len = savelen;
5924             lk->u.ec.publicValue.len >>= 3;
5925 
5926 #ifdef EC_DEBUG
5927             fordebug = &pki->privateKey;
5928             SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType,
5929                       fordebug);
5930 #endif
5931 
5932             param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding);
5933 
5934             algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
5935             break;
5936         case NSSLOWKEYDHKey:
5937         default:
5938             dummy = NULL;
5939             break;
5940     }
5941 
5942     if (!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) {
5943         *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
5944         rv = SECFailure;
5945         goto loser;
5946     }
5947 
5948     rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm,
5949                                (SECItem *)param);
5950     if (rv != SECSuccess) {
5951         *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
5952         rv = SECFailure;
5953         goto loser;
5954     }
5955 
5956     dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
5957                                   NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
5958     if (!dummy) {
5959         *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
5960         rv = SECFailure;
5961         goto loser;
5962     }
5963 
5964     encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
5965                                     nsslowkey_PrivateKeyInfoTemplate);
5966     *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR;
5967 
5968 #ifdef EC_DEBUG
5969     fordebug = encodedKey;
5970     SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType,
5971               fordebug);
5972 #endif
5973 loser:
5974     if (arena) {
5975         PORT_FreeArena(arena, PR_TRUE);
5976     }
5977 
5978     if (lk && (lk != key->objectInfo)) {
5979         nsslowkey_DestroyPrivateKey(lk);
5980     }
5981 
5982     if (param) {
5983         SECITEM_ZfreeItem((SECItem *)param, PR_TRUE);
5984     }
5985 
5986     if (rv != SECSuccess) {
5987         return NULL;
5988     }
5989 
5990     return encodedKey;
5991 }
5992 
5993 /* it doesn't matter yet, since we colapse error conditions in the
5994  * level above, but we really should map those few key error differences */
5995 static CK_RV
sftk_mapWrap(CK_RV crv)5996 sftk_mapWrap(CK_RV crv)
5997 {
5998     switch (crv) {
5999         case CKR_ENCRYPTED_DATA_INVALID:
6000             crv = CKR_WRAPPED_KEY_INVALID;
6001             break;
6002     }
6003     return crv;
6004 }
6005 
6006 /* NSC_WrapKey wraps (i.e., encrypts) a key. */
6007 CK_RV
NSC_WrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hWrappingKey,CK_OBJECT_HANDLE hKey,CK_BYTE_PTR pWrappedKey,CK_ULONG_PTR pulWrappedKeyLen)6008 NSC_WrapKey(CK_SESSION_HANDLE hSession,
6009             CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
6010             CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
6011             CK_ULONG_PTR pulWrappedKeyLen)
6012 {
6013     SFTKSession *session;
6014     SFTKAttribute *attribute;
6015     SFTKObject *key;
6016     CK_RV crv;
6017 
6018     CHECK_FORK();
6019 
6020     session = sftk_SessionFromHandle(hSession);
6021     if (session == NULL) {
6022         return CKR_SESSION_HANDLE_INVALID;
6023     }
6024 
6025     key = sftk_ObjectFromHandle(hKey, session);
6026     if (key == NULL) {
6027         sftk_FreeSession(session);
6028         return CKR_KEY_HANDLE_INVALID;
6029     }
6030 
6031     switch (key->objclass) {
6032         case CKO_SECRET_KEY: {
6033             SFTKSessionContext *context = NULL;
6034             SECItem pText;
6035 
6036             attribute = sftk_FindAttribute(key, CKA_VALUE);
6037 
6038             if (attribute == NULL) {
6039                 crv = CKR_KEY_TYPE_INCONSISTENT;
6040                 break;
6041             }
6042             crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
6043                                  CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
6044             if (crv != CKR_OK) {
6045                 sftk_FreeAttribute(attribute);
6046                 break;
6047             }
6048 
6049             pText.type = siBuffer;
6050             pText.data = (unsigned char *)attribute->attrib.pValue;
6051             pText.len = attribute->attrib.ulValueLen;
6052 
6053             /* Find out if this is a block cipher. */
6054             crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, NULL);
6055             if (crv != CKR_OK || !context)
6056                 break;
6057             if (context->blockSize > 1) {
6058                 unsigned int remainder = pText.len % context->blockSize;
6059                 if (!context->doPad && remainder) {
6060                     /* When wrapping secret keys with unpadded block ciphers,
6061                     ** the keys are zero padded, if necessary, to fill out
6062                     ** a full block.
6063                     */
6064                     pText.len += context->blockSize - remainder;
6065                     pText.data = PORT_ZAlloc(pText.len);
6066                     if (pText.data)
6067                         memcpy(pText.data, attribute->attrib.pValue,
6068                                attribute->attrib.ulValueLen);
6069                     else {
6070                         crv = CKR_HOST_MEMORY;
6071                         break;
6072                     }
6073                 }
6074             }
6075 
6076             crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data,
6077                               pText.len, pWrappedKey, pulWrappedKeyLen);
6078             /* always force a finalize, both on errors and when
6079              * we are just getting the size */
6080             if (crv != CKR_OK || pWrappedKey == NULL) {
6081                 CK_RV lcrv;
6082                 lcrv = sftk_GetContext(hSession, &context,
6083                                        SFTK_ENCRYPT, PR_FALSE, NULL);
6084                 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
6085                 if (lcrv == CKR_OK && context) {
6086                     sftk_FreeContext(context);
6087                 }
6088             }
6089 
6090             if (pText.data != (unsigned char *)attribute->attrib.pValue)
6091                 PORT_ZFree(pText.data, pText.len);
6092             sftk_FreeAttribute(attribute);
6093             break;
6094         }
6095 
6096         case CKO_PRIVATE_KEY: {
6097             SECItem *bpki = sftk_PackagePrivateKey(key, &crv);
6098             SFTKSessionContext *context = NULL;
6099 
6100             if (!bpki) {
6101                 break;
6102             }
6103 
6104             crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
6105                                  CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
6106             if (crv != CKR_OK) {
6107                 SECITEM_ZfreeItem(bpki, PR_TRUE);
6108                 crv = CKR_KEY_TYPE_INCONSISTENT;
6109                 break;
6110             }
6111 
6112             crv = NSC_Encrypt(hSession, bpki->data, bpki->len,
6113                               pWrappedKey, pulWrappedKeyLen);
6114             /* always force a finalize */
6115             if (crv != CKR_OK || pWrappedKey == NULL) {
6116                 CK_RV lcrv;
6117                 lcrv = sftk_GetContext(hSession, &context,
6118                                        SFTK_ENCRYPT, PR_FALSE, NULL);
6119                 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
6120                 if (lcrv == CKR_OK && context) {
6121                     sftk_FreeContext(context);
6122                 }
6123             }
6124             SECITEM_ZfreeItem(bpki, PR_TRUE);
6125             break;
6126         }
6127 
6128         default:
6129             crv = CKR_KEY_TYPE_INCONSISTENT;
6130             break;
6131     }
6132     sftk_FreeObject(key);
6133     sftk_FreeSession(session);
6134     return sftk_mapWrap(crv);
6135 }
6136 
6137 /*
6138  * import a pprivate key info into the desired slot
6139  */
6140 static SECStatus
sftk_unwrapPrivateKey(SFTKObject * key,SECItem * bpki)6141 sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
6142 {
6143     CK_BBOOL cktrue = CK_TRUE;
6144     CK_KEY_TYPE keyType = CKK_RSA;
6145     SECStatus rv = SECFailure;
6146     const SEC_ASN1Template *keyTemplate, *paramTemplate;
6147     void *paramDest = NULL;
6148     PLArenaPool *arena;
6149     NSSLOWKEYPrivateKey *lpk = NULL;
6150     NSSLOWKEYPrivateKeyInfo *pki = NULL;
6151     CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
6152 
6153     arena = PORT_NewArena(2048);
6154     if (!arena) {
6155         return SECFailure;
6156     }
6157 
6158     pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena,
6159                                                       sizeof(NSSLOWKEYPrivateKeyInfo));
6160     if (!pki) {
6161         PORT_FreeArena(arena, PR_FALSE);
6162         return SECFailure;
6163     }
6164 
6165     if (SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) {
6166         PORT_FreeArena(arena, PR_TRUE);
6167         return SECFailure;
6168     }
6169 
6170     lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena,
6171                                                   sizeof(NSSLOWKEYPrivateKey));
6172     if (lpk == NULL) {
6173         goto loser;
6174     }
6175     lpk->arena = arena;
6176 
6177     switch (SECOID_GetAlgorithmTag(&pki->algorithm)) {
6178         case SEC_OID_PKCS1_RSA_ENCRYPTION:
6179         case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
6180             keyTemplate = nsslowkey_RSAPrivateKeyTemplate;
6181             paramTemplate = NULL;
6182             paramDest = NULL;
6183             lpk->keyType = NSSLOWKEYRSAKey;
6184             prepare_low_rsa_priv_key_for_asn1(lpk);
6185             break;
6186         case SEC_OID_ANSIX9_DSA_SIGNATURE:
6187             keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate;
6188             paramTemplate = nsslowkey_PQGParamsTemplate;
6189             paramDest = &(lpk->u.dsa.params);
6190             lpk->keyType = NSSLOWKEYDSAKey;
6191             prepare_low_dsa_priv_key_export_for_asn1(lpk);
6192             prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params);
6193             break;
6194         /* case NSSLOWKEYDHKey: */
6195         case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
6196             keyTemplate = nsslowkey_ECPrivateKeyTemplate;
6197             paramTemplate = NULL;
6198             paramDest = &(lpk->u.ec.ecParams.DEREncoding);
6199             lpk->keyType = NSSLOWKEYECKey;
6200             prepare_low_ec_priv_key_for_asn1(lpk);
6201             prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams);
6202             break;
6203         default:
6204             keyTemplate = NULL;
6205             paramTemplate = NULL;
6206             paramDest = NULL;
6207             break;
6208     }
6209 
6210     if (!keyTemplate) {
6211         goto loser;
6212     }
6213 
6214     /* decode the private key and any algorithm parameters */
6215     rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
6216 
6217     if (lpk->keyType == NSSLOWKEYECKey) {
6218         /* convert length in bits to length in bytes */
6219         lpk->u.ec.publicValue.len >>= 3;
6220         rv = SECITEM_CopyItem(arena,
6221                               &(lpk->u.ec.ecParams.DEREncoding),
6222                               &(pki->algorithm.parameters));
6223         if (rv != SECSuccess) {
6224             goto loser;
6225         }
6226     }
6227 
6228     if (rv != SECSuccess) {
6229         goto loser;
6230     }
6231     if (paramDest && paramTemplate) {
6232         rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate,
6233                                     &(pki->algorithm.parameters));
6234         if (rv != SECSuccess) {
6235             goto loser;
6236         }
6237     }
6238 
6239     rv = SECFailure;
6240 
6241     switch (lpk->keyType) {
6242         case NSSLOWKEYRSAKey:
6243             keyType = CKK_RSA;
6244             if (sftk_hasAttribute(key, CKA_NSS_DB)) {
6245                 sftk_DeleteAttributeType(key, CKA_NSS_DB);
6246             }
6247             crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6248                                         sizeof(keyType));
6249             if (crv != CKR_OK)
6250                 break;
6251             crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue,
6252                                         sizeof(CK_BBOOL));
6253             if (crv != CKR_OK)
6254                 break;
6255             crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue,
6256                                         sizeof(CK_BBOOL));
6257             if (crv != CKR_OK)
6258                 break;
6259             crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6260                                         sizeof(CK_BBOOL));
6261             if (crv != CKR_OK)
6262                 break;
6263             crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6264                                         sizeof(CK_BBOOL));
6265             if (crv != CKR_OK)
6266                 break;
6267             crv = sftk_AddAttributeType(key, CKA_MODULUS,
6268                                         sftk_item_expand(&lpk->u.rsa.modulus));
6269             if (crv != CKR_OK)
6270                 break;
6271             crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT,
6272                                         sftk_item_expand(&lpk->u.rsa.publicExponent));
6273             if (crv != CKR_OK)
6274                 break;
6275             crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT,
6276                                         sftk_item_expand(&lpk->u.rsa.privateExponent));
6277             if (crv != CKR_OK)
6278                 break;
6279             crv = sftk_AddAttributeType(key, CKA_PRIME_1,
6280                                         sftk_item_expand(&lpk->u.rsa.prime1));
6281             if (crv != CKR_OK)
6282                 break;
6283             crv = sftk_AddAttributeType(key, CKA_PRIME_2,
6284                                         sftk_item_expand(&lpk->u.rsa.prime2));
6285             if (crv != CKR_OK)
6286                 break;
6287             crv = sftk_AddAttributeType(key, CKA_EXPONENT_1,
6288                                         sftk_item_expand(&lpk->u.rsa.exponent1));
6289             if (crv != CKR_OK)
6290                 break;
6291             crv = sftk_AddAttributeType(key, CKA_EXPONENT_2,
6292                                         sftk_item_expand(&lpk->u.rsa.exponent2));
6293             if (crv != CKR_OK)
6294                 break;
6295             crv = sftk_AddAttributeType(key, CKA_COEFFICIENT,
6296                                         sftk_item_expand(&lpk->u.rsa.coefficient));
6297             break;
6298         case NSSLOWKEYDSAKey:
6299             keyType = CKK_DSA;
6300             crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
6301             if (crv != CKR_OK)
6302                 break;
6303             crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6304                                         sizeof(keyType));
6305             if (crv != CKR_OK)
6306                 break;
6307             crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6308                                         sizeof(CK_BBOOL));
6309             if (crv != CKR_OK)
6310                 break;
6311             crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6312                                         sizeof(CK_BBOOL));
6313             if (crv != CKR_OK)
6314                 break;
6315             crv = sftk_AddAttributeType(key, CKA_PRIME,
6316                                         sftk_item_expand(&lpk->u.dsa.params.prime));
6317             if (crv != CKR_OK)
6318                 break;
6319             crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
6320                                         sftk_item_expand(&lpk->u.dsa.params.subPrime));
6321             if (crv != CKR_OK)
6322                 break;
6323             crv = sftk_AddAttributeType(key, CKA_BASE,
6324                                         sftk_item_expand(&lpk->u.dsa.params.base));
6325             if (crv != CKR_OK)
6326                 break;
6327             crv = sftk_AddAttributeType(key, CKA_VALUE,
6328                                         sftk_item_expand(&lpk->u.dsa.privateValue));
6329             if (crv != CKR_OK)
6330                 break;
6331             break;
6332 #ifdef notdef
6333         case NSSLOWKEYDHKey:
6334             template = dhTemplate;
6335             templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE);
6336             keyType = CKK_DH;
6337             break;
6338 #endif
6339         /* what about fortezza??? */
6340         case NSSLOWKEYECKey:
6341             keyType = CKK_EC;
6342             crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
6343             if (crv != CKR_OK)
6344                 break;
6345             crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6346                                         sizeof(keyType));
6347             if (crv != CKR_OK)
6348                 break;
6349             crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6350                                         sizeof(CK_BBOOL));
6351             if (crv != CKR_OK)
6352                 break;
6353             crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6354                                         sizeof(CK_BBOOL));
6355             if (crv != CKR_OK)
6356                 break;
6357             crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue,
6358                                         sizeof(CK_BBOOL));
6359             if (crv != CKR_OK)
6360                 break;
6361             crv = sftk_AddAttributeType(key, CKA_EC_PARAMS,
6362                                         sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding));
6363             if (crv != CKR_OK)
6364                 break;
6365             crv = sftk_AddAttributeType(key, CKA_VALUE,
6366                                         sftk_item_expand(&lpk->u.ec.privateValue));
6367             if (crv != CKR_OK)
6368                 break;
6369             /* XXX Do we need to decode the EC Params here ?? */
6370             break;
6371         default:
6372             crv = CKR_KEY_TYPE_INCONSISTENT;
6373             break;
6374     }
6375 
6376     if (crv != CKR_OK) {
6377         goto loser;
6378     }
6379 
6380     /* For RSA-PSS, record the original algorithm parameters so
6381      * they can be encrypted altoghether when wrapping */
6382     if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
6383         NSSLOWKEYSubjectPublicKeyInfo spki;
6384         NSSLOWKEYPublicKey pubk;
6385         SECItem *publicKeyInfo;
6386 
6387         memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo));
6388         rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm);
6389         if (rv != SECSuccess) {
6390             crv = CKR_HOST_MEMORY;
6391             goto loser;
6392         }
6393 
6394         prepare_low_rsa_pub_key_for_asn1(&pubk);
6395 
6396         rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus);
6397         if (rv != SECSuccess) {
6398             crv = CKR_HOST_MEMORY;
6399             goto loser;
6400         }
6401         rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent);
6402         if (rv != SECSuccess) {
6403             crv = CKR_HOST_MEMORY;
6404             goto loser;
6405         }
6406 
6407         if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey,
6408                                &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) {
6409             crv = CKR_HOST_MEMORY;
6410             goto loser;
6411         }
6412 
6413         publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL,
6414                                            &spki, nsslowkey_SubjectPublicKeyInfoTemplate);
6415         if (!publicKeyInfo) {
6416             crv = CKR_HOST_MEMORY;
6417             goto loser;
6418         }
6419         crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO,
6420                                     sftk_item_expand(publicKeyInfo));
6421     }
6422 
6423 loser:
6424     if (lpk) {
6425         nsslowkey_DestroyPrivateKey(lpk);
6426     }
6427 
6428     if (crv != CKR_OK) {
6429         return SECFailure;
6430     }
6431 
6432     return SECSuccess;
6433 }
6434 
6435 /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
6436 CK_RV
NSC_UnwrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hUnwrappingKey,CK_BYTE_PTR pWrappedKey,CK_ULONG ulWrappedKeyLen,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)6437 NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
6438               CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
6439               CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
6440               CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
6441               CK_OBJECT_HANDLE_PTR phKey)
6442 {
6443     SFTKObject *key = NULL;
6444     SFTKSession *session;
6445     CK_ULONG key_length = 0;
6446     unsigned char *buf = NULL;
6447     CK_RV crv = CKR_OK;
6448     int i;
6449     CK_ULONG bsize = ulWrappedKeyLen;
6450     SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
6451     SECItem bpki;
6452     CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
6453 
6454     CHECK_FORK();
6455 
6456     if (!slot) {
6457         return CKR_SESSION_HANDLE_INVALID;
6458     }
6459     /*
6460      * now lets create an object to hang the attributes off of
6461      */
6462     key = sftk_NewObject(slot); /* fill in the handle later */
6463     if (key == NULL) {
6464         return CKR_HOST_MEMORY;
6465     }
6466 
6467     /*
6468      * load the template values into the object
6469      */
6470     for (i = 0; i < (int)ulAttributeCount; i++) {
6471         if (pTemplate[i].type == CKA_VALUE_LEN) {
6472             key_length = *(CK_ULONG *)pTemplate[i].pValue;
6473             continue;
6474         }
6475         if (pTemplate[i].type == CKA_CLASS) {
6476             target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
6477         }
6478         crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
6479         if (crv != CKR_OK)
6480             break;
6481     }
6482     if (crv != CKR_OK) {
6483         sftk_FreeObject(key);
6484         return crv;
6485     }
6486 
6487     crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP,
6488                          CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE);
6489     if (crv != CKR_OK) {
6490         sftk_FreeObject(key);
6491         return sftk_mapWrap(crv);
6492     }
6493 
6494     /* allocate the buffer to decrypt into
6495      * this assumes the unwrapped key is never larger than the
6496      * wrapped key. For all the mechanisms we support this is true */
6497     buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen);
6498     bsize = ulWrappedKeyLen;
6499 
6500     crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
6501     if (crv != CKR_OK) {
6502         sftk_FreeObject(key);
6503         PORT_Free(buf);
6504         return sftk_mapWrap(crv);
6505     }
6506 
6507     switch (target_type) {
6508         case CKO_SECRET_KEY:
6509             if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) {
6510                 crv = CKR_TEMPLATE_INCOMPLETE;
6511                 break;
6512             }
6513 
6514             if (key_length == 0 || key_length > bsize) {
6515                 key_length = bsize;
6516             }
6517             if (key_length > MAX_KEY_LEN) {
6518                 crv = CKR_TEMPLATE_INCONSISTENT;
6519                 break;
6520             }
6521 
6522             /* add the value */
6523             crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
6524             break;
6525         case CKO_PRIVATE_KEY:
6526             bpki.data = (unsigned char *)buf;
6527             bpki.len = bsize;
6528             crv = CKR_OK;
6529             if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) {
6530                 crv = CKR_TEMPLATE_INCOMPLETE;
6531             }
6532             break;
6533         default:
6534             crv = CKR_TEMPLATE_INCONSISTENT;
6535             break;
6536     }
6537 
6538     PORT_ZFree(buf, bsize);
6539     if (crv != CKR_OK) {
6540         sftk_FreeObject(key);
6541         return crv;
6542     }
6543 
6544     /* get the session */
6545     session = sftk_SessionFromHandle(hSession);
6546     if (session == NULL) {
6547         sftk_FreeObject(key);
6548         return CKR_SESSION_HANDLE_INVALID;
6549     }
6550 
6551     /* mark the key as FIPS if the previous operation was all FIPS */
6552     key->isFIPS = session->lastOpWasFIPS;
6553 
6554     /*
6555      * handle the base object stuff
6556      */
6557     crv = sftk_handleObject(key, session);
6558     *phKey = key->handle;
6559     sftk_FreeSession(session);
6560     sftk_FreeObject(key);
6561 
6562     return crv;
6563 }
6564 
6565 /*
6566  * The SSL key gen mechanism create's lots of keys. This function handles the
6567  * details of each of these key creation.
6568  */
6569 static CK_RV
sftk_buildSSLKey(CK_SESSION_HANDLE hSession,SFTKObject * baseKey,PRBool isMacKey,unsigned char * keyBlock,unsigned int keySize,CK_OBJECT_HANDLE * keyHandle)6570 sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey,
6571                  PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
6572                  CK_OBJECT_HANDLE *keyHandle)
6573 {
6574     SFTKObject *key;
6575     SFTKSession *session;
6576     CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
6577     CK_BBOOL cktrue = CK_TRUE;
6578     CK_BBOOL ckfalse = CK_FALSE;
6579     CK_RV crv = CKR_HOST_MEMORY;
6580 
6581     /*
6582      * now lets create an object to hang the attributes off of
6583      */
6584     *keyHandle = CK_INVALID_HANDLE;
6585     key = sftk_NewObject(baseKey->slot);
6586     if (key == NULL)
6587         return CKR_HOST_MEMORY;
6588     sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE;
6589 
6590     crv = sftk_CopyObject(key, baseKey);
6591     if (crv != CKR_OK)
6592         goto loser;
6593     if (isMacKey) {
6594         crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
6595         if (crv != CKR_OK)
6596             goto loser;
6597         crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
6598         if (crv != CKR_OK)
6599             goto loser;
6600         crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL));
6601         if (crv != CKR_OK)
6602             goto loser;
6603         crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL));
6604         if (crv != CKR_OK)
6605             goto loser;
6606         crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
6607         if (crv != CKR_OK)
6608             goto loser;
6609         crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
6610         if (crv != CKR_OK)
6611             goto loser;
6612         crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL));
6613         if (crv != CKR_OK)
6614             goto loser;
6615         crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL));
6616         if (crv != CKR_OK)
6617             goto loser;
6618     }
6619     crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize);
6620     if (crv != CKR_OK)
6621         goto loser;
6622 
6623     /* get the session */
6624     crv = CKR_HOST_MEMORY;
6625     session = sftk_SessionFromHandle(hSession);
6626     if (session == NULL) {
6627         goto loser;
6628     }
6629 
6630     crv = sftk_handleObject(key, session);
6631     sftk_FreeSession(session);
6632     *keyHandle = key->handle;
6633 loser:
6634     if (key)
6635         sftk_FreeObject(key);
6636     return crv;
6637 }
6638 
6639 /*
6640  * if there is an error, we need to free the keys we already created in SSL
6641  * This is the routine that will do it..
6642  */
6643 static void
sftk_freeSSLKeys(CK_SESSION_HANDLE session,CK_SSL3_KEY_MAT_OUT * returnedMaterial)6644 sftk_freeSSLKeys(CK_SESSION_HANDLE session,
6645                  CK_SSL3_KEY_MAT_OUT *returnedMaterial)
6646 {
6647     if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) {
6648         NSC_DestroyObject(session, returnedMaterial->hClientMacSecret);
6649     }
6650     if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) {
6651         NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
6652     }
6653     if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) {
6654         NSC_DestroyObject(session, returnedMaterial->hClientKey);
6655     }
6656     if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) {
6657         NSC_DestroyObject(session, returnedMaterial->hServerKey);
6658     }
6659 }
6660 
6661 /*
6662  * when deriving from sensitive and extractable keys, we need to preserve some
6663  * of the semantics in the derived key. This helper routine maintains these
6664  * semantics.
6665  */
6666 static CK_RV
sftk_DeriveSensitiveCheck(SFTKObject * baseKey,SFTKObject * destKey,PRBool canBeData)6667 sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey,
6668                           PRBool canBeData)
6669 {
6670     PRBool hasSensitive;
6671     PRBool sensitive = PR_FALSE;
6672     CK_BBOOL bFalse = CK_FALSE;
6673     PRBool hasExtractable;
6674     PRBool extractable = PR_TRUE;
6675     CK_BBOOL bTrue = CK_TRUE;
6676     CK_RV crv = CKR_OK;
6677     SFTKAttribute *att;
6678     PRBool isData = PR_TRUE;
6679 
6680     if (canBeData) {
6681         CK_OBJECT_CLASS objClass;
6682 
6683         /* if the target key is actually data, don't set the unexpected
6684          * attributes */
6685         crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass);
6686         if (crv != CKR_OK) {
6687             return crv;
6688         }
6689         if (objClass == CKO_DATA) {
6690             return CKR_OK;
6691         }
6692 
6693         /* if the base key is data, it doesn't have sensitive attributes,
6694          * allow the destKey to get it's own */
6695         crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass);
6696         if (crv != CKR_OK) {
6697             return crv;
6698         }
6699         if (objClass == CKO_DATA) {
6700             isData = PR_TRUE;
6701         }
6702     }
6703 
6704     hasSensitive = PR_FALSE;
6705     att = sftk_FindAttribute(destKey, CKA_SENSITIVE);
6706     if (att) {
6707         hasSensitive = PR_TRUE;
6708         sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
6709         sftk_FreeAttribute(att);
6710     }
6711 
6712     hasExtractable = PR_FALSE;
6713     att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE);
6714     if (att) {
6715         hasExtractable = PR_TRUE;
6716         extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
6717         sftk_FreeAttribute(att);
6718     }
6719 
6720     /* don't make a key more accessible */
6721     if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive &&
6722         (sensitive == PR_FALSE)) {
6723         return CKR_KEY_FUNCTION_NOT_PERMITTED;
6724     }
6725     if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable &&
6726         (extractable == PR_TRUE)) {
6727         return CKR_KEY_FUNCTION_NOT_PERMITTED;
6728     }
6729 
6730     /* inherit parent's sensitivity */
6731     if (!hasSensitive) {
6732         att = sftk_FindAttribute(baseKey, CKA_SENSITIVE);
6733         if (att != NULL) {
6734             crv = sftk_defaultAttribute(destKey,
6735                                         sftk_attr_expand(&att->attrib));
6736             sftk_FreeAttribute(att);
6737         } else if (isData) {
6738             crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE,
6739                                         &bFalse, sizeof(bFalse));
6740         } else {
6741             return CKR_KEY_TYPE_INCONSISTENT;
6742         }
6743         if (crv != CKR_OK)
6744             return crv;
6745     }
6746     if (!hasExtractable) {
6747         att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE);
6748         if (att != NULL) {
6749             crv = sftk_defaultAttribute(destKey,
6750                                         sftk_attr_expand(&att->attrib));
6751             sftk_FreeAttribute(att);
6752         } else if (isData) {
6753             crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE,
6754                                         &bTrue, sizeof(bTrue));
6755         } else {
6756             return CKR_KEY_TYPE_INCONSISTENT;
6757         }
6758         if (crv != CKR_OK)
6759             return crv;
6760     }
6761 
6762     /* we should inherit the parent's always extractable/ never sensitive info,
6763      * but handleObject always forces this attributes, so we would need to do
6764      * something special. */
6765     return CKR_OK;
6766 }
6767 
6768 /*
6769  * make known fixed PKCS #11 key types to their sizes in bytes
6770  */
6771 unsigned long
sftk_MapKeySize(CK_KEY_TYPE keyType)6772 sftk_MapKeySize(CK_KEY_TYPE keyType)
6773 {
6774     switch (keyType) {
6775         case CKK_CDMF:
6776             return 8;
6777         case CKK_DES:
6778             return 8;
6779         case CKK_DES2:
6780             return 16;
6781         case CKK_DES3:
6782             return 24;
6783         /* IDEA and CAST need to be added */
6784         default:
6785             break;
6786     }
6787     return 0;
6788 }
6789 
6790 /* Inputs:
6791  *  key_len: Length of derived key to be generated.
6792  *  SharedSecret: a shared secret that is the output of a key agreement primitive.
6793  *  SharedInfo: (Optional) some data shared by the entities computing the secret key.
6794  *  SharedInfoLen: the length in octets of SharedInfo
6795  *  Hash: The hash function to be used in the KDF
6796  *  HashLen: the length in octets of the output of Hash
6797  * Output:
6798  *  key: Pointer to a buffer containing derived key, if return value is SECSuccess.
6799  */
6800 static CK_RV
sftk_compute_ANSI_X9_63_kdf(CK_BYTE ** key,CK_ULONG key_len,SECItem * SharedSecret,CK_BYTE_PTR SharedInfo,CK_ULONG SharedInfoLen,SECStatus Hash (unsigned char *,const unsigned char *,PRUint32),CK_ULONG HashLen)6801 sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret,
6802                             CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
6803                             SECStatus Hash(unsigned char *, const unsigned char *, PRUint32),
6804                             CK_ULONG HashLen)
6805 {
6806     unsigned char *buffer = NULL, *output_buffer = NULL;
6807     PRUint32 buffer_len, max_counter, i;
6808     SECStatus rv;
6809     CK_RV crv;
6810 
6811     /* Check that key_len isn't too long.  The maximum key length could be
6812      * greatly increased if the code below did not limit the 4-byte counter
6813      * to a maximum value of 255. */
6814     if (key_len > 254 * HashLen)
6815         return CKR_ARGUMENTS_BAD;
6816 
6817     if (SharedInfo == NULL)
6818         SharedInfoLen = 0;
6819 
6820     buffer_len = SharedSecret->len + 4 + SharedInfoLen;
6821     buffer = (CK_BYTE *)PORT_Alloc(buffer_len);
6822     if (buffer == NULL) {
6823         crv = CKR_HOST_MEMORY;
6824         goto loser;
6825     }
6826 
6827     max_counter = key_len / HashLen;
6828     if (key_len > max_counter * HashLen)
6829         max_counter++;
6830 
6831     output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen);
6832     if (output_buffer == NULL) {
6833         crv = CKR_HOST_MEMORY;
6834         goto loser;
6835     }
6836 
6837     /* Populate buffer with SharedSecret || Counter || [SharedInfo]
6838      * where Counter is 0x00000001 */
6839     PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len);
6840     buffer[SharedSecret->len] = 0;
6841     buffer[SharedSecret->len + 1] = 0;
6842     buffer[SharedSecret->len + 2] = 0;
6843     buffer[SharedSecret->len + 3] = 1;
6844     if (SharedInfo) {
6845         PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen);
6846     }
6847 
6848     for (i = 0; i < max_counter; i++) {
6849         rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len);
6850         if (rv != SECSuccess) {
6851             /* 'Hash' should not fail. */
6852             crv = CKR_FUNCTION_FAILED;
6853             goto loser;
6854         }
6855 
6856         /* Increment counter (assumes max_counter < 255) */
6857         buffer[SharedSecret->len + 3]++;
6858     }
6859 
6860     PORT_ZFree(buffer, buffer_len);
6861     if (key_len < max_counter * HashLen) {
6862         PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len);
6863     }
6864     *key = output_buffer;
6865 
6866     return CKR_OK;
6867 
6868 loser:
6869     if (buffer) {
6870         PORT_ZFree(buffer, buffer_len);
6871     }
6872     if (output_buffer) {
6873         PORT_ZFree(output_buffer, max_counter * HashLen);
6874     }
6875     return crv;
6876 }
6877 
6878 static CK_RV
sftk_ANSI_X9_63_kdf(CK_BYTE ** key,CK_ULONG key_len,SECItem * SharedSecret,CK_BYTE_PTR SharedInfo,CK_ULONG SharedInfoLen,CK_EC_KDF_TYPE kdf)6879 sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len,
6880                     SECItem *SharedSecret,
6881                     CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
6882                     CK_EC_KDF_TYPE kdf)
6883 {
6884     if (kdf == CKD_SHA1_KDF)
6885         return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
6886                                            SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH);
6887     else if (kdf == CKD_SHA224_KDF)
6888         return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
6889                                            SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH);
6890     else if (kdf == CKD_SHA256_KDF)
6891         return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
6892                                            SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH);
6893     else if (kdf == CKD_SHA384_KDF)
6894         return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
6895                                            SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH);
6896     else if (kdf == CKD_SHA512_KDF)
6897         return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
6898                                            SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH);
6899     else
6900         return CKR_MECHANISM_INVALID;
6901 }
6902 
6903 /*
6904  *  Handle the derive from a block encryption cipher
6905  */
6906 CK_RV
sftk_DeriveEncrypt(SFTKCipher encrypt,void * cipherInfo,int blockSize,SFTKObject * key,CK_ULONG keySize,unsigned char * data,CK_ULONG len)6907 sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo,
6908                    int blockSize, SFTKObject *key, CK_ULONG keySize,
6909                    unsigned char *data, CK_ULONG len)
6910 {
6911     /* large enough for a 512-bit key */
6912     unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE];
6913     SECStatus rv;
6914     unsigned int outLen;
6915     CK_RV crv;
6916 
6917     if ((len % blockSize) != 0) {
6918         return CKR_MECHANISM_PARAM_INVALID;
6919     }
6920     if (len > SFTK_MAX_DERIVE_KEY_SIZE) {
6921         return CKR_MECHANISM_PARAM_INVALID;
6922     }
6923     if (keySize && (len < keySize)) {
6924         return CKR_MECHANISM_PARAM_INVALID;
6925     }
6926     if (keySize == 0) {
6927         keySize = len;
6928     }
6929 
6930     rv = (*encrypt)(cipherInfo, &tmpdata, &outLen, len, data, len);
6931     if (rv != SECSuccess) {
6932         crv = sftk_MapCryptError(PORT_GetError());
6933         return crv;
6934     }
6935 
6936     crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize);
6937     PORT_Memset(tmpdata, 0, sizeof tmpdata);
6938     return crv;
6939 }
6940 
6941 CK_RV
sftk_HKDF(CK_HKDF_PARAMS_PTR params,CK_SESSION_HANDLE hSession,SFTKObject * sourceKey,const unsigned char * sourceKeyBytes,int sourceKeyLen,SFTKObject * key,unsigned char * outKeyBytes,int keySize,PRBool canBeData,PRBool isFIPS)6942 sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession,
6943           SFTKObject *sourceKey, const unsigned char *sourceKeyBytes,
6944           int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes,
6945           int keySize, PRBool canBeData, PRBool isFIPS)
6946 {
6947     SFTKSession *session;
6948     SFTKAttribute *saltKey_att = NULL;
6949     const SECHashObject *rawHash;
6950     unsigned hashLen;
6951     unsigned genLen = 0;
6952     unsigned char hashbuf[HASH_LENGTH_MAX];
6953     unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH];
6954     unsigned char *keyBlockAlloc = NULL;    /* allocated keyBlock */
6955     unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */
6956     const unsigned char *prk;               /* psuedo-random key */
6957     CK_ULONG prkLen;
6958     const unsigned char *okm; /* output keying material */
6959     HASH_HashType hashType = GetHashTypeFromMechanism(params->prfHashMechanism);
6960     SFTKObject *saltKey = NULL;
6961     CK_RV crv = CKR_OK;
6962 
6963     /* Spec says it should be the base hash, but also accept the HMAC */
6964     if (hashType == HASH_AlgNULL) {
6965         hashType = sftk_HMACMechanismToHash(params->prfHashMechanism);
6966     }
6967     rawHash = HASH_GetRawHashObject(hashType);
6968     if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) {
6969         return CKR_MECHANISM_INVALID;
6970     }
6971     hashLen = rawHash->length;
6972 
6973     if ((!params->bExpand && !params->bExtract) ||
6974         (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
6975         (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
6976         return CKR_MECHANISM_PARAM_INVALID;
6977     }
6978     if ((params->bExpand && keySize == 0) ||
6979         (!params->bExpand && keySize > hashLen) ||
6980         (params->bExpand && keySize > 255 * hashLen)) {
6981         return CKR_TEMPLATE_INCONSISTENT;
6982     }
6983 
6984     /* sourceKey is NULL if we are called from the POST, skip the
6985      * sensitiveCheck */
6986     if (sourceKey != NULL) {
6987         crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData);
6988         if (crv != CKR_OK)
6989             return crv;
6990     }
6991 
6992     /* HKDF-Extract(salt, base key value) */
6993     if (params->bExtract) {
6994         CK_BYTE *salt;
6995         CK_ULONG saltLen;
6996         HMACContext *hmac;
6997         unsigned int bufLen;
6998 
6999         switch (params->ulSaltType) {
7000             case CKF_HKDF_SALT_NULL:
7001                 saltLen = hashLen;
7002                 salt = hashbuf;
7003                 memset(salt, 0, saltLen);
7004                 break;
7005             case CKF_HKDF_SALT_DATA:
7006                 salt = params->pSalt;
7007                 saltLen = params->ulSaltLen;
7008                 if ((salt == NULL) || (params->ulSaltLen == 0)) {
7009                     return CKR_MECHANISM_PARAM_INVALID;
7010                 }
7011                 break;
7012             case CKF_HKDF_SALT_KEY:
7013                 /* lookup key */
7014                 session = sftk_SessionFromHandle(hSession);
7015                 if (session == NULL) {
7016                     return CKR_SESSION_HANDLE_INVALID;
7017                 }
7018 
7019                 saltKey = sftk_ObjectFromHandle(params->hSaltKey, session);
7020                 sftk_FreeSession(session);
7021                 if (saltKey == NULL) {
7022                     return CKR_KEY_HANDLE_INVALID;
7023                 }
7024                 /* if the base key is not fips, but the salt key is, the
7025                  * resulting key can be fips */
7026                 if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) {
7027                     CK_MECHANISM mech;
7028                     mech.mechanism = CKM_HKDF_DERIVE;
7029                     mech.pParameter = params;
7030                     mech.ulParameterLen = sizeof(*params);
7031                     key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech,
7032                                                        CKA_DERIVE, saltKey);
7033                 }
7034                 saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
7035                 if (saltKey_att == NULL) {
7036                     sftk_FreeObject(saltKey);
7037                     return CKR_KEY_HANDLE_INVALID;
7038                 }
7039                 /* save the resulting salt */
7040                 salt = saltKey_att->attrib.pValue;
7041                 saltLen = saltKey_att->attrib.ulValueLen;
7042                 break;
7043             default:
7044                 return CKR_MECHANISM_PARAM_INVALID;
7045                 break;
7046         }
7047 
7048         hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
7049         if (saltKey_att) {
7050             sftk_FreeAttribute(saltKey_att);
7051         }
7052         if (saltKey) {
7053             sftk_FreeObject(saltKey);
7054         }
7055         if (!hmac) {
7056             return CKR_HOST_MEMORY;
7057         }
7058         HMAC_Begin(hmac);
7059         HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen);
7060         HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf));
7061         HMAC_Destroy(hmac, PR_TRUE);
7062         PORT_Assert(bufLen == rawHash->length);
7063         prk = hashbuf;
7064         prkLen = bufLen;
7065     } else {
7066         /* PRK = base key value */
7067         prk = sourceKeyBytes;
7068         prkLen = sourceKeyLen;
7069     }
7070 
7071     /* HKDF-Expand */
7072     if (!params->bExpand) {
7073         okm = prk;
7074         keySize = genLen = hashLen;
7075     } else {
7076         /* T(1) = HMAC-Hash(prk, "" | info | 0x01)
7077          * T(n) = HMAC-Hash(prk, T(n-1) | info | n
7078          * key material = T(1) | ... | T(n)
7079          */
7080         HMACContext *hmac;
7081         CK_BYTE bi;
7082         unsigned iterations;
7083 
7084         genLen = PR_ROUNDUP(keySize, hashLen);
7085         iterations = genLen / hashLen;
7086 
7087         if (genLen > sizeof(keyBlock)) {
7088             keyBlockAlloc = PORT_Alloc(genLen);
7089             if (keyBlockAlloc == NULL) {
7090                 return CKR_HOST_MEMORY;
7091             }
7092             keyBlockData = keyBlockAlloc;
7093         }
7094         hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
7095         if (hmac == NULL) {
7096             PORT_Free(keyBlockAlloc);
7097             return CKR_HOST_MEMORY;
7098         }
7099         for (bi = 1; bi <= iterations && bi > 0; ++bi) {
7100             unsigned len;
7101             HMAC_Begin(hmac);
7102             if (bi > 1) {
7103                 HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen);
7104             }
7105             if (params->ulInfoLen != 0) {
7106                 HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
7107             }
7108             HMAC_Update(hmac, &bi, 1);
7109             HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len,
7110                         hashLen);
7111             PORT_Assert(len == hashLen);
7112         }
7113         HMAC_Destroy(hmac, PR_TRUE);
7114         okm = &keyBlockData[0];
7115     }
7116     /* key material = okm */
7117     crv = CKR_OK;
7118     if (key) {
7119         crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
7120     } else {
7121         PORT_Assert(outKeyBytes != NULL);
7122         PORT_Memcpy(outKeyBytes, okm, keySize);
7123     }
7124     PORT_Memset(keyBlockData, 0, genLen);
7125     PORT_Memset(hashbuf, 0, sizeof(hashbuf));
7126     PORT_Free(keyBlockAlloc);
7127     return crv;
7128 }
7129 
7130 /*
7131  * SSL Key generation given pre master secret
7132  */
7133 #define NUM_MIXERS 9
7134 static const char *const mixers[NUM_MIXERS] = {
7135     "A",
7136     "BB",
7137     "CCC",
7138     "DDDD",
7139     "EEEEE",
7140     "FFFFFF",
7141     "GGGGGGG",
7142     "HHHHHHHH",
7143     "IIIIIIIII"
7144 };
7145 #define SSL3_PMS_LENGTH 48
7146 #define SSL3_MASTER_SECRET_LENGTH 48
7147 #define SSL3_RANDOM_LENGTH 32
7148 
7149 /* NSC_DeriveKey derives a key from a base key, creating a new key object. */
7150 CK_RV
NSC_DeriveKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hBaseKey,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)7151 NSC_DeriveKey(CK_SESSION_HANDLE hSession,
7152               CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
7153               CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
7154               CK_OBJECT_HANDLE_PTR phKey)
7155 {
7156     SFTKSession *session;
7157     SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
7158     SFTKObject *key;
7159     SFTKObject *sourceKey;
7160     SFTKAttribute *att = NULL;
7161     SFTKAttribute *att2 = NULL;
7162     unsigned char *buf;
7163     SHA1Context *sha;
7164     MD5Context *md5;
7165     MD2Context *md2;
7166     CK_ULONG macSize;
7167     CK_ULONG tmpKeySize;
7168     CK_ULONG IVSize;
7169     CK_ULONG keySize = 0;
7170     CK_RV crv = CKR_OK;
7171     CK_BBOOL cktrue = CK_TRUE;
7172     CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
7173     CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
7174     CK_KEY_DERIVATION_STRING_DATA *stringPtr;
7175     PRBool isTLS = PR_FALSE;
7176     PRBool isDH = PR_FALSE;
7177     HASH_HashType tlsPrfHash = HASH_AlgNULL;
7178     SECStatus rv;
7179     int i;
7180     unsigned int outLen;
7181     unsigned char sha_out[SHA1_LENGTH];
7182     unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH];
7183     PRBool isFIPS;
7184     HASH_HashType hashType;
7185     CK_MECHANISM_TYPE hashMech;
7186     PRBool extractValue = PR_TRUE;
7187     CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS ikeAppB;
7188     CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *pIkeAppB;
7189 
7190     CHECK_FORK();
7191 
7192     if (!slot) {
7193         return CKR_SESSION_HANDLE_INVALID;
7194     }
7195     if (!pMechanism) {
7196         return CKR_MECHANISM_PARAM_INVALID;
7197     }
7198     CK_MECHANISM_TYPE mechanism = pMechanism->mechanism;
7199 
7200     /*
7201      * now lets create an object to hang the attributes off of
7202      */
7203     if (phKey)
7204         *phKey = CK_INVALID_HANDLE;
7205 
7206     key = sftk_NewObject(slot); /* fill in the handle later */
7207     if (key == NULL) {
7208         return CKR_HOST_MEMORY;
7209     }
7210     isFIPS = sftk_isFIPS(slot->slotID);
7211 
7212     /*
7213      * load the template values into the object
7214      */
7215     for (i = 0; i < (int)ulAttributeCount; i++) {
7216         crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
7217         if (crv != CKR_OK)
7218             break;
7219 
7220         if (pTemplate[i].type == CKA_KEY_TYPE) {
7221             keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
7222         }
7223         if (pTemplate[i].type == CKA_VALUE_LEN) {
7224             keySize = *(CK_ULONG *)pTemplate[i].pValue;
7225         }
7226     }
7227     if (crv != CKR_OK) {
7228         sftk_FreeObject(key);
7229         return crv;
7230     }
7231 
7232     if (keySize == 0) {
7233         keySize = sftk_MapKeySize(keyType);
7234     }
7235 
7236     switch (mechanism) {
7237         case CKM_NSS_JPAKE_ROUND2_SHA1:   /* fall through */
7238         case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */
7239         case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */
7240         case CKM_NSS_JPAKE_ROUND2_SHA512:
7241             extractValue = PR_FALSE;
7242             classType = CKO_PRIVATE_KEY;
7243             break;
7244         case CKM_NSS_PUB_FROM_PRIV:
7245             extractValue = PR_FALSE;
7246             classType = CKO_PUBLIC_KEY;
7247             break;
7248         case CKM_HKDF_DATA:                              /* fall through */
7249         case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA:  /* fall through */
7250         case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
7251         case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA:
7252             classType = CKO_DATA;
7253             break;
7254         case CKM_NSS_JPAKE_FINAL_SHA1:   /* fall through */
7255         case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
7256         case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
7257         case CKM_NSS_JPAKE_FINAL_SHA512:
7258             extractValue = PR_FALSE;
7259         /* fall through */
7260         default:
7261             classType = CKO_SECRET_KEY;
7262     }
7263 
7264     crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType));
7265     if (crv != CKR_OK) {
7266         sftk_FreeObject(key);
7267         return crv;
7268     }
7269 
7270     /* look up the base key we're deriving with */
7271     session = sftk_SessionFromHandle(hSession);
7272     if (session == NULL) {
7273         sftk_FreeObject(key);
7274         return CKR_SESSION_HANDLE_INVALID;
7275     }
7276 
7277     sourceKey = sftk_ObjectFromHandle(hBaseKey, session);
7278     sftk_FreeSession(session);
7279     /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's
7280      * FIPS state below. */
7281     session->lastOpWasFIPS = PR_FALSE;
7282     if (sourceKey == NULL) {
7283         sftk_FreeObject(key);
7284         return CKR_KEY_HANDLE_INVALID;
7285     }
7286 
7287     if (extractValue) {
7288         /* get the value of the base key */
7289         att = sftk_FindAttribute(sourceKey, CKA_VALUE);
7290         if (att == NULL) {
7291             sftk_FreeObject(key);
7292             sftk_FreeObject(sourceKey);
7293             return CKR_KEY_HANDLE_INVALID;
7294         }
7295     }
7296     key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey);
7297 
7298     switch (mechanism) {
7299         /* get a public key from a private key. nsslowkey_ConvertToPublickey()
7300          * will generate the public portion if it doesn't already exist. */
7301         case CKM_NSS_PUB_FROM_PRIV: {
7302             NSSLOWKEYPrivateKey *privKey;
7303             NSSLOWKEYPublicKey *pubKey;
7304             int error;
7305 
7306             crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType);
7307             if (crv != CKR_OK) {
7308                 break;
7309             }
7310 
7311             /* privKey is stored in sourceKey and will be destroyed when
7312              * the sourceKey is freed. */
7313             privKey = sftk_GetPrivKey(sourceKey, keyType, &crv);
7314             if (privKey == NULL) {
7315                 break;
7316             }
7317             pubKey = nsslowkey_ConvertToPublicKey(privKey);
7318             if (pubKey == NULL) {
7319                 error = PORT_GetError();
7320                 crv = sftk_MapCryptError(error);
7321                 break;
7322             }
7323             crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey);
7324             nsslowkey_DestroyPublicKey(pubKey);
7325             break;
7326         }
7327         case CKM_NSS_IKE_PRF_DERIVE:
7328             if (pMechanism->ulParameterLen !=
7329                 sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) {
7330                 crv = CKR_MECHANISM_PARAM_INVALID;
7331                 break;
7332             }
7333             crv = sftk_ike_prf(hSession, att,
7334                                (CK_NSS_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key);
7335             break;
7336         case CKM_NSS_IKE1_PRF_DERIVE:
7337             if (pMechanism->ulParameterLen !=
7338                 sizeof(CK_NSS_IKE1_PRF_DERIVE_PARAMS)) {
7339                 crv = CKR_MECHANISM_PARAM_INVALID;
7340                 break;
7341             }
7342             crv = sftk_ike1_prf(hSession, att,
7343                                 (CK_NSS_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter,
7344                                 key, keySize);
7345             break;
7346         case CKM_NSS_IKE1_APP_B_PRF_DERIVE:
7347             pIkeAppB = (CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *)pMechanism->pParameter;
7348             if (pMechanism->ulParameterLen ==
7349                 sizeof(CK_MECHANISM_TYPE)) {
7350                 ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter;
7351                 ikeAppB.bHasKeygxy = PR_FALSE;
7352                 ikeAppB.hKeygxy = CK_INVALID_HANDLE;
7353                 ikeAppB.pExtraData = NULL;
7354                 ikeAppB.ulExtraDataLen = 0;
7355                 pIkeAppB = &ikeAppB;
7356             } else if (pMechanism->ulParameterLen !=
7357                        sizeof(CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS)) {
7358                 crv = CKR_MECHANISM_PARAM_INVALID;
7359                 break;
7360             }
7361             crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key,
7362                                            keySize);
7363             break;
7364         case CKM_NSS_IKE_PRF_PLUS_DERIVE:
7365             if (pMechanism->ulParameterLen !=
7366                 sizeof(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS)) {
7367                 crv = CKR_MECHANISM_PARAM_INVALID;
7368                 break;
7369             }
7370             crv = sftk_ike_prf_plus(hSession, att,
7371                                     (CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter,
7372                                     key, keySize);
7373             break;
7374         /*
7375          * generate the master secret
7376          */
7377         case CKM_TLS12_MASTER_KEY_DERIVE:
7378         case CKM_TLS12_MASTER_KEY_DERIVE_DH:
7379         case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256:
7380         case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256:
7381         case CKM_TLS_MASTER_KEY_DERIVE:
7382         case CKM_TLS_MASTER_KEY_DERIVE_DH:
7383         case CKM_SSL3_MASTER_KEY_DERIVE:
7384         case CKM_SSL3_MASTER_KEY_DERIVE_DH: {
7385             CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
7386             SSL3RSAPreMasterSecret *rsa_pms;
7387             unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
7388 
7389             if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) ||
7390                 (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
7391                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) {
7392                     crv = CKR_MECHANISM_PARAM_INVALID;
7393                     break;
7394                 }
7395                 CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master =
7396                     (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter;
7397                 tlsPrfHash = GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
7398                 if (tlsPrfHash == HASH_AlgNULL) {
7399                     crv = CKR_MECHANISM_PARAM_INVALID;
7400                     break;
7401                 }
7402             } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) ||
7403                        (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) {
7404                 tlsPrfHash = HASH_AlgSHA256;
7405             }
7406 
7407             if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) &&
7408                 (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) {
7409                 isTLS = PR_TRUE;
7410             }
7411             if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) ||
7412                 (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) ||
7413                 (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) ||
7414                 (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
7415                 isDH = PR_TRUE;
7416             }
7417 
7418             /* first do the consistency checks */
7419             if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
7420                 crv = CKR_KEY_TYPE_INCONSISTENT;
7421                 break;
7422             }
7423             att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7424             if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
7425                                    CKK_GENERIC_SECRET)) {
7426                 if (att2)
7427                     sftk_FreeAttribute(att2);
7428                 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7429                 break;
7430             }
7431             sftk_FreeAttribute(att2);
7432             if (keyType != CKK_GENERIC_SECRET) {
7433                 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7434                 break;
7435             }
7436             if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
7437                 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7438                 break;
7439             }
7440 
7441             /* finally do the key gen */
7442             ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
7443                               pMechanism->pParameter;
7444 
7445             if (ssl3_master->pVersion) {
7446                 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
7447                 rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
7448                 /* don't leak more key material then necessary for SSL to work */
7449                 if ((sessKey == NULL) || sessKey->wasDerived) {
7450                     ssl3_master->pVersion->major = 0xff;
7451                     ssl3_master->pVersion->minor = 0xff;
7452                 } else {
7453                     ssl3_master->pVersion->major = rsa_pms->client_version[0];
7454                     ssl3_master->pVersion->minor = rsa_pms->client_version[1];
7455                 }
7456             }
7457             if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
7458                 crv = CKR_MECHANISM_PARAM_INVALID;
7459                 break;
7460             }
7461             if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
7462                 crv = CKR_MECHANISM_PARAM_INVALID;
7463                 break;
7464             }
7465             PORT_Memcpy(crsrdata,
7466                         ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
7467             PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
7468                         ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
7469 
7470             if (isTLS) {
7471                 SECStatus status;
7472                 SECItem crsr = { siBuffer, NULL, 0 };
7473                 SECItem master = { siBuffer, NULL, 0 };
7474                 SECItem pms = { siBuffer, NULL, 0 };
7475 
7476                 crsr.data = crsrdata;
7477                 crsr.len = sizeof crsrdata;
7478                 master.data = key_block;
7479                 master.len = SSL3_MASTER_SECRET_LENGTH;
7480                 pms.data = (unsigned char *)att->attrib.pValue;
7481                 pms.len = att->attrib.ulValueLen;
7482 
7483                 if (tlsPrfHash != HASH_AlgNULL) {
7484                     status = TLS_P_hash(tlsPrfHash, &pms, "master secret",
7485                                         &crsr, &master, isFIPS);
7486                 } else {
7487                     status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS);
7488                 }
7489                 if (status != SECSuccess) {
7490                     PORT_Memset(crsrdata, 0, sizeof crsrdata);
7491                     crv = CKR_FUNCTION_FAILED;
7492                     break;
7493                 }
7494             } else {
7495                 /* now allocate the hash contexts */
7496                 md5 = MD5_NewContext();
7497                 if (md5 == NULL) {
7498                     PORT_Memset(crsrdata, 0, sizeof crsrdata);
7499                     crv = CKR_HOST_MEMORY;
7500                     break;
7501                 }
7502                 sha = SHA1_NewContext();
7503                 if (sha == NULL) {
7504                     PORT_Memset(crsrdata, 0, sizeof crsrdata);
7505                     PORT_Free(md5);
7506                     crv = CKR_HOST_MEMORY;
7507                     break;
7508                 }
7509                 for (i = 0; i < 3; i++) {
7510                     SHA1_Begin(sha);
7511                     SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
7512                     SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
7513                                 att->attrib.ulValueLen);
7514                     SHA1_Update(sha, crsrdata, sizeof crsrdata);
7515                     SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
7516                     PORT_Assert(outLen == SHA1_LENGTH);
7517 
7518                     MD5_Begin(md5);
7519                     MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
7520                                att->attrib.ulValueLen);
7521                     MD5_Update(md5, sha_out, outLen);
7522                     MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
7523                     PORT_Assert(outLen == MD5_LENGTH);
7524                 }
7525                 PORT_Free(md5);
7526                 PORT_Free(sha);
7527                 PORT_Memset(crsrdata, 0, sizeof crsrdata);
7528                 PORT_Memset(sha_out, 0, sizeof sha_out);
7529             }
7530 
7531             /* store the results */
7532             crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH);
7533             PORT_Memset(key_block, 0, sizeof key_block);
7534             if (crv != CKR_OK)
7535                 break;
7536             keyType = CKK_GENERIC_SECRET;
7537             crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
7538             if (isTLS) {
7539                 /* TLS's master secret is used to "sign" finished msgs with PRF. */
7540                 /* XXX This seems like a hack.   But SFTK_Derive only accepts
7541                  * one "operation" argument. */
7542                 crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
7543                 if (crv != CKR_OK)
7544                     break;
7545                 crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
7546                 if (crv != CKR_OK)
7547                     break;
7548                 /* While we're here, we might as well force this, too. */
7549                 crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
7550                 if (crv != CKR_OK)
7551                     break;
7552             }
7553             break;
7554         }
7555 
7556         /* Extended master key derivation [draft-ietf-tls-session-hash] */
7557         case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE:
7558         case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: {
7559             CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params;
7560             SSL3RSAPreMasterSecret *rsa_pms;
7561             SECStatus status;
7562             SECItem pms = { siBuffer, NULL, 0 };
7563             SECItem seed = { siBuffer, NULL, 0 };
7564             SECItem master = { siBuffer, NULL, 0 };
7565 
7566             ems_params = (CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *)
7567                              pMechanism->pParameter;
7568 
7569             /* First do the consistency checks */
7570             if ((mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE) &&
7571                 (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
7572                 crv = CKR_KEY_TYPE_INCONSISTENT;
7573                 break;
7574             }
7575             att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7576             if ((att2 == NULL) ||
7577                 (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) {
7578                 if (att2)
7579                     sftk_FreeAttribute(att2);
7580                 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7581                 break;
7582             }
7583             sftk_FreeAttribute(att2);
7584             if (keyType != CKK_GENERIC_SECRET) {
7585                 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7586                 break;
7587             }
7588             if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
7589                 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7590                 break;
7591             }
7592 
7593             /* Do the key derivation */
7594             pms.data = (unsigned char *)att->attrib.pValue;
7595             pms.len = att->attrib.ulValueLen;
7596             seed.data = ems_params->pSessionHash;
7597             seed.len = ems_params->ulSessionHashLen;
7598             master.data = key_block;
7599             master.len = SSL3_MASTER_SECRET_LENGTH;
7600             if (ems_params->prfHashMechanism == CKM_TLS_PRF) {
7601                 /*
7602                  * In this case, the session hash is the concatenation of SHA-1
7603                  * and MD5, so it should be 36 bytes long.
7604                  */
7605                 if (seed.len != MD5_LENGTH + SHA1_LENGTH) {
7606                     crv = CKR_TEMPLATE_INCONSISTENT;
7607                     break;
7608                 }
7609 
7610                 status = TLS_PRF(&pms, "extended master secret",
7611                                  &seed, &master, isFIPS);
7612             } else {
7613                 const SECHashObject *hashObj;
7614 
7615                 tlsPrfHash = GetHashTypeFromMechanism(ems_params->prfHashMechanism);
7616                 if (tlsPrfHash == HASH_AlgNULL) {
7617                     crv = CKR_MECHANISM_PARAM_INVALID;
7618                     break;
7619                 }
7620 
7621                 hashObj = HASH_GetRawHashObject(tlsPrfHash);
7622                 if (seed.len != hashObj->length) {
7623                     crv = CKR_TEMPLATE_INCONSISTENT;
7624                     break;
7625                 }
7626 
7627                 status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret",
7628                                     &seed, &master, isFIPS);
7629             }
7630             if (status != SECSuccess) {
7631                 crv = CKR_FUNCTION_FAILED;
7632                 break;
7633             }
7634 
7635             /* Reflect the version if required */
7636             if (ems_params->pVersion) {
7637                 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
7638                 rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
7639                 /* don't leak more key material than necessary for SSL to work */
7640                 if ((sessKey == NULL) || sessKey->wasDerived) {
7641                     ems_params->pVersion->major = 0xff;
7642                     ems_params->pVersion->minor = 0xff;
7643                 } else {
7644                     ems_params->pVersion->major = rsa_pms->client_version[0];
7645                     ems_params->pVersion->minor = rsa_pms->client_version[1];
7646                 }
7647             }
7648 
7649             /* Store the results */
7650             crv = sftk_forceAttribute(key, CKA_VALUE, key_block,
7651                                       SSL3_MASTER_SECRET_LENGTH);
7652             PORT_Memset(key_block, 0, sizeof key_block);
7653             break;
7654         }
7655 
7656         case CKM_TLS12_KEY_AND_MAC_DERIVE:
7657         case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256:
7658         case CKM_TLS_KEY_AND_MAC_DERIVE:
7659         case CKM_SSL3_KEY_AND_MAC_DERIVE: {
7660             CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
7661             CK_SSL3_KEY_MAT_OUT *ssl3_keys_out;
7662             CK_ULONG effKeySize;
7663             unsigned int block_needed;
7664             unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
7665 
7666             if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) {
7667                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) {
7668                     crv = CKR_MECHANISM_PARAM_INVALID;
7669                     break;
7670                 }
7671                 CK_TLS12_KEY_MAT_PARAMS *tls12_keys =
7672                     (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter;
7673                 tlsPrfHash = GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
7674                 if (tlsPrfHash == HASH_AlgNULL) {
7675                     crv = CKR_MECHANISM_PARAM_INVALID;
7676                     break;
7677                 }
7678             } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) {
7679                 tlsPrfHash = HASH_AlgSHA256;
7680             }
7681 
7682             if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) {
7683                 isTLS = PR_TRUE;
7684             }
7685 
7686             crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
7687             if (crv != CKR_OK)
7688                 break;
7689 
7690             if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
7691                 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7692                 break;
7693             }
7694             att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7695             if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
7696                                    CKK_GENERIC_SECRET)) {
7697                 if (att2)
7698                     sftk_FreeAttribute(att2);
7699                 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7700                 break;
7701             }
7702             sftk_FreeAttribute(att2);
7703             md5 = MD5_NewContext();
7704             if (md5 == NULL) {
7705                 crv = CKR_HOST_MEMORY;
7706                 break;
7707             }
7708             sha = SHA1_NewContext();
7709             if (sha == NULL) {
7710                 MD5_DestroyContext(md5, PR_TRUE);
7711                 crv = CKR_HOST_MEMORY;
7712                 break;
7713             }
7714 
7715             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) {
7716                 MD5_DestroyContext(md5, PR_TRUE);
7717                 SHA1_DestroyContext(sha, PR_TRUE);
7718                 crv = CKR_MECHANISM_PARAM_INVALID;
7719                 break;
7720             }
7721             ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter;
7722 
7723             PORT_Memcpy(srcrdata,
7724                         ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
7725             PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
7726                         ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
7727 
7728             /*
7729              * clear out our returned keys so we can recover on failure
7730              */
7731             ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
7732             ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;
7733             ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;
7734             ssl3_keys_out->hClientKey = CK_INVALID_HANDLE;
7735             ssl3_keys_out->hServerKey = CK_INVALID_HANDLE;
7736 
7737             /*
7738              * How much key material do we need?
7739              */
7740             macSize = ssl3_keys->ulMacSizeInBits / 8;
7741             effKeySize = ssl3_keys->ulKeySizeInBits / 8;
7742             IVSize = ssl3_keys->ulIVSizeInBits / 8;
7743             if (keySize == 0) {
7744                 effKeySize = keySize;
7745             }
7746 
7747             /* bIsExport must be false. */
7748             if (ssl3_keys->bIsExport) {
7749                 MD5_DestroyContext(md5, PR_TRUE);
7750                 SHA1_DestroyContext(sha, PR_TRUE);
7751                 PORT_Memset(srcrdata, 0, sizeof srcrdata);
7752                 crv = CKR_MECHANISM_PARAM_INVALID;
7753                 break;
7754             }
7755 
7756             block_needed = 2 * (macSize + effKeySize + IVSize);
7757             PORT_Assert(block_needed <= sizeof key_block);
7758             if (block_needed > sizeof key_block)
7759                 block_needed = sizeof key_block;
7760 
7761             /*
7762              * generate the key material: This looks amazingly similar to the
7763              * PMS code, and is clearly crying out for a function to provide it.
7764              */
7765             if (isTLS) {
7766                 SECStatus status;
7767                 SECItem srcr = { siBuffer, NULL, 0 };
7768                 SECItem keyblk = { siBuffer, NULL, 0 };
7769                 SECItem master = { siBuffer, NULL, 0 };
7770 
7771                 srcr.data = srcrdata;
7772                 srcr.len = sizeof srcrdata;
7773                 keyblk.data = key_block;
7774                 keyblk.len = block_needed;
7775                 master.data = (unsigned char *)att->attrib.pValue;
7776                 master.len = att->attrib.ulValueLen;
7777 
7778                 if (tlsPrfHash != HASH_AlgNULL) {
7779                     status = TLS_P_hash(tlsPrfHash, &master, "key expansion",
7780                                         &srcr, &keyblk, isFIPS);
7781                 } else {
7782                     status = TLS_PRF(&master, "key expansion", &srcr, &keyblk,
7783                                      isFIPS);
7784                 }
7785                 if (status != SECSuccess) {
7786                     goto key_and_mac_derive_fail;
7787                 }
7788             } else {
7789                 unsigned int block_bytes = 0;
7790                 /* key_block =
7791                  *     MD5(master_secret + SHA('A' + master_secret +
7792                  *                      ServerHello.random + ClientHello.random)) +
7793                  *     MD5(master_secret + SHA('BB' + master_secret +
7794                  *                      ServerHello.random + ClientHello.random)) +
7795                  *     MD5(master_secret + SHA('CCC' + master_secret +
7796                  *                      ServerHello.random + ClientHello.random)) +
7797                  *     [...];
7798                  */
7799                 for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) {
7800                     SHA1_Begin(sha);
7801                     SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
7802                     SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
7803                                 att->attrib.ulValueLen);
7804                     SHA1_Update(sha, srcrdata, sizeof srcrdata);
7805                     SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
7806                     PORT_Assert(outLen == SHA1_LENGTH);
7807                     MD5_Begin(md5);
7808                     MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
7809                                att->attrib.ulValueLen);
7810                     MD5_Update(md5, sha_out, outLen);
7811                     MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
7812                     PORT_Assert(outLen == MD5_LENGTH);
7813                     block_bytes += outLen;
7814                 }
7815                 PORT_Memset(sha_out, 0, sizeof sha_out);
7816             }
7817 
7818             /*
7819              * Put the key material where it goes.
7820              */
7821             i = 0; /* now shows how much consumed */
7822 
7823             /*
7824              * The key_block is partitioned as follows:
7825              * client_write_MAC_secret[CipherSpec.hash_size]
7826              */
7827             crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
7828                                    &ssl3_keys_out->hClientMacSecret);
7829             if (crv != CKR_OK)
7830                 goto key_and_mac_derive_fail;
7831 
7832             i += macSize;
7833 
7834             /*
7835              * server_write_MAC_secret[CipherSpec.hash_size]
7836              */
7837             crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
7838                                    &ssl3_keys_out->hServerMacSecret);
7839             if (crv != CKR_OK) {
7840                 goto key_and_mac_derive_fail;
7841             }
7842             i += macSize;
7843 
7844             if (keySize) {
7845                 /*
7846                 ** Generate Domestic write keys and IVs.
7847                 ** client_write_key[CipherSpec.key_material]
7848                 */
7849                 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
7850                                        keySize, &ssl3_keys_out->hClientKey);
7851                 if (crv != CKR_OK) {
7852                     goto key_and_mac_derive_fail;
7853                 }
7854                 i += keySize;
7855 
7856                 /*
7857                 ** server_write_key[CipherSpec.key_material]
7858                 */
7859                 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
7860                                        keySize, &ssl3_keys_out->hServerKey);
7861                 if (crv != CKR_OK) {
7862                     goto key_and_mac_derive_fail;
7863                 }
7864                 i += keySize;
7865 
7866                 /*
7867                 ** client_write_IV[CipherSpec.IV_size]
7868                 */
7869                 if (IVSize > 0) {
7870                     PORT_Memcpy(ssl3_keys_out->pIVClient,
7871                                 &key_block[i], IVSize);
7872                     i += IVSize;
7873                 }
7874 
7875                 /*
7876                 ** server_write_IV[CipherSpec.IV_size]
7877                 */
7878                 if (IVSize > 0) {
7879                     PORT_Memcpy(ssl3_keys_out->pIVServer,
7880                                 &key_block[i], IVSize);
7881                     i += IVSize;
7882                 }
7883                 PORT_Assert(i <= sizeof key_block);
7884             }
7885 
7886             crv = CKR_OK;
7887 
7888             if (0) {
7889             key_and_mac_derive_fail:
7890                 if (crv == CKR_OK)
7891                     crv = CKR_FUNCTION_FAILED;
7892                 sftk_freeSSLKeys(hSession, ssl3_keys_out);
7893             }
7894             PORT_Memset(srcrdata, 0, sizeof srcrdata);
7895             PORT_Memset(key_block, 0, sizeof key_block);
7896             MD5_DestroyContext(md5, PR_TRUE);
7897             SHA1_DestroyContext(sha, PR_TRUE);
7898             sftk_FreeObject(key);
7899             key = NULL;
7900             break;
7901         }
7902 
7903         case CKM_DES3_ECB_ENCRYPT_DATA:
7904         case CKM_DES3_CBC_ENCRYPT_DATA: {
7905             void *cipherInfo;
7906             unsigned char des3key[MAX_DES3_KEY_SIZE];
7907             CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr;
7908             int mode;
7909             unsigned char *iv;
7910             unsigned char *data;
7911             CK_ULONG len;
7912 
7913             if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) {
7914                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
7915                     crv = CKR_MECHANISM_PARAM_INVALID;
7916                     break;
7917                 }
7918                 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
7919                                 pMechanism->pParameter;
7920                 mode = NSS_DES_EDE3;
7921                 iv = NULL;
7922                 data = stringPtr->pData;
7923                 len = stringPtr->ulLen;
7924             } else {
7925                 mode = NSS_DES_EDE3_CBC;
7926                 desEncryptPtr =
7927                     (CK_DES_CBC_ENCRYPT_DATA_PARAMS *)
7928                         pMechanism->pParameter;
7929                 iv = desEncryptPtr->iv;
7930                 data = desEncryptPtr->pData;
7931                 len = desEncryptPtr->length;
7932             }
7933             if (att->attrib.ulValueLen == 16) {
7934                 PORT_Memcpy(des3key, att->attrib.pValue, 16);
7935                 PORT_Memcpy(des3key + 16, des3key, 8);
7936             } else if (att->attrib.ulValueLen == 24) {
7937                 PORT_Memcpy(des3key, att->attrib.pValue, 24);
7938             } else {
7939                 crv = CKR_KEY_SIZE_RANGE;
7940                 break;
7941             }
7942             cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE);
7943             PORT_Memset(des3key, 0, 24);
7944             if (cipherInfo == NULL) {
7945                 crv = CKR_HOST_MEMORY;
7946                 break;
7947             }
7948             crv = sftk_DeriveEncrypt((SFTKCipher)DES_Encrypt,
7949                                      cipherInfo, 8, key, keySize,
7950                                      data, len);
7951             DES_DestroyContext(cipherInfo, PR_TRUE);
7952             break;
7953         }
7954 
7955         case CKM_AES_ECB_ENCRYPT_DATA:
7956         case CKM_AES_CBC_ENCRYPT_DATA: {
7957             void *cipherInfo;
7958             CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
7959             int mode;
7960             unsigned char *iv;
7961             unsigned char *data;
7962             CK_ULONG len;
7963 
7964             if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) {
7965                 mode = NSS_AES;
7966                 iv = NULL;
7967                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
7968                     crv = CKR_MECHANISM_PARAM_INVALID;
7969                     break;
7970                 }
7971                 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
7972                 data = stringPtr->pData;
7973                 len = stringPtr->ulLen;
7974             } else {
7975                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
7976                     crv = CKR_MECHANISM_PARAM_INVALID;
7977                     break;
7978                 }
7979                 aesEncryptPtr =
7980                     (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter;
7981                 mode = NSS_AES_CBC;
7982                 iv = aesEncryptPtr->iv;
7983                 data = aesEncryptPtr->pData;
7984                 len = aesEncryptPtr->length;
7985             }
7986 
7987             cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue,
7988                                            iv, mode, PR_TRUE,
7989                                            att->attrib.ulValueLen, 16);
7990             if (cipherInfo == NULL) {
7991                 crv = CKR_HOST_MEMORY;
7992                 break;
7993             }
7994             crv = sftk_DeriveEncrypt((SFTKCipher)AES_Encrypt,
7995                                      cipherInfo, 16, key, keySize,
7996                                      data, len);
7997             AES_DestroyContext(cipherInfo, PR_TRUE);
7998             break;
7999         }
8000 
8001         case CKM_CAMELLIA_ECB_ENCRYPT_DATA:
8002         case CKM_CAMELLIA_CBC_ENCRYPT_DATA: {
8003             void *cipherInfo;
8004             CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
8005             int mode;
8006             unsigned char *iv;
8007             unsigned char *data;
8008             CK_ULONG len;
8009 
8010             if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) {
8011                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8012                     crv = CKR_MECHANISM_PARAM_INVALID;
8013                     break;
8014                 }
8015                 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
8016                                 pMechanism->pParameter;
8017                 aesEncryptPtr = NULL;
8018                 mode = NSS_CAMELLIA;
8019                 data = stringPtr->pData;
8020                 len = stringPtr->ulLen;
8021                 iv = NULL;
8022             } else {
8023                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
8024                     crv = CKR_MECHANISM_PARAM_INVALID;
8025                     break;
8026                 }
8027                 stringPtr = NULL;
8028                 aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
8029                                     pMechanism->pParameter;
8030                 mode = NSS_CAMELLIA_CBC;
8031                 iv = aesEncryptPtr->iv;
8032                 data = aesEncryptPtr->pData;
8033                 len = aesEncryptPtr->length;
8034             }
8035 
8036             cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue,
8037                                                 iv, mode, PR_TRUE,
8038                                                 att->attrib.ulValueLen);
8039             if (cipherInfo == NULL) {
8040                 crv = CKR_HOST_MEMORY;
8041                 break;
8042             }
8043             crv = sftk_DeriveEncrypt((SFTKCipher)Camellia_Encrypt,
8044                                      cipherInfo, 16, key, keySize,
8045                                      data, len);
8046             Camellia_DestroyContext(cipherInfo, PR_TRUE);
8047             break;
8048         }
8049 
8050 #ifndef NSS_DISABLE_DEPRECATED_SEED
8051         case CKM_SEED_ECB_ENCRYPT_DATA:
8052         case CKM_SEED_CBC_ENCRYPT_DATA: {
8053             void *cipherInfo;
8054             CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
8055             int mode;
8056             unsigned char *iv;
8057             unsigned char *data;
8058             CK_ULONG len;
8059 
8060             if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) {
8061                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8062                     crv = CKR_MECHANISM_PARAM_INVALID;
8063                     break;
8064                 }
8065                 mode = NSS_SEED;
8066                 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
8067                                 pMechanism->pParameter;
8068                 aesEncryptPtr = NULL;
8069                 data = stringPtr->pData;
8070                 len = stringPtr->ulLen;
8071                 iv = NULL;
8072             } else {
8073                 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
8074                     crv = CKR_MECHANISM_PARAM_INVALID;
8075                     break;
8076                 }
8077                 mode = NSS_SEED_CBC;
8078                 aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
8079                                     pMechanism->pParameter;
8080                 iv = aesEncryptPtr->iv;
8081                 data = aesEncryptPtr->pData;
8082                 len = aesEncryptPtr->length;
8083             }
8084 
8085             cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue,
8086                                             iv, mode, PR_TRUE);
8087             if (cipherInfo == NULL) {
8088                 crv = CKR_HOST_MEMORY;
8089                 break;
8090             }
8091             crv = sftk_DeriveEncrypt((SFTKCipher)SEED_Encrypt,
8092                                      cipherInfo, 16, key, keySize,
8093                                      data, len);
8094             SEED_DestroyContext(cipherInfo, PR_TRUE);
8095             break;
8096         }
8097 #endif /* NSS_DISABLE_DEPRECATED_SEED */
8098 
8099         case CKM_CONCATENATE_BASE_AND_KEY: {
8100             SFTKObject *newKey;
8101 
8102             crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8103             if (crv != CKR_OK)
8104                 break;
8105 
8106             session = sftk_SessionFromHandle(hSession);
8107             if (session == NULL) {
8108                 crv = CKR_SESSION_HANDLE_INVALID;
8109                 break;
8110             }
8111 
8112             newKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
8113                                                 pMechanism->pParameter,
8114                                            session);
8115             sftk_FreeSession(session);
8116             if (newKey == NULL) {
8117                 crv = CKR_KEY_HANDLE_INVALID;
8118                 break;
8119             }
8120 
8121             if (sftk_isTrue(newKey, CKA_SENSITIVE)) {
8122                 crv = sftk_forceAttribute(newKey, CKA_SENSITIVE, &cktrue,
8123                                           sizeof(CK_BBOOL));
8124                 if (crv != CKR_OK) {
8125                     sftk_FreeObject(newKey);
8126                     break;
8127                 }
8128             }
8129 
8130             att2 = sftk_FindAttribute(newKey, CKA_VALUE);
8131             if (att2 == NULL) {
8132                 sftk_FreeObject(newKey);
8133                 crv = CKR_KEY_HANDLE_INVALID;
8134                 break;
8135             }
8136             tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen;
8137             if (keySize == 0)
8138                 keySize = tmpKeySize;
8139             if (keySize > tmpKeySize) {
8140                 sftk_FreeObject(newKey);
8141                 sftk_FreeAttribute(att2);
8142                 crv = CKR_TEMPLATE_INCONSISTENT;
8143                 break;
8144             }
8145             buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8146             if (buf == NULL) {
8147                 sftk_FreeAttribute(att2);
8148                 sftk_FreeObject(newKey);
8149                 crv = CKR_HOST_MEMORY;
8150                 break;
8151             }
8152 
8153             PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
8154             PORT_Memcpy(buf + att->attrib.ulValueLen,
8155                         att2->attrib.pValue, att2->attrib.ulValueLen);
8156 
8157             crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8158             PORT_ZFree(buf, tmpKeySize);
8159             sftk_FreeAttribute(att2);
8160             sftk_FreeObject(newKey);
8161             break;
8162         }
8163 
8164         case CKM_CONCATENATE_BASE_AND_DATA:
8165             crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8166             if (crv != CKR_OK)
8167                 break;
8168 
8169             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8170                 crv = CKR_MECHANISM_PARAM_INVALID;
8171                 break;
8172             }
8173             stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8174             tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
8175             if (keySize == 0)
8176                 keySize = tmpKeySize;
8177             if (keySize > tmpKeySize) {
8178                 crv = CKR_TEMPLATE_INCONSISTENT;
8179                 break;
8180             }
8181             buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8182             if (buf == NULL) {
8183                 crv = CKR_HOST_MEMORY;
8184                 break;
8185             }
8186 
8187             PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
8188             PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData,
8189                         stringPtr->ulLen);
8190 
8191             crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8192             PORT_ZFree(buf, tmpKeySize);
8193             break;
8194         case CKM_CONCATENATE_DATA_AND_BASE:
8195             crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8196             if (crv != CKR_OK)
8197                 break;
8198 
8199             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8200                 crv = CKR_MECHANISM_PARAM_INVALID;
8201                 break;
8202             }
8203             stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8204             tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
8205             if (keySize == 0)
8206                 keySize = tmpKeySize;
8207             if (keySize > tmpKeySize) {
8208                 crv = CKR_TEMPLATE_INCONSISTENT;
8209                 break;
8210             }
8211             buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8212             if (buf == NULL) {
8213                 crv = CKR_HOST_MEMORY;
8214                 break;
8215             }
8216 
8217             PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen);
8218             PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue,
8219                         att->attrib.ulValueLen);
8220 
8221             crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8222             PORT_ZFree(buf, tmpKeySize);
8223             break;
8224         case CKM_XOR_BASE_AND_DATA:
8225             crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8226             if (crv != CKR_OK)
8227                 break;
8228 
8229             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8230                 crv = CKR_MECHANISM_PARAM_INVALID;
8231                 break;
8232             }
8233             stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8234             tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen);
8235             if (keySize == 0)
8236                 keySize = tmpKeySize;
8237             if (keySize > tmpKeySize) {
8238                 crv = CKR_TEMPLATE_INCONSISTENT;
8239                 break;
8240             }
8241             buf = (unsigned char *)PORT_Alloc(keySize);
8242             if (buf == NULL) {
8243                 crv = CKR_HOST_MEMORY;
8244                 break;
8245             }
8246 
8247             PORT_Memcpy(buf, att->attrib.pValue, keySize);
8248             for (i = 0; i < (int)keySize; i++) {
8249                 buf[i] ^= stringPtr->pData[i];
8250             }
8251 
8252             crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8253             PORT_ZFree(buf, keySize);
8254             break;
8255 
8256         case CKM_EXTRACT_KEY_FROM_KEY: {
8257             if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) {
8258                 crv = CKR_MECHANISM_PARAM_INVALID;
8259                 break;
8260             }
8261             /* the following assumes 8 bits per byte */
8262             CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
8263             CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
8264             CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
8265 
8266             crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8267             if (crv != CKR_OK)
8268                 break;
8269 
8270             if (keySize == 0) {
8271                 crv = CKR_TEMPLATE_INCOMPLETE;
8272                 break;
8273             }
8274             /* make sure we have enough bits in the original key */
8275             if (att->attrib.ulValueLen <
8276                 (offset + keySize + ((shift != 0) ? 1 : 0))) {
8277                 crv = CKR_MECHANISM_PARAM_INVALID;
8278                 break;
8279             }
8280             buf = (unsigned char *)PORT_Alloc(keySize);
8281             if (buf == NULL) {
8282                 crv = CKR_HOST_MEMORY;
8283                 break;
8284             }
8285 
8286             /* copy the bits we need into the new key */
8287             for (i = 0; i < (int)keySize; i++) {
8288                 unsigned char *value =
8289                     ((unsigned char *)att->attrib.pValue) + offset + i;
8290                 if (shift) {
8291                     buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
8292                 } else {
8293                     buf[i] = value[0];
8294                 }
8295             }
8296 
8297             crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8298             PORT_ZFree(buf, keySize);
8299             break;
8300         }
8301         case CKM_MD2_KEY_DERIVATION:
8302             if (keySize == 0)
8303                 keySize = MD2_LENGTH;
8304             if (keySize > MD2_LENGTH) {
8305                 crv = CKR_TEMPLATE_INCONSISTENT;
8306                 break;
8307             }
8308             /* now allocate the hash contexts */
8309             md2 = MD2_NewContext();
8310             if (md2 == NULL) {
8311                 crv = CKR_HOST_MEMORY;
8312                 break;
8313             }
8314             MD2_Begin(md2);
8315             MD2_Update(md2, (const unsigned char *)att->attrib.pValue,
8316                        att->attrib.ulValueLen);
8317             MD2_End(md2, key_block, &outLen, MD2_LENGTH);
8318             MD2_DestroyContext(md2, PR_TRUE);
8319 
8320             crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);
8321             PORT_Memset(key_block, 0, MD2_LENGTH);
8322             break;
8323 #define DERIVE_KEY_HASH(hash)                                                \
8324     case CKM_##hash##_KEY_DERIVATION:                                        \
8325         if (keySize == 0)                                                    \
8326             keySize = hash##_LENGTH;                                         \
8327         if (keySize > hash##_LENGTH) {                                       \
8328             crv = CKR_TEMPLATE_INCONSISTENT;                                 \
8329             break;                                                           \
8330         }                                                                    \
8331         hash##_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, \
8332                        att->attrib.ulValueLen);                              \
8333         crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);       \
8334         PORT_Memset(key_block, 0, hash##_LENGTH);                            \
8335         break;
8336             DERIVE_KEY_HASH(MD5)
8337             DERIVE_KEY_HASH(SHA1)
8338             DERIVE_KEY_HASH(SHA224)
8339             DERIVE_KEY_HASH(SHA256)
8340             DERIVE_KEY_HASH(SHA384)
8341             DERIVE_KEY_HASH(SHA512)
8342 
8343         case CKM_DH_PKCS_DERIVE: {
8344             SECItem derived, dhPublic;
8345             SECItem dhPrime, dhValue;
8346             const SECItem *subPrime;
8347             /* sourceKey - values for the local existing low key */
8348             /* get prime and value attributes */
8349             crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
8350             if (crv != CKR_OK)
8351                 break;
8352 
8353             dhPublic.data = pMechanism->pParameter;
8354             dhPublic.len = pMechanism->ulParameterLen;
8355 
8356             /* if the prime is an approved prime, we can skip all the other
8357              * checks. */
8358             subPrime = sftk_VerifyDH_Prime(&dhPrime, isFIPS);
8359             if (subPrime == NULL) {
8360                 SECItem dhSubPrime;
8361                 /* If the caller set the subprime value, it means that
8362                  * either the caller knows the subprime value and wants us
8363                  * to validate the key against the subprime, or that the
8364                  * caller wants us to verify that the prime is a safe prime
8365                  * by passing in subprime = (prime-1)/2 */
8366                 dhSubPrime.data = NULL;
8367                 dhSubPrime.len = 0;
8368                 crv = sftk_Attribute2SecItem(NULL, &dhSubPrime,
8369                                              sourceKey, CKA_SUBPRIME);
8370                 /* we ignore the value of crv here, We treat a valid
8371                 * return of len = 0 and a failure to find a subrime the same
8372                 * NOTE: we free the subprime in both cases depending on
8373                 * PORT_Free of NULL to be a noop */
8374                 if (dhSubPrime.len != 0) {
8375                     PRBool isSafe = PR_FALSE;
8376 
8377                     /* Callers can set dhSubPrime to q=(p-1)/2 to force
8378                      * checks for safe primes. If so we only need to check
8379                      * q and p for primality and skip the group test.  */
8380                     rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe);
8381                     if (rv != SECSuccess) {
8382                         /* either p or q was even and therefore not prime,
8383                          * we can stop processing here and fail now */
8384                         crv = CKR_ARGUMENTS_BAD;
8385                         SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8386                         SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8387                         break;
8388                     }
8389 
8390                     /* first make sure the primes are really prime */
8391                     if (!KEA_PrimeCheck(&dhPrime)) {
8392                         crv = CKR_ARGUMENTS_BAD;
8393                         SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8394                         SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8395                         break;
8396                     }
8397                     if (!KEA_PrimeCheck(&dhSubPrime)) {
8398                         crv = CKR_ARGUMENTS_BAD;
8399                         SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8400                         SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8401                         break;
8402                     }
8403                     if (isFIPS || !isSafe) {
8404                         /* With safe primes, there is only one other small
8405                          * subgroup. As long as y isn't 0, 1, or -1 mod p,
8406                          * any other y is safe. Only do the full check for
8407                          * non-safe primes, except in FIPS mode we need
8408                          * to do this check on all primes in which
8409                          * we receive the subprime value */
8410                         if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) {
8411                             crv = CKR_ARGUMENTS_BAD;
8412                             SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8413                             SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8414                             break;
8415                         }
8416                     }
8417                 } else if (isFIPS) {
8418                     /* In FIPS mode we only accept approved primes, or
8419                      * primes with the full subprime value */
8420                     crv = CKR_ARGUMENTS_BAD;
8421                     SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8422                     break;
8423                 }
8424                 /* checks are complete, no need for the subPrime any longer */
8425                 SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8426             }
8427 
8428             /* now that the prime is validated, get the private value */
8429             crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
8430             if (crv != CKR_OK) {
8431                 SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8432                 break;
8433             }
8434 
8435             /* calculate private value - oct */
8436             rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
8437 
8438             SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8439             SECITEM_ZfreeItem(&dhValue, PR_FALSE);
8440 
8441             if (rv == SECSuccess) {
8442                 sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
8443                 SECITEM_ZfreeItem(&derived, PR_FALSE);
8444                 crv = CKR_OK;
8445             } else
8446                 crv = CKR_HOST_MEMORY;
8447 
8448             break;
8449         }
8450 
8451         case CKM_ECDH1_DERIVE:
8452         case CKM_ECDH1_COFACTOR_DERIVE: {
8453             SECItem ecScalar, ecPoint;
8454             SECItem tmp;
8455             PRBool withCofactor = PR_FALSE;
8456             unsigned char *secret;
8457             unsigned char *keyData = NULL;
8458             unsigned int secretlen, pubKeyLen;
8459             CK_ECDH1_DERIVE_PARAMS *mechParams;
8460             NSSLOWKEYPrivateKey *privKey;
8461             PLArenaPool *arena = NULL;
8462 
8463             /* Check mechanism parameters */
8464             mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter;
8465             if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) ||
8466                 ((mechParams->kdf == CKD_NULL) &&
8467                  ((mechParams->ulSharedDataLen != 0) ||
8468                   (mechParams->pSharedData != NULL)))) {
8469                 crv = CKR_MECHANISM_PARAM_INVALID;
8470                 break;
8471             }
8472 
8473             privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv);
8474             if (privKey == NULL) {
8475                 break;
8476             }
8477 
8478             /* Now we are working with a non-NULL private key */
8479             SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue);
8480 
8481             ecPoint.data = mechParams->pPublicData;
8482             ecPoint.len = mechParams->ulPublicDataLen;
8483 
8484             pubKeyLen = EC_GetPointSize(&privKey->u.ec.ecParams);
8485 
8486             /* if the len is too large, might be an encoded point */
8487             if (ecPoint.len > pubKeyLen) {
8488                 SECItem newPoint;
8489 
8490                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
8491                 if (arena == NULL) {
8492                     goto ec_loser;
8493                 }
8494 
8495                 rv = SEC_QuickDERDecodeItem(arena, &newPoint,
8496                                             SEC_ASN1_GET(SEC_OctetStringTemplate),
8497                                             &ecPoint);
8498                 if (rv != SECSuccess) {
8499                     goto ec_loser;
8500                 }
8501                 ecPoint = newPoint;
8502             }
8503 
8504             if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) {
8505                 withCofactor = PR_TRUE;
8506             }
8507 
8508             rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
8509                              withCofactor, &tmp);
8510             SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
8511             ecScalar.data = NULL;
8512             if (privKey != sourceKey->objectInfo) {
8513                 nsslowkey_DestroyPrivateKey(privKey);
8514                 privKey = NULL;
8515             }
8516             if (arena) {
8517                 PORT_FreeArena(arena, PR_FALSE);
8518                 arena = NULL;
8519             }
8520 
8521             if (rv != SECSuccess) {
8522                 crv = sftk_MapCryptError(PORT_GetError());
8523                 break;
8524             }
8525 
8526             /*
8527              * apply the kdf function.
8528              */
8529             if (mechParams->kdf == CKD_NULL) {
8530                 /*
8531              * tmp is the raw data created by ECDH_Derive,
8532              * secret and secretlen are the values we will
8533              * eventually pass as our generated key.
8534              */
8535                 secret = tmp.data;
8536                 secretlen = tmp.len;
8537             } else {
8538                 secretlen = keySize;
8539                 crv = sftk_ANSI_X9_63_kdf(&secret, keySize,
8540                                           &tmp, mechParams->pSharedData,
8541                                           mechParams->ulSharedDataLen, mechParams->kdf);
8542                 PORT_ZFree(tmp.data, tmp.len);
8543                 if (crv != CKR_OK) {
8544                     break;
8545                 }
8546                 tmp.data = secret;
8547                 tmp.len = secretlen;
8548             }
8549 
8550             /*
8551              * if keySize is supplied, then we are generating a key of a specific
8552              * length. This is done by taking the least significant 'keySize'
8553              * bytes from the unsigned value calculated by ECDH. Note: this may
8554              * mean padding temp with extra leading zeros from what ECDH_Derive
8555              * already returned (which itself may contain leading zeros).
8556              */
8557             if (keySize) {
8558                 if (secretlen < keySize) {
8559                     keyData = PORT_ZAlloc(keySize);
8560                     if (!keyData) {
8561                         PORT_ZFree(tmp.data, tmp.len);
8562                         crv = CKR_HOST_MEMORY;
8563                         break;
8564                     }
8565                     PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen);
8566                     secret = keyData;
8567                 } else {
8568                     secret += (secretlen - keySize);
8569                 }
8570                 secretlen = keySize;
8571             }
8572 
8573             sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
8574             PORT_ZFree(tmp.data, tmp.len);
8575             if (keyData) {
8576                 PORT_ZFree(keyData, keySize);
8577             }
8578             break;
8579 
8580         ec_loser:
8581             crv = CKR_ARGUMENTS_BAD;
8582             SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
8583             if (privKey != sourceKey->objectInfo)
8584                 nsslowkey_DestroyPrivateKey(privKey);
8585             if (arena) {
8586                 PORT_FreeArena(arena, PR_TRUE);
8587             }
8588             break;
8589         }
8590         /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */
8591         case CKM_NSS_HKDF_SHA1:
8592             hashMech = CKM_SHA_1;
8593             goto hkdf;
8594         case CKM_NSS_HKDF_SHA256:
8595             hashMech = CKM_SHA256;
8596             goto hkdf;
8597         case CKM_NSS_HKDF_SHA384:
8598             hashMech = CKM_SHA384;
8599             goto hkdf;
8600         case CKM_NSS_HKDF_SHA512:
8601             hashMech = CKM_SHA512;
8602             goto hkdf;
8603         hkdf : {
8604             const CK_NSS_HKDFParams *params =
8605                 (const CK_NSS_HKDFParams *)pMechanism->pParameter;
8606             CK_HKDF_PARAMS hkdfParams;
8607 
8608             if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) {
8609                 crv = CKR_MECHANISM_PARAM_INVALID;
8610                 break;
8611             }
8612             hkdfParams.bExtract = params->bExtract;
8613             hkdfParams.bExpand = params->bExpand;
8614             if (params->pSalt) {
8615                 hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA;
8616             } else {
8617                 hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL;
8618             }
8619             hkdfParams.pSalt = params->pSalt;
8620             hkdfParams.ulSaltLen = params->ulSaltLen;
8621             hkdfParams.hSaltKey = CK_INVALID_HANDLE;
8622             hkdfParams.pInfo = params->pInfo;
8623             hkdfParams.ulInfoLen = params->ulInfoLen;
8624             hkdfParams.prfHashMechanism = hashMech;
8625 
8626             crv = sftk_HKDF(&hkdfParams, hSession, sourceKey,
8627                             att->attrib.pValue, att->attrib.ulValueLen,
8628                             key, NULL, keySize, PR_FALSE, isFIPS);
8629         } break;
8630         case CKM_HKDF_DERIVE:
8631         case CKM_HKDF_DATA: /* only difference is the class of key */
8632             if ((pMechanism->pParameter == NULL) ||
8633                 (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) {
8634                 crv = CKR_MECHANISM_PARAM_INVALID;
8635                 break;
8636             }
8637             crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter,
8638                             hSession, sourceKey, att->attrib.pValue,
8639                             att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE,
8640                             isFIPS);
8641             break;
8642         case CKM_NSS_JPAKE_ROUND2_SHA1:
8643             hashType = HASH_AlgSHA1;
8644             goto jpake2;
8645         case CKM_NSS_JPAKE_ROUND2_SHA256:
8646             hashType = HASH_AlgSHA256;
8647             goto jpake2;
8648         case CKM_NSS_JPAKE_ROUND2_SHA384:
8649             hashType = HASH_AlgSHA384;
8650             goto jpake2;
8651         case CKM_NSS_JPAKE_ROUND2_SHA512:
8652             hashType = HASH_AlgSHA512;
8653             goto jpake2;
8654         jpake2:
8655             if (pMechanism->pParameter == NULL ||
8656                 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params))
8657                 crv = CKR_MECHANISM_PARAM_INVALID;
8658             if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN))
8659                 crv = CKR_TEMPLATE_INCONSISTENT;
8660             if (crv == CKR_OK)
8661                 crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8662             if (crv == CKR_OK)
8663                 crv = jpake_Round2(hashType,
8664                                    (CK_NSS_JPAKERound2Params *)pMechanism->pParameter,
8665                                    sourceKey, key);
8666             break;
8667 
8668         case CKM_NSS_JPAKE_FINAL_SHA1:
8669             hashType = HASH_AlgSHA1;
8670             goto jpakeFinal;
8671         case CKM_NSS_JPAKE_FINAL_SHA256:
8672             hashType = HASH_AlgSHA256;
8673             goto jpakeFinal;
8674         case CKM_NSS_JPAKE_FINAL_SHA384:
8675             hashType = HASH_AlgSHA384;
8676             goto jpakeFinal;
8677         case CKM_NSS_JPAKE_FINAL_SHA512:
8678             hashType = HASH_AlgSHA512;
8679             goto jpakeFinal;
8680         jpakeFinal:
8681             if (pMechanism->pParameter == NULL ||
8682                 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams))
8683                 crv = CKR_MECHANISM_PARAM_INVALID;
8684             /* We purposely do not do the derive sensitivity check; we want to be
8685                able to derive non-sensitive keys while allowing the ROUND1 and
8686                ROUND2 keys to be sensitive (which they always are, since they are
8687                in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE
8688                in the template in order for the resultant keyblock key to be
8689                sensitive.
8690              */
8691             if (crv == CKR_OK)
8692                 crv = jpake_Final(hashType,
8693                                   (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter,
8694                                   sourceKey, key);
8695             break;
8696 
8697         case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA:         /* fall through */
8698         case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA:        /* fall through */
8699         case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */
8700         case CKM_SP800_108_COUNTER_KDF:                         /* fall through */
8701         case CKM_SP800_108_FEEDBACK_KDF:                        /* fall through */
8702         case CKM_SP800_108_DOUBLE_PIPELINE_KDF:
8703             crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8704             if (crv != CKR_OK) {
8705                 break;
8706             }
8707 
8708             crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize);
8709             break;
8710         default:
8711             crv = CKR_MECHANISM_INVALID;
8712     }
8713     if (att) {
8714         sftk_FreeAttribute(att);
8715     }
8716     sftk_FreeObject(sourceKey);
8717     if (crv != CKR_OK) {
8718         if (key)
8719             sftk_FreeObject(key);
8720         return crv;
8721     }
8722 
8723     /* link the key object into the list */
8724     if (key) {
8725         SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
8726         PORT_Assert(sessKey);
8727         /* get the session */
8728         sessKey->wasDerived = PR_TRUE;
8729         session = sftk_SessionFromHandle(hSession);
8730         if (session == NULL) {
8731             sftk_FreeObject(key);
8732             return CKR_HOST_MEMORY;
8733         }
8734 
8735         crv = sftk_handleObject(key, session);
8736         session->lastOpWasFIPS = key->isFIPS;
8737         sftk_FreeSession(session);
8738         *phKey = key->handle;
8739         sftk_FreeObject(key);
8740     }
8741     return crv;
8742 }
8743 
8744 /* NSC_GetFunctionStatus obtains an updated status of a function running
8745  * in parallel with an application. */
8746 CK_RV
NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)8747 NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
8748 {
8749     CHECK_FORK();
8750 
8751     return CKR_FUNCTION_NOT_PARALLEL;
8752 }
8753 
8754 /* NSC_CancelFunction cancels a function running in parallel */
8755 CK_RV
NSC_CancelFunction(CK_SESSION_HANDLE hSession)8756 NSC_CancelFunction(CK_SESSION_HANDLE hSession)
8757 {
8758     CHECK_FORK();
8759 
8760     return CKR_FUNCTION_NOT_PARALLEL;
8761 }
8762 
8763 /* NSC_GetOperationState saves the state of the cryptographic
8764  * operation in a session.
8765  * NOTE: This code only works for digest functions for now. eventually need
8766  * to add full flatten/resurect to our state stuff so that all types of state
8767  * can be saved */
8768 CK_RV
NSC_GetOperationState(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pOperationState,CK_ULONG_PTR pulOperationStateLen)8769 NSC_GetOperationState(CK_SESSION_HANDLE hSession,
8770                       CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
8771 {
8772     SFTKSessionContext *context;
8773     SFTKSession *session;
8774     CK_RV crv;
8775     CK_ULONG pOSLen = *pulOperationStateLen;
8776 
8777     CHECK_FORK();
8778 
8779     /* make sure we're legal */
8780     crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
8781     if (crv != CKR_OK)
8782         return crv;
8783 
8784     *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType);
8785     if (pOperationState == NULL) {
8786         sftk_FreeSession(session);
8787         return CKR_OK;
8788     } else {
8789         if (pOSLen < *pulOperationStateLen) {
8790             return CKR_BUFFER_TOO_SMALL;
8791         }
8792     }
8793     PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType));
8794     pOperationState += sizeof(SFTKContextType);
8795     PORT_Memcpy(pOperationState, &context->currentMech,
8796                 sizeof(CK_MECHANISM_TYPE));
8797     pOperationState += sizeof(CK_MECHANISM_TYPE);
8798     PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen);
8799     sftk_FreeSession(session);
8800     return CKR_OK;
8801 }
8802 
8803 #define sftk_Decrement(stateSize, len) \
8804     stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0;
8805 
8806 /* NSC_SetOperationState restores the state of the cryptographic
8807  * operation in a session. This is coded like it can restore lots of
8808  * states, but it only works for truly flat cipher structures. */
8809 CK_RV
NSC_SetOperationState(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pOperationState,CK_ULONG ulOperationStateLen,CK_OBJECT_HANDLE hEncryptionKey,CK_OBJECT_HANDLE hAuthenticationKey)8810 NSC_SetOperationState(CK_SESSION_HANDLE hSession,
8811                       CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
8812                       CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
8813 {
8814     SFTKSessionContext *context;
8815     SFTKSession *session;
8816     SFTKContextType type;
8817     CK_MECHANISM mech;
8818     CK_RV crv = CKR_OK;
8819 
8820     CHECK_FORK();
8821 
8822     while (ulOperationStateLen != 0) {
8823         /* get what type of state we're dealing with... */
8824         PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType));
8825 
8826         /* fix up session contexts based on type */
8827         session = sftk_SessionFromHandle(hSession);
8828         if (session == NULL)
8829             return CKR_SESSION_HANDLE_INVALID;
8830         context = sftk_ReturnContextByType(session, type);
8831         sftk_SetContextByType(session, type, NULL);
8832         if (context) {
8833             sftk_FreeContext(context);
8834         }
8835         pOperationState += sizeof(SFTKContextType);
8836         sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType));
8837 
8838         /* get the mechanism structure */
8839         PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE));
8840         pOperationState += sizeof(CK_MECHANISM_TYPE);
8841         sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
8842         /* should be filled in... but not necessary for hash */
8843         mech.pParameter = NULL;
8844         mech.ulParameterLen = 0;
8845         switch (type) {
8846             case SFTK_HASH:
8847                 crv = NSC_DigestInit(hSession, &mech);
8848                 if (crv != CKR_OK)
8849                     break;
8850                 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE,
8851                                       NULL);
8852                 if (crv != CKR_OK)
8853                     break;
8854                 PORT_Memcpy(context->cipherInfo, pOperationState,
8855                             context->cipherInfoLen);
8856                 pOperationState += context->cipherInfoLen;
8857                 sftk_Decrement(ulOperationStateLen, context->cipherInfoLen);
8858                 break;
8859             default:
8860                 /* do sign/encrypt/decrypt later */
8861                 crv = CKR_SAVED_STATE_INVALID;
8862         }
8863         sftk_FreeSession(session);
8864         if (crv != CKR_OK)
8865             break;
8866     }
8867     return crv;
8868 }
8869 
8870 /* Dual-function cryptographic operations */
8871 
8872 /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
8873  * operation. */
8874 CK_RV
NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen,CK_BYTE_PTR pEncryptedPart,CK_ULONG_PTR pulEncryptedPartLen)8875 NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
8876                         CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
8877                         CK_ULONG_PTR pulEncryptedPartLen)
8878 {
8879     CK_RV crv;
8880 
8881     CHECK_FORK();
8882 
8883     crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
8884                             pulEncryptedPartLen);
8885     if (crv != CKR_OK)
8886         return crv;
8887     crv = NSC_DigestUpdate(hSession, pPart, ulPartLen);
8888 
8889     return crv;
8890 }
8891 
8892 /* NSC_DecryptDigestUpdate continues a multiple-part decryption and
8893  * digesting operation. */
8894 CK_RV
NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedPart,CK_ULONG ulEncryptedPartLen,CK_BYTE_PTR pPart,CK_ULONG_PTR pulPartLen)8895 NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
8896                         CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
8897                         CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
8898 {
8899     CK_RV crv;
8900 
8901     CHECK_FORK();
8902 
8903     crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen,
8904                             pPart, pulPartLen);
8905     if (crv != CKR_OK)
8906         return crv;
8907     crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen);
8908 
8909     return crv;
8910 }
8911 
8912 /* NSC_SignEncryptUpdate continues a multiple-part signing and
8913  * encryption operation. */
8914 CK_RV
NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen,CK_BYTE_PTR pEncryptedPart,CK_ULONG_PTR pulEncryptedPartLen)8915 NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
8916                       CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
8917                       CK_ULONG_PTR pulEncryptedPartLen)
8918 {
8919     CK_RV crv;
8920 
8921     CHECK_FORK();
8922 
8923     crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
8924                             pulEncryptedPartLen);
8925     if (crv != CKR_OK)
8926         return crv;
8927     crv = NSC_SignUpdate(hSession, pPart, ulPartLen);
8928 
8929     return crv;
8930 }
8931 
8932 /* NSC_DecryptVerifyUpdate continues a multiple-part decryption
8933  * and verify operation. */
8934 CK_RV
NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)8935 NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
8936                         CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
8937                         CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
8938 {
8939     CK_RV crv;
8940 
8941     CHECK_FORK();
8942 
8943     crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
8944                             pData, pulDataLen);
8945     if (crv != CKR_OK)
8946         return crv;
8947     crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
8948 
8949     return crv;
8950 }
8951 
8952 /* NSC_DigestKey continues a multi-part message-digesting operation,
8953  * by digesting the value of a secret key as part of the data already digested.
8954  */
8955 CK_RV
NSC_DigestKey(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hKey)8956 NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
8957 {
8958     SFTKSession *session = NULL;
8959     SFTKObject *key = NULL;
8960     SFTKAttribute *att;
8961     CK_RV crv;
8962 
8963     CHECK_FORK();
8964 
8965     session = sftk_SessionFromHandle(hSession);
8966     if (session == NULL)
8967         return CKR_SESSION_HANDLE_INVALID;
8968 
8969     key = sftk_ObjectFromHandle(hKey, session);
8970     sftk_FreeSession(session);
8971     if (key == NULL)
8972         return CKR_KEY_HANDLE_INVALID;
8973 
8974     /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
8975 
8976     /* make sure it's a valid  key for this operation */
8977     if (key->objclass != CKO_SECRET_KEY) {
8978         sftk_FreeObject(key);
8979         return CKR_KEY_TYPE_INCONSISTENT;
8980     }
8981     /* get the key value */
8982     att = sftk_FindAttribute(key, CKA_VALUE);
8983     sftk_FreeObject(key);
8984     if (!att) {
8985         return CKR_KEY_HANDLE_INVALID;
8986     }
8987     crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue,
8988                            att->attrib.ulValueLen);
8989     sftk_FreeAttribute(att);
8990     return crv;
8991 }
8992