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, ¶ms->prime, key, CKA_PRIME);
4167 if (crv != CKR_OK) {
4168 goto loser;
4169 }
4170 crv = sftk_Attribute2SSecItem(arena, ¶ms->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, ¶ms, &vfy);
4209 } else {
4210 rv = PQG_ParamGenSeedLen(j, seedBits / 8, ¶ms, &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, ¶ms, &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, ¶ms->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