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