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