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_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
6301 if (crv != CKR_OK)
6302 break;
6303 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6304 sizeof(keyType));
6305 if (crv != CKR_OK)
6306 break;
6307 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6308 sizeof(CK_BBOOL));
6309 if (crv != CKR_OK)
6310 break;
6311 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6312 sizeof(CK_BBOOL));
6313 if (crv != CKR_OK)
6314 break;
6315 crv = sftk_AddAttributeType(key, CKA_PRIME,
6316 sftk_item_expand(&lpk->u.dsa.params.prime));
6317 if (crv != CKR_OK)
6318 break;
6319 crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
6320 sftk_item_expand(&lpk->u.dsa.params.subPrime));
6321 if (crv != CKR_OK)
6322 break;
6323 crv = sftk_AddAttributeType(key, CKA_BASE,
6324 sftk_item_expand(&lpk->u.dsa.params.base));
6325 if (crv != CKR_OK)
6326 break;
6327 crv = sftk_AddAttributeType(key, CKA_VALUE,
6328 sftk_item_expand(&lpk->u.dsa.privateValue));
6329 if (crv != CKR_OK)
6330 break;
6331 break;
6332 #ifdef notdef
6333 case NSSLOWKEYDHKey:
6334 template = dhTemplate;
6335 templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE);
6336 keyType = CKK_DH;
6337 break;
6338 #endif
6339 /* what about fortezza??? */
6340 case NSSLOWKEYECKey:
6341 keyType = CKK_EC;
6342 crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
6343 if (crv != CKR_OK)
6344 break;
6345 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6346 sizeof(keyType));
6347 if (crv != CKR_OK)
6348 break;
6349 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6350 sizeof(CK_BBOOL));
6351 if (crv != CKR_OK)
6352 break;
6353 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6354 sizeof(CK_BBOOL));
6355 if (crv != CKR_OK)
6356 break;
6357 crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue,
6358 sizeof(CK_BBOOL));
6359 if (crv != CKR_OK)
6360 break;
6361 crv = sftk_AddAttributeType(key, CKA_EC_PARAMS,
6362 sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding));
6363 if (crv != CKR_OK)
6364 break;
6365 crv = sftk_AddAttributeType(key, CKA_VALUE,
6366 sftk_item_expand(&lpk->u.ec.privateValue));
6367 if (crv != CKR_OK)
6368 break;
6369 /* XXX Do we need to decode the EC Params here ?? */
6370 break;
6371 default:
6372 crv = CKR_KEY_TYPE_INCONSISTENT;
6373 break;
6374 }
6375
6376 if (crv != CKR_OK) {
6377 goto loser;
6378 }
6379
6380 /* For RSA-PSS, record the original algorithm parameters so
6381 * they can be encrypted altoghether when wrapping */
6382 if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
6383 NSSLOWKEYSubjectPublicKeyInfo spki;
6384 NSSLOWKEYPublicKey pubk;
6385 SECItem *publicKeyInfo;
6386
6387 memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo));
6388 rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm);
6389 if (rv != SECSuccess) {
6390 crv = CKR_HOST_MEMORY;
6391 goto loser;
6392 }
6393
6394 prepare_low_rsa_pub_key_for_asn1(&pubk);
6395
6396 rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus);
6397 if (rv != SECSuccess) {
6398 crv = CKR_HOST_MEMORY;
6399 goto loser;
6400 }
6401 rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent);
6402 if (rv != SECSuccess) {
6403 crv = CKR_HOST_MEMORY;
6404 goto loser;
6405 }
6406
6407 if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey,
6408 &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) {
6409 crv = CKR_HOST_MEMORY;
6410 goto loser;
6411 }
6412
6413 publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL,
6414 &spki, nsslowkey_SubjectPublicKeyInfoTemplate);
6415 if (!publicKeyInfo) {
6416 crv = CKR_HOST_MEMORY;
6417 goto loser;
6418 }
6419 crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO,
6420 sftk_item_expand(publicKeyInfo));
6421 }
6422
6423 loser:
6424 if (lpk) {
6425 nsslowkey_DestroyPrivateKey(lpk);
6426 }
6427
6428 if (crv != CKR_OK) {
6429 return SECFailure;
6430 }
6431
6432 return SECSuccess;
6433 }
6434
6435 /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
6436 CK_RV
NSC_UnwrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hUnwrappingKey,CK_BYTE_PTR pWrappedKey,CK_ULONG ulWrappedKeyLen,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)6437 NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
6438 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
6439 CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
6440 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
6441 CK_OBJECT_HANDLE_PTR phKey)
6442 {
6443 SFTKObject *key = NULL;
6444 SFTKSession *session;
6445 CK_ULONG key_length = 0;
6446 unsigned char *buf = NULL;
6447 CK_RV crv = CKR_OK;
6448 int i;
6449 CK_ULONG bsize = ulWrappedKeyLen;
6450 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
6451 SECItem bpki;
6452 CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
6453
6454 CHECK_FORK();
6455
6456 if (!slot) {
6457 return CKR_SESSION_HANDLE_INVALID;
6458 }
6459 /*
6460 * now lets create an object to hang the attributes off of
6461 */
6462 key = sftk_NewObject(slot); /* fill in the handle later */
6463 if (key == NULL) {
6464 return CKR_HOST_MEMORY;
6465 }
6466
6467 /*
6468 * load the template values into the object
6469 */
6470 for (i = 0; i < (int)ulAttributeCount; i++) {
6471 if (pTemplate[i].type == CKA_VALUE_LEN) {
6472 key_length = *(CK_ULONG *)pTemplate[i].pValue;
6473 continue;
6474 }
6475 if (pTemplate[i].type == CKA_CLASS) {
6476 target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
6477 }
6478 crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
6479 if (crv != CKR_OK)
6480 break;
6481 }
6482 if (crv != CKR_OK) {
6483 sftk_FreeObject(key);
6484 return crv;
6485 }
6486
6487 crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP,
6488 CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE);
6489 if (crv != CKR_OK) {
6490 sftk_FreeObject(key);
6491 return sftk_mapWrap(crv);
6492 }
6493
6494 /* allocate the buffer to decrypt into
6495 * this assumes the unwrapped key is never larger than the
6496 * wrapped key. For all the mechanisms we support this is true */
6497 buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen);
6498 bsize = ulWrappedKeyLen;
6499
6500 crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
6501 if (crv != CKR_OK) {
6502 sftk_FreeObject(key);
6503 PORT_Free(buf);
6504 return sftk_mapWrap(crv);
6505 }
6506
6507 switch (target_type) {
6508 case CKO_SECRET_KEY:
6509 if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) {
6510 crv = CKR_TEMPLATE_INCOMPLETE;
6511 break;
6512 }
6513
6514 if (key_length == 0 || key_length > bsize) {
6515 key_length = bsize;
6516 }
6517 if (key_length > MAX_KEY_LEN) {
6518 crv = CKR_TEMPLATE_INCONSISTENT;
6519 break;
6520 }
6521
6522 /* add the value */
6523 crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
6524 break;
6525 case CKO_PRIVATE_KEY:
6526 bpki.data = (unsigned char *)buf;
6527 bpki.len = bsize;
6528 crv = CKR_OK;
6529 if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) {
6530 crv = CKR_TEMPLATE_INCOMPLETE;
6531 }
6532 break;
6533 default:
6534 crv = CKR_TEMPLATE_INCONSISTENT;
6535 break;
6536 }
6537
6538 PORT_ZFree(buf, bsize);
6539 if (crv != CKR_OK) {
6540 sftk_FreeObject(key);
6541 return crv;
6542 }
6543
6544 /* get the session */
6545 session = sftk_SessionFromHandle(hSession);
6546 if (session == NULL) {
6547 sftk_FreeObject(key);
6548 return CKR_SESSION_HANDLE_INVALID;
6549 }
6550
6551 /* mark the key as FIPS if the previous operation was all FIPS */
6552 key->isFIPS = session->lastOpWasFIPS;
6553
6554 /*
6555 * handle the base object stuff
6556 */
6557 crv = sftk_handleObject(key, session);
6558 *phKey = key->handle;
6559 sftk_FreeSession(session);
6560 sftk_FreeObject(key);
6561
6562 return crv;
6563 }
6564
6565 /*
6566 * The SSL key gen mechanism create's lots of keys. This function handles the
6567 * details of each of these key creation.
6568 */
6569 static CK_RV
sftk_buildSSLKey(CK_SESSION_HANDLE hSession,SFTKObject * baseKey,PRBool isMacKey,unsigned char * keyBlock,unsigned int keySize,CK_OBJECT_HANDLE * keyHandle)6570 sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey,
6571 PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
6572 CK_OBJECT_HANDLE *keyHandle)
6573 {
6574 SFTKObject *key;
6575 SFTKSession *session;
6576 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
6577 CK_BBOOL cktrue = CK_TRUE;
6578 CK_BBOOL ckfalse = CK_FALSE;
6579 CK_RV crv = CKR_HOST_MEMORY;
6580
6581 /*
6582 * now lets create an object to hang the attributes off of
6583 */
6584 *keyHandle = CK_INVALID_HANDLE;
6585 key = sftk_NewObject(baseKey->slot);
6586 if (key == NULL)
6587 return CKR_HOST_MEMORY;
6588 sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE;
6589
6590 crv = sftk_CopyObject(key, baseKey);
6591 if (crv != CKR_OK)
6592 goto loser;
6593 if (isMacKey) {
6594 crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
6595 if (crv != CKR_OK)
6596 goto loser;
6597 crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
6598 if (crv != CKR_OK)
6599 goto loser;
6600 crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL));
6601 if (crv != CKR_OK)
6602 goto loser;
6603 crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL));
6604 if (crv != CKR_OK)
6605 goto loser;
6606 crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
6607 if (crv != CKR_OK)
6608 goto loser;
6609 crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
6610 if (crv != CKR_OK)
6611 goto loser;
6612 crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL));
6613 if (crv != CKR_OK)
6614 goto loser;
6615 crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL));
6616 if (crv != CKR_OK)
6617 goto loser;
6618 }
6619 crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize);
6620 if (crv != CKR_OK)
6621 goto loser;
6622
6623 /* get the session */
6624 crv = CKR_HOST_MEMORY;
6625 session = sftk_SessionFromHandle(hSession);
6626 if (session == NULL) {
6627 goto loser;
6628 }
6629
6630 crv = sftk_handleObject(key, session);
6631 sftk_FreeSession(session);
6632 *keyHandle = key->handle;
6633 loser:
6634 if (key)
6635 sftk_FreeObject(key);
6636 return crv;
6637 }
6638
6639 /*
6640 * if there is an error, we need to free the keys we already created in SSL
6641 * This is the routine that will do it..
6642 */
6643 static void
sftk_freeSSLKeys(CK_SESSION_HANDLE session,CK_SSL3_KEY_MAT_OUT * returnedMaterial)6644 sftk_freeSSLKeys(CK_SESSION_HANDLE session,
6645 CK_SSL3_KEY_MAT_OUT *returnedMaterial)
6646 {
6647 if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) {
6648 NSC_DestroyObject(session, returnedMaterial->hClientMacSecret);
6649 }
6650 if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) {
6651 NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
6652 }
6653 if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) {
6654 NSC_DestroyObject(session, returnedMaterial->hClientKey);
6655 }
6656 if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) {
6657 NSC_DestroyObject(session, returnedMaterial->hServerKey);
6658 }
6659 }
6660
6661 /*
6662 * when deriving from sensitive and extractable keys, we need to preserve some
6663 * of the semantics in the derived key. This helper routine maintains these
6664 * semantics.
6665 */
6666 static CK_RV
sftk_DeriveSensitiveCheck(SFTKObject * baseKey,SFTKObject * destKey,PRBool canBeData)6667 sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey,
6668 PRBool canBeData)
6669 {
6670 PRBool hasSensitive;
6671 PRBool sensitive = PR_FALSE;
6672 CK_BBOOL bFalse = CK_FALSE;
6673 PRBool hasExtractable;
6674 PRBool extractable = PR_TRUE;
6675 CK_BBOOL bTrue = CK_TRUE;
6676 CK_RV crv = CKR_OK;
6677 SFTKAttribute *att;
6678 PRBool isData = PR_TRUE;
6679
6680 if (canBeData) {
6681 CK_OBJECT_CLASS objClass;
6682
6683 /* if the target key is actually data, don't set the unexpected
6684 * attributes */
6685 crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass);
6686 if (crv != CKR_OK) {
6687 return crv;
6688 }
6689 if (objClass == CKO_DATA) {
6690 return CKR_OK;
6691 }
6692
6693 /* if the base key is data, it doesn't have sensitive attributes,
6694 * allow the destKey to get it's own */
6695 crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass);
6696 if (crv != CKR_OK) {
6697 return crv;
6698 }
6699 if (objClass == CKO_DATA) {
6700 isData = PR_TRUE;
6701 }
6702 }
6703
6704 hasSensitive = PR_FALSE;
6705 att = sftk_FindAttribute(destKey, CKA_SENSITIVE);
6706 if (att) {
6707 hasSensitive = PR_TRUE;
6708 sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
6709 sftk_FreeAttribute(att);
6710 }
6711
6712 hasExtractable = PR_FALSE;
6713 att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE);
6714 if (att) {
6715 hasExtractable = PR_TRUE;
6716 extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
6717 sftk_FreeAttribute(att);
6718 }
6719
6720 /* don't make a key more accessible */
6721 if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive &&
6722 (sensitive == PR_FALSE)) {
6723 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6724 }
6725 if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable &&
6726 (extractable == PR_TRUE)) {
6727 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6728 }
6729
6730 /* inherit parent's sensitivity */
6731 if (!hasSensitive) {
6732 att = sftk_FindAttribute(baseKey, CKA_SENSITIVE);
6733 if (att != NULL) {
6734 crv = sftk_defaultAttribute(destKey,
6735 sftk_attr_expand(&att->attrib));
6736 sftk_FreeAttribute(att);
6737 } else if (isData) {
6738 crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE,
6739 &bFalse, sizeof(bFalse));
6740 } else {
6741 return CKR_KEY_TYPE_INCONSISTENT;
6742 }
6743 if (crv != CKR_OK)
6744 return crv;
6745 }
6746 if (!hasExtractable) {
6747 att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE);
6748 if (att != NULL) {
6749 crv = sftk_defaultAttribute(destKey,
6750 sftk_attr_expand(&att->attrib));
6751 sftk_FreeAttribute(att);
6752 } else if (isData) {
6753 crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE,
6754 &bTrue, sizeof(bTrue));
6755 } else {
6756 return CKR_KEY_TYPE_INCONSISTENT;
6757 }
6758 if (crv != CKR_OK)
6759 return crv;
6760 }
6761
6762 /* we should inherit the parent's always extractable/ never sensitive info,
6763 * but handleObject always forces this attributes, so we would need to do
6764 * something special. */
6765 return CKR_OK;
6766 }
6767
6768 /*
6769 * make known fixed PKCS #11 key types to their sizes in bytes
6770 */
6771 unsigned long
sftk_MapKeySize(CK_KEY_TYPE keyType)6772 sftk_MapKeySize(CK_KEY_TYPE keyType)
6773 {
6774 switch (keyType) {
6775 case CKK_CDMF:
6776 return 8;
6777 case CKK_DES:
6778 return 8;
6779 case CKK_DES2:
6780 return 16;
6781 case CKK_DES3:
6782 return 24;
6783 /* IDEA and CAST need to be added */
6784 default:
6785 break;
6786 }
6787 return 0;
6788 }
6789
6790 /* Inputs:
6791 * key_len: Length of derived key to be generated.
6792 * SharedSecret: a shared secret that is the output of a key agreement primitive.
6793 * SharedInfo: (Optional) some data shared by the entities computing the secret key.
6794 * SharedInfoLen: the length in octets of SharedInfo
6795 * Hash: The hash function to be used in the KDF
6796 * HashLen: the length in octets of the output of Hash
6797 * Output:
6798 * key: Pointer to a buffer containing derived key, if return value is SECSuccess.
6799 */
6800 static CK_RV
sftk_compute_ANSI_X9_63_kdf(CK_BYTE ** key,CK_ULONG key_len,SECItem * SharedSecret,CK_BYTE_PTR SharedInfo,CK_ULONG SharedInfoLen,SECStatus Hash (unsigned char *,const unsigned char *,PRUint32),CK_ULONG HashLen)6801 sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret,
6802 CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
6803 SECStatus Hash(unsigned char *, const unsigned char *, PRUint32),
6804 CK_ULONG HashLen)
6805 {
6806 unsigned char *buffer = NULL, *output_buffer = NULL;
6807 PRUint32 buffer_len, max_counter, i;
6808 SECStatus rv;
6809 CK_RV crv;
6810
6811 /* Check that key_len isn't too long. The maximum key length could be
6812 * greatly increased if the code below did not limit the 4-byte counter
6813 * to a maximum value of 255. */
6814 if (key_len > 254 * HashLen)
6815 return CKR_ARGUMENTS_BAD;
6816
6817 if (SharedInfo == NULL)
6818 SharedInfoLen = 0;
6819
6820 buffer_len = SharedSecret->len + 4 + SharedInfoLen;
6821 buffer = (CK_BYTE *)PORT_Alloc(buffer_len);
6822 if (buffer == NULL) {
6823 crv = CKR_HOST_MEMORY;
6824 goto loser;
6825 }
6826
6827 max_counter = key_len / HashLen;
6828 if (key_len > max_counter * HashLen)
6829 max_counter++;
6830
6831 output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen);
6832 if (output_buffer == NULL) {
6833 crv = CKR_HOST_MEMORY;
6834 goto loser;
6835 }
6836
6837 /* Populate buffer with SharedSecret || Counter || [SharedInfo]
6838 * where Counter is 0x00000001 */
6839 PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len);
6840 buffer[SharedSecret->len] = 0;
6841 buffer[SharedSecret->len + 1] = 0;
6842 buffer[SharedSecret->len + 2] = 0;
6843 buffer[SharedSecret->len + 3] = 1;
6844 if (SharedInfo) {
6845 PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen);
6846 }
6847
6848 for (i = 0; i < max_counter; i++) {
6849 rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len);
6850 if (rv != SECSuccess) {
6851 /* 'Hash' should not fail. */
6852 crv = CKR_FUNCTION_FAILED;
6853 goto loser;
6854 }
6855
6856 /* Increment counter (assumes max_counter < 255) */
6857 buffer[SharedSecret->len + 3]++;
6858 }
6859
6860 PORT_ZFree(buffer, buffer_len);
6861 if (key_len < max_counter * HashLen) {
6862 PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len);
6863 }
6864 *key = output_buffer;
6865
6866 return CKR_OK;
6867
6868 loser:
6869 if (buffer) {
6870 PORT_ZFree(buffer, buffer_len);
6871 }
6872 if (output_buffer) {
6873 PORT_ZFree(output_buffer, max_counter * HashLen);
6874 }
6875 return crv;
6876 }
6877
6878 static CK_RV
sftk_ANSI_X9_63_kdf(CK_BYTE ** key,CK_ULONG key_len,SECItem * SharedSecret,CK_BYTE_PTR SharedInfo,CK_ULONG SharedInfoLen,CK_EC_KDF_TYPE kdf)6879 sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len,
6880 SECItem *SharedSecret,
6881 CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
6882 CK_EC_KDF_TYPE kdf)
6883 {
6884 if (kdf == CKD_SHA1_KDF)
6885 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
6886 SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH);
6887 else if (kdf == CKD_SHA224_KDF)
6888 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
6889 SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH);
6890 else if (kdf == CKD_SHA256_KDF)
6891 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
6892 SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH);
6893 else if (kdf == CKD_SHA384_KDF)
6894 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
6895 SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH);
6896 else if (kdf == CKD_SHA512_KDF)
6897 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
6898 SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH);
6899 else
6900 return CKR_MECHANISM_INVALID;
6901 }
6902
6903 /*
6904 * Handle the derive from a block encryption cipher
6905 */
6906 CK_RV
sftk_DeriveEncrypt(SFTKCipher encrypt,void * cipherInfo,int blockSize,SFTKObject * key,CK_ULONG keySize,unsigned char * data,CK_ULONG len)6907 sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo,
6908 int blockSize, SFTKObject *key, CK_ULONG keySize,
6909 unsigned char *data, CK_ULONG len)
6910 {
6911 /* large enough for a 512-bit key */
6912 unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE];
6913 SECStatus rv;
6914 unsigned int outLen;
6915 CK_RV crv;
6916
6917 if ((len % blockSize) != 0) {
6918 return CKR_MECHANISM_PARAM_INVALID;
6919 }
6920 if (len > SFTK_MAX_DERIVE_KEY_SIZE) {
6921 return CKR_MECHANISM_PARAM_INVALID;
6922 }
6923 if (keySize && (len < keySize)) {
6924 return CKR_MECHANISM_PARAM_INVALID;
6925 }
6926 if (keySize == 0) {
6927 keySize = len;
6928 }
6929
6930 rv = (*encrypt)(cipherInfo, &tmpdata, &outLen, len, data, len);
6931 if (rv != SECSuccess) {
6932 crv = sftk_MapCryptError(PORT_GetError());
6933 return crv;
6934 }
6935
6936 crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize);
6937 PORT_Memset(tmpdata, 0, sizeof tmpdata);
6938 return crv;
6939 }
6940
6941 CK_RV
sftk_HKDF(CK_HKDF_PARAMS_PTR params,CK_SESSION_HANDLE hSession,SFTKObject * sourceKey,const unsigned char * sourceKeyBytes,int sourceKeyLen,SFTKObject * key,unsigned char * outKeyBytes,int keySize,PRBool canBeData,PRBool isFIPS)6942 sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession,
6943 SFTKObject *sourceKey, const unsigned char *sourceKeyBytes,
6944 int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes,
6945 int keySize, PRBool canBeData, PRBool isFIPS)
6946 {
6947 SFTKSession *session;
6948 SFTKAttribute *saltKey_att = NULL;
6949 const SECHashObject *rawHash;
6950 unsigned hashLen;
6951 unsigned genLen = 0;
6952 unsigned char hashbuf[HASH_LENGTH_MAX];
6953 unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH];
6954 unsigned char *keyBlockAlloc = NULL; /* allocated keyBlock */
6955 unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */
6956 const unsigned char *prk; /* psuedo-random key */
6957 CK_ULONG prkLen;
6958 const unsigned char *okm; /* output keying material */
6959 HASH_HashType hashType = GetHashTypeFromMechanism(params->prfHashMechanism);
6960 SFTKObject *saltKey = NULL;
6961 CK_RV crv = CKR_OK;
6962
6963 /* Spec says it should be the base hash, but also accept the HMAC */
6964 if (hashType == HASH_AlgNULL) {
6965 hashType = sftk_HMACMechanismToHash(params->prfHashMechanism);
6966 }
6967 rawHash = HASH_GetRawHashObject(hashType);
6968 if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) {
6969 return CKR_MECHANISM_INVALID;
6970 }
6971 hashLen = rawHash->length;
6972
6973 if ((!params->bExpand && !params->bExtract) ||
6974 (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
6975 (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
6976 return CKR_MECHANISM_PARAM_INVALID;
6977 }
6978 if ((params->bExpand && keySize == 0) ||
6979 (!params->bExpand && keySize > hashLen) ||
6980 (params->bExpand && keySize > 255 * hashLen)) {
6981 return CKR_TEMPLATE_INCONSISTENT;
6982 }
6983
6984 /* sourceKey is NULL if we are called from the POST, skip the
6985 * sensitiveCheck */
6986 if (sourceKey != NULL) {
6987 crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData);
6988 if (crv != CKR_OK)
6989 return crv;
6990 }
6991
6992 /* HKDF-Extract(salt, base key value) */
6993 if (params->bExtract) {
6994 CK_BYTE *salt;
6995 CK_ULONG saltLen;
6996 HMACContext *hmac;
6997 unsigned int bufLen;
6998
6999 switch (params->ulSaltType) {
7000 case CKF_HKDF_SALT_NULL:
7001 saltLen = hashLen;
7002 salt = hashbuf;
7003 memset(salt, 0, saltLen);
7004 break;
7005 case CKF_HKDF_SALT_DATA:
7006 salt = params->pSalt;
7007 saltLen = params->ulSaltLen;
7008 if ((salt == NULL) || (params->ulSaltLen == 0)) {
7009 return CKR_MECHANISM_PARAM_INVALID;
7010 }
7011 break;
7012 case CKF_HKDF_SALT_KEY:
7013 /* lookup key */
7014 session = sftk_SessionFromHandle(hSession);
7015 if (session == NULL) {
7016 return CKR_SESSION_HANDLE_INVALID;
7017 }
7018
7019 saltKey = sftk_ObjectFromHandle(params->hSaltKey, session);
7020 sftk_FreeSession(session);
7021 if (saltKey == NULL) {
7022 return CKR_KEY_HANDLE_INVALID;
7023 }
7024 /* if the base key is not fips, but the salt key is, the
7025 * resulting key can be fips */
7026 if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) {
7027 CK_MECHANISM mech;
7028 mech.mechanism = CKM_HKDF_DERIVE;
7029 mech.pParameter = params;
7030 mech.ulParameterLen = sizeof(*params);
7031 key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech,
7032 CKA_DERIVE, saltKey);
7033 }
7034 saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
7035 if (saltKey_att == NULL) {
7036 sftk_FreeObject(saltKey);
7037 return CKR_KEY_HANDLE_INVALID;
7038 }
7039 /* save the resulting salt */
7040 salt = saltKey_att->attrib.pValue;
7041 saltLen = saltKey_att->attrib.ulValueLen;
7042 break;
7043 default:
7044 return CKR_MECHANISM_PARAM_INVALID;
7045 break;
7046 }
7047
7048 hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
7049 if (saltKey_att) {
7050 sftk_FreeAttribute(saltKey_att);
7051 }
7052 if (saltKey) {
7053 sftk_FreeObject(saltKey);
7054 }
7055 if (!hmac) {
7056 return CKR_HOST_MEMORY;
7057 }
7058 HMAC_Begin(hmac);
7059 HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen);
7060 HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf));
7061 HMAC_Destroy(hmac, PR_TRUE);
7062 PORT_Assert(bufLen == rawHash->length);
7063 prk = hashbuf;
7064 prkLen = bufLen;
7065 } else {
7066 /* PRK = base key value */
7067 prk = sourceKeyBytes;
7068 prkLen = sourceKeyLen;
7069 }
7070
7071 /* HKDF-Expand */
7072 if (!params->bExpand) {
7073 okm = prk;
7074 keySize = genLen = hashLen;
7075 } else {
7076 /* T(1) = HMAC-Hash(prk, "" | info | 0x01)
7077 * T(n) = HMAC-Hash(prk, T(n-1) | info | n
7078 * key material = T(1) | ... | T(n)
7079 */
7080 HMACContext *hmac;
7081 CK_BYTE bi;
7082 unsigned iterations;
7083
7084 genLen = PR_ROUNDUP(keySize, hashLen);
7085 iterations = genLen / hashLen;
7086
7087 if (genLen > sizeof(keyBlock)) {
7088 keyBlockAlloc = PORT_Alloc(genLen);
7089 if (keyBlockAlloc == NULL) {
7090 return CKR_HOST_MEMORY;
7091 }
7092 keyBlockData = keyBlockAlloc;
7093 }
7094 hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
7095 if (hmac == NULL) {
7096 PORT_Free(keyBlockAlloc);
7097 return CKR_HOST_MEMORY;
7098 }
7099 for (bi = 1; bi <= iterations && bi > 0; ++bi) {
7100 unsigned len;
7101 HMAC_Begin(hmac);
7102 if (bi > 1) {
7103 HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen);
7104 }
7105 if (params->ulInfoLen != 0) {
7106 HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
7107 }
7108 HMAC_Update(hmac, &bi, 1);
7109 HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len,
7110 hashLen);
7111 PORT_Assert(len == hashLen);
7112 }
7113 HMAC_Destroy(hmac, PR_TRUE);
7114 okm = &keyBlockData[0];
7115 }
7116 /* key material = okm */
7117 crv = CKR_OK;
7118 if (key) {
7119 crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
7120 } else {
7121 PORT_Assert(outKeyBytes != NULL);
7122 PORT_Memcpy(outKeyBytes, okm, keySize);
7123 }
7124 PORT_Memset(keyBlockData, 0, genLen);
7125 PORT_Memset(hashbuf, 0, sizeof(hashbuf));
7126 PORT_Free(keyBlockAlloc);
7127 return crv;
7128 }
7129
7130 /*
7131 * SSL Key generation given pre master secret
7132 */
7133 #define NUM_MIXERS 9
7134 static const char *const mixers[NUM_MIXERS] = {
7135 "A",
7136 "BB",
7137 "CCC",
7138 "DDDD",
7139 "EEEEE",
7140 "FFFFFF",
7141 "GGGGGGG",
7142 "HHHHHHHH",
7143 "IIIIIIIII"
7144 };
7145 #define SSL3_PMS_LENGTH 48
7146 #define SSL3_MASTER_SECRET_LENGTH 48
7147 #define SSL3_RANDOM_LENGTH 32
7148
7149 /* NSC_DeriveKey derives a key from a base key, creating a new key object. */
7150 CK_RV
NSC_DeriveKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hBaseKey,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)7151 NSC_DeriveKey(CK_SESSION_HANDLE hSession,
7152 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
7153 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
7154 CK_OBJECT_HANDLE_PTR phKey)
7155 {
7156 SFTKSession *session;
7157 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
7158 SFTKObject *key;
7159 SFTKObject *sourceKey;
7160 SFTKAttribute *att = NULL;
7161 SFTKAttribute *att2 = NULL;
7162 unsigned char *buf;
7163 SHA1Context *sha;
7164 MD5Context *md5;
7165 MD2Context *md2;
7166 CK_ULONG macSize;
7167 CK_ULONG tmpKeySize;
7168 CK_ULONG IVSize;
7169 CK_ULONG keySize = 0;
7170 CK_RV crv = CKR_OK;
7171 CK_BBOOL cktrue = CK_TRUE;
7172 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
7173 CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
7174 CK_KEY_DERIVATION_STRING_DATA *stringPtr;
7175 PRBool isTLS = PR_FALSE;
7176 PRBool isDH = PR_FALSE;
7177 HASH_HashType tlsPrfHash = HASH_AlgNULL;
7178 SECStatus rv;
7179 int i;
7180 unsigned int outLen;
7181 unsigned char sha_out[SHA1_LENGTH];
7182 unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH];
7183 PRBool isFIPS;
7184 HASH_HashType hashType;
7185 CK_MECHANISM_TYPE hashMech;
7186 PRBool extractValue = PR_TRUE;
7187 CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS ikeAppB;
7188 CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *pIkeAppB;
7189
7190 CHECK_FORK();
7191
7192 if (!slot) {
7193 return CKR_SESSION_HANDLE_INVALID;
7194 }
7195 if (!pMechanism) {
7196 return CKR_MECHANISM_PARAM_INVALID;
7197 }
7198 CK_MECHANISM_TYPE mechanism = pMechanism->mechanism;
7199
7200 /*
7201 * now lets create an object to hang the attributes off of
7202 */
7203 if (phKey)
7204 *phKey = CK_INVALID_HANDLE;
7205
7206 key = sftk_NewObject(slot); /* fill in the handle later */
7207 if (key == NULL) {
7208 return CKR_HOST_MEMORY;
7209 }
7210 isFIPS = sftk_isFIPS(slot->slotID);
7211
7212 /*
7213 * load the template values into the object
7214 */
7215 for (i = 0; i < (int)ulAttributeCount; i++) {
7216 crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
7217 if (crv != CKR_OK)
7218 break;
7219
7220 if (pTemplate[i].type == CKA_KEY_TYPE) {
7221 keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
7222 }
7223 if (pTemplate[i].type == CKA_VALUE_LEN) {
7224 keySize = *(CK_ULONG *)pTemplate[i].pValue;
7225 }
7226 }
7227 if (crv != CKR_OK) {
7228 sftk_FreeObject(key);
7229 return crv;
7230 }
7231
7232 if (keySize == 0) {
7233 keySize = sftk_MapKeySize(keyType);
7234 }
7235
7236 switch (mechanism) {
7237 case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */
7238 case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */
7239 case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */
7240 case CKM_NSS_JPAKE_ROUND2_SHA512:
7241 extractValue = PR_FALSE;
7242 classType = CKO_PRIVATE_KEY;
7243 break;
7244 case CKM_NSS_PUB_FROM_PRIV:
7245 extractValue = PR_FALSE;
7246 classType = CKO_PUBLIC_KEY;
7247 break;
7248 case CKM_HKDF_DATA: /* fall through */
7249 case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */
7250 case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
7251 case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA:
7252 classType = CKO_DATA;
7253 break;
7254 case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */
7255 case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
7256 case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
7257 case CKM_NSS_JPAKE_FINAL_SHA512:
7258 extractValue = PR_FALSE;
7259 /* fall through */
7260 default:
7261 classType = CKO_SECRET_KEY;
7262 }
7263
7264 crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType));
7265 if (crv != CKR_OK) {
7266 sftk_FreeObject(key);
7267 return crv;
7268 }
7269
7270 /* look up the base key we're deriving with */
7271 session = sftk_SessionFromHandle(hSession);
7272 if (session == NULL) {
7273 sftk_FreeObject(key);
7274 return CKR_SESSION_HANDLE_INVALID;
7275 }
7276
7277 sourceKey = sftk_ObjectFromHandle(hBaseKey, session);
7278 sftk_FreeSession(session);
7279 /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's
7280 * FIPS state below. */
7281 session->lastOpWasFIPS = PR_FALSE;
7282 if (sourceKey == NULL) {
7283 sftk_FreeObject(key);
7284 return CKR_KEY_HANDLE_INVALID;
7285 }
7286
7287 if (extractValue) {
7288 /* get the value of the base key */
7289 att = sftk_FindAttribute(sourceKey, CKA_VALUE);
7290 if (att == NULL) {
7291 sftk_FreeObject(key);
7292 sftk_FreeObject(sourceKey);
7293 return CKR_KEY_HANDLE_INVALID;
7294 }
7295 }
7296 key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey);
7297
7298 switch (mechanism) {
7299 /* get a public key from a private key. nsslowkey_ConvertToPublickey()
7300 * will generate the public portion if it doesn't already exist. */
7301 case CKM_NSS_PUB_FROM_PRIV: {
7302 NSSLOWKEYPrivateKey *privKey;
7303 NSSLOWKEYPublicKey *pubKey;
7304 int error;
7305
7306 crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType);
7307 if (crv != CKR_OK) {
7308 break;
7309 }
7310
7311 /* privKey is stored in sourceKey and will be destroyed when
7312 * the sourceKey is freed. */
7313 privKey = sftk_GetPrivKey(sourceKey, keyType, &crv);
7314 if (privKey == NULL) {
7315 break;
7316 }
7317 pubKey = nsslowkey_ConvertToPublicKey(privKey);
7318 if (pubKey == NULL) {
7319 error = PORT_GetError();
7320 crv = sftk_MapCryptError(error);
7321 break;
7322 }
7323 crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey);
7324 nsslowkey_DestroyPublicKey(pubKey);
7325 break;
7326 }
7327 case CKM_NSS_IKE_PRF_DERIVE:
7328 if (pMechanism->ulParameterLen !=
7329 sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) {
7330 crv = CKR_MECHANISM_PARAM_INVALID;
7331 break;
7332 }
7333 crv = sftk_ike_prf(hSession, att,
7334 (CK_NSS_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key);
7335 break;
7336 case CKM_NSS_IKE1_PRF_DERIVE:
7337 if (pMechanism->ulParameterLen !=
7338 sizeof(CK_NSS_IKE1_PRF_DERIVE_PARAMS)) {
7339 crv = CKR_MECHANISM_PARAM_INVALID;
7340 break;
7341 }
7342 crv = sftk_ike1_prf(hSession, att,
7343 (CK_NSS_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter,
7344 key, keySize);
7345 break;
7346 case CKM_NSS_IKE1_APP_B_PRF_DERIVE:
7347 pIkeAppB = (CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *)pMechanism->pParameter;
7348 if (pMechanism->ulParameterLen ==
7349 sizeof(CK_MECHANISM_TYPE)) {
7350 ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter;
7351 ikeAppB.bHasKeygxy = PR_FALSE;
7352 ikeAppB.hKeygxy = CK_INVALID_HANDLE;
7353 ikeAppB.pExtraData = NULL;
7354 ikeAppB.ulExtraDataLen = 0;
7355 pIkeAppB = &ikeAppB;
7356 } else if (pMechanism->ulParameterLen !=
7357 sizeof(CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS)) {
7358 crv = CKR_MECHANISM_PARAM_INVALID;
7359 break;
7360 }
7361 crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key,
7362 keySize);
7363 break;
7364 case CKM_NSS_IKE_PRF_PLUS_DERIVE:
7365 if (pMechanism->ulParameterLen !=
7366 sizeof(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS)) {
7367 crv = CKR_MECHANISM_PARAM_INVALID;
7368 break;
7369 }
7370 crv = sftk_ike_prf_plus(hSession, att,
7371 (CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter,
7372 key, keySize);
7373 break;
7374 /*
7375 * generate the master secret
7376 */
7377 case CKM_TLS12_MASTER_KEY_DERIVE:
7378 case CKM_TLS12_MASTER_KEY_DERIVE_DH:
7379 case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256:
7380 case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256:
7381 case CKM_TLS_MASTER_KEY_DERIVE:
7382 case CKM_TLS_MASTER_KEY_DERIVE_DH:
7383 case CKM_SSL3_MASTER_KEY_DERIVE:
7384 case CKM_SSL3_MASTER_KEY_DERIVE_DH: {
7385 CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
7386 SSL3RSAPreMasterSecret *rsa_pms;
7387 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
7388
7389 if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) ||
7390 (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
7391 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) {
7392 crv = CKR_MECHANISM_PARAM_INVALID;
7393 break;
7394 }
7395 CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master =
7396 (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter;
7397 tlsPrfHash = GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
7398 if (tlsPrfHash == HASH_AlgNULL) {
7399 crv = CKR_MECHANISM_PARAM_INVALID;
7400 break;
7401 }
7402 } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) ||
7403 (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) {
7404 tlsPrfHash = HASH_AlgSHA256;
7405 }
7406
7407 if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) &&
7408 (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) {
7409 isTLS = PR_TRUE;
7410 }
7411 if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) ||
7412 (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) ||
7413 (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) ||
7414 (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
7415 isDH = PR_TRUE;
7416 }
7417
7418 /* first do the consistency checks */
7419 if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
7420 crv = CKR_KEY_TYPE_INCONSISTENT;
7421 break;
7422 }
7423 att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7424 if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
7425 CKK_GENERIC_SECRET)) {
7426 if (att2)
7427 sftk_FreeAttribute(att2);
7428 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7429 break;
7430 }
7431 sftk_FreeAttribute(att2);
7432 if (keyType != CKK_GENERIC_SECRET) {
7433 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7434 break;
7435 }
7436 if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
7437 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7438 break;
7439 }
7440
7441 /* finally do the key gen */
7442 ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
7443 pMechanism->pParameter;
7444
7445 if (ssl3_master->pVersion) {
7446 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
7447 rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
7448 /* don't leak more key material then necessary for SSL to work */
7449 if ((sessKey == NULL) || sessKey->wasDerived) {
7450 ssl3_master->pVersion->major = 0xff;
7451 ssl3_master->pVersion->minor = 0xff;
7452 } else {
7453 ssl3_master->pVersion->major = rsa_pms->client_version[0];
7454 ssl3_master->pVersion->minor = rsa_pms->client_version[1];
7455 }
7456 }
7457 if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
7458 crv = CKR_MECHANISM_PARAM_INVALID;
7459 break;
7460 }
7461 if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
7462 crv = CKR_MECHANISM_PARAM_INVALID;
7463 break;
7464 }
7465 PORT_Memcpy(crsrdata,
7466 ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
7467 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
7468 ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
7469
7470 if (isTLS) {
7471 SECStatus status;
7472 SECItem crsr = { siBuffer, NULL, 0 };
7473 SECItem master = { siBuffer, NULL, 0 };
7474 SECItem pms = { siBuffer, NULL, 0 };
7475
7476 crsr.data = crsrdata;
7477 crsr.len = sizeof crsrdata;
7478 master.data = key_block;
7479 master.len = SSL3_MASTER_SECRET_LENGTH;
7480 pms.data = (unsigned char *)att->attrib.pValue;
7481 pms.len = att->attrib.ulValueLen;
7482
7483 if (tlsPrfHash != HASH_AlgNULL) {
7484 status = TLS_P_hash(tlsPrfHash, &pms, "master secret",
7485 &crsr, &master, isFIPS);
7486 } else {
7487 status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS);
7488 }
7489 if (status != SECSuccess) {
7490 PORT_Memset(crsrdata, 0, sizeof crsrdata);
7491 crv = CKR_FUNCTION_FAILED;
7492 break;
7493 }
7494 } else {
7495 /* now allocate the hash contexts */
7496 md5 = MD5_NewContext();
7497 if (md5 == NULL) {
7498 PORT_Memset(crsrdata, 0, sizeof crsrdata);
7499 crv = CKR_HOST_MEMORY;
7500 break;
7501 }
7502 sha = SHA1_NewContext();
7503 if (sha == NULL) {
7504 PORT_Memset(crsrdata, 0, sizeof crsrdata);
7505 PORT_Free(md5);
7506 crv = CKR_HOST_MEMORY;
7507 break;
7508 }
7509 for (i = 0; i < 3; i++) {
7510 SHA1_Begin(sha);
7511 SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
7512 SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
7513 att->attrib.ulValueLen);
7514 SHA1_Update(sha, crsrdata, sizeof crsrdata);
7515 SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
7516 PORT_Assert(outLen == SHA1_LENGTH);
7517
7518 MD5_Begin(md5);
7519 MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
7520 att->attrib.ulValueLen);
7521 MD5_Update(md5, sha_out, outLen);
7522 MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
7523 PORT_Assert(outLen == MD5_LENGTH);
7524 }
7525 PORT_Free(md5);
7526 PORT_Free(sha);
7527 PORT_Memset(crsrdata, 0, sizeof crsrdata);
7528 PORT_Memset(sha_out, 0, sizeof sha_out);
7529 }
7530
7531 /* store the results */
7532 crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH);
7533 PORT_Memset(key_block, 0, sizeof key_block);
7534 if (crv != CKR_OK)
7535 break;
7536 keyType = CKK_GENERIC_SECRET;
7537 crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
7538 if (isTLS) {
7539 /* TLS's master secret is used to "sign" finished msgs with PRF. */
7540 /* XXX This seems like a hack. But SFTK_Derive only accepts
7541 * one "operation" argument. */
7542 crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
7543 if (crv != CKR_OK)
7544 break;
7545 crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
7546 if (crv != CKR_OK)
7547 break;
7548 /* While we're here, we might as well force this, too. */
7549 crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
7550 if (crv != CKR_OK)
7551 break;
7552 }
7553 break;
7554 }
7555
7556 /* Extended master key derivation [draft-ietf-tls-session-hash] */
7557 case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE:
7558 case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: {
7559 CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params;
7560 SSL3RSAPreMasterSecret *rsa_pms;
7561 SECStatus status;
7562 SECItem pms = { siBuffer, NULL, 0 };
7563 SECItem seed = { siBuffer, NULL, 0 };
7564 SECItem master = { siBuffer, NULL, 0 };
7565
7566 ems_params = (CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *)
7567 pMechanism->pParameter;
7568
7569 /* First do the consistency checks */
7570 if ((mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE) &&
7571 (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
7572 crv = CKR_KEY_TYPE_INCONSISTENT;
7573 break;
7574 }
7575 att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7576 if ((att2 == NULL) ||
7577 (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) {
7578 if (att2)
7579 sftk_FreeAttribute(att2);
7580 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7581 break;
7582 }
7583 sftk_FreeAttribute(att2);
7584 if (keyType != CKK_GENERIC_SECRET) {
7585 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7586 break;
7587 }
7588 if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
7589 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7590 break;
7591 }
7592
7593 /* Do the key derivation */
7594 pms.data = (unsigned char *)att->attrib.pValue;
7595 pms.len = att->attrib.ulValueLen;
7596 seed.data = ems_params->pSessionHash;
7597 seed.len = ems_params->ulSessionHashLen;
7598 master.data = key_block;
7599 master.len = SSL3_MASTER_SECRET_LENGTH;
7600 if (ems_params->prfHashMechanism == CKM_TLS_PRF) {
7601 /*
7602 * In this case, the session hash is the concatenation of SHA-1
7603 * and MD5, so it should be 36 bytes long.
7604 */
7605 if (seed.len != MD5_LENGTH + SHA1_LENGTH) {
7606 crv = CKR_TEMPLATE_INCONSISTENT;
7607 break;
7608 }
7609
7610 status = TLS_PRF(&pms, "extended master secret",
7611 &seed, &master, isFIPS);
7612 } else {
7613 const SECHashObject *hashObj;
7614
7615 tlsPrfHash = GetHashTypeFromMechanism(ems_params->prfHashMechanism);
7616 if (tlsPrfHash == HASH_AlgNULL) {
7617 crv = CKR_MECHANISM_PARAM_INVALID;
7618 break;
7619 }
7620
7621 hashObj = HASH_GetRawHashObject(tlsPrfHash);
7622 if (seed.len != hashObj->length) {
7623 crv = CKR_TEMPLATE_INCONSISTENT;
7624 break;
7625 }
7626
7627 status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret",
7628 &seed, &master, isFIPS);
7629 }
7630 if (status != SECSuccess) {
7631 crv = CKR_FUNCTION_FAILED;
7632 break;
7633 }
7634
7635 /* Reflect the version if required */
7636 if (ems_params->pVersion) {
7637 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
7638 rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
7639 /* don't leak more key material than necessary for SSL to work */
7640 if ((sessKey == NULL) || sessKey->wasDerived) {
7641 ems_params->pVersion->major = 0xff;
7642 ems_params->pVersion->minor = 0xff;
7643 } else {
7644 ems_params->pVersion->major = rsa_pms->client_version[0];
7645 ems_params->pVersion->minor = rsa_pms->client_version[1];
7646 }
7647 }
7648
7649 /* Store the results */
7650 crv = sftk_forceAttribute(key, CKA_VALUE, key_block,
7651 SSL3_MASTER_SECRET_LENGTH);
7652 PORT_Memset(key_block, 0, sizeof key_block);
7653 break;
7654 }
7655
7656 case CKM_TLS12_KEY_AND_MAC_DERIVE:
7657 case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256:
7658 case CKM_TLS_KEY_AND_MAC_DERIVE:
7659 case CKM_SSL3_KEY_AND_MAC_DERIVE: {
7660 CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
7661 CK_SSL3_KEY_MAT_OUT *ssl3_keys_out;
7662 CK_ULONG effKeySize;
7663 unsigned int block_needed;
7664 unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
7665
7666 if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) {
7667 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) {
7668 crv = CKR_MECHANISM_PARAM_INVALID;
7669 break;
7670 }
7671 CK_TLS12_KEY_MAT_PARAMS *tls12_keys =
7672 (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter;
7673 tlsPrfHash = GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
7674 if (tlsPrfHash == HASH_AlgNULL) {
7675 crv = CKR_MECHANISM_PARAM_INVALID;
7676 break;
7677 }
7678 } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) {
7679 tlsPrfHash = HASH_AlgSHA256;
7680 }
7681
7682 if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) {
7683 isTLS = PR_TRUE;
7684 }
7685
7686 crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
7687 if (crv != CKR_OK)
7688 break;
7689
7690 if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
7691 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7692 break;
7693 }
7694 att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7695 if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
7696 CKK_GENERIC_SECRET)) {
7697 if (att2)
7698 sftk_FreeAttribute(att2);
7699 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7700 break;
7701 }
7702 sftk_FreeAttribute(att2);
7703 md5 = MD5_NewContext();
7704 if (md5 == NULL) {
7705 crv = CKR_HOST_MEMORY;
7706 break;
7707 }
7708 sha = SHA1_NewContext();
7709 if (sha == NULL) {
7710 MD5_DestroyContext(md5, PR_TRUE);
7711 crv = CKR_HOST_MEMORY;
7712 break;
7713 }
7714
7715 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) {
7716 MD5_DestroyContext(md5, PR_TRUE);
7717 SHA1_DestroyContext(sha, PR_TRUE);
7718 crv = CKR_MECHANISM_PARAM_INVALID;
7719 break;
7720 }
7721 ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter;
7722
7723 PORT_Memcpy(srcrdata,
7724 ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
7725 PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
7726 ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
7727
7728 /*
7729 * clear out our returned keys so we can recover on failure
7730 */
7731 ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
7732 ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;
7733 ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;
7734 ssl3_keys_out->hClientKey = CK_INVALID_HANDLE;
7735 ssl3_keys_out->hServerKey = CK_INVALID_HANDLE;
7736
7737 /*
7738 * How much key material do we need?
7739 */
7740 macSize = ssl3_keys->ulMacSizeInBits / 8;
7741 effKeySize = ssl3_keys->ulKeySizeInBits / 8;
7742 IVSize = ssl3_keys->ulIVSizeInBits / 8;
7743 if (keySize == 0) {
7744 effKeySize = keySize;
7745 }
7746
7747 /* bIsExport must be false. */
7748 if (ssl3_keys->bIsExport) {
7749 MD5_DestroyContext(md5, PR_TRUE);
7750 SHA1_DestroyContext(sha, PR_TRUE);
7751 PORT_Memset(srcrdata, 0, sizeof srcrdata);
7752 crv = CKR_MECHANISM_PARAM_INVALID;
7753 break;
7754 }
7755
7756 block_needed = 2 * (macSize + effKeySize + IVSize);
7757 PORT_Assert(block_needed <= sizeof key_block);
7758 if (block_needed > sizeof key_block)
7759 block_needed = sizeof key_block;
7760
7761 /*
7762 * generate the key material: This looks amazingly similar to the
7763 * PMS code, and is clearly crying out for a function to provide it.
7764 */
7765 if (isTLS) {
7766 SECStatus status;
7767 SECItem srcr = { siBuffer, NULL, 0 };
7768 SECItem keyblk = { siBuffer, NULL, 0 };
7769 SECItem master = { siBuffer, NULL, 0 };
7770
7771 srcr.data = srcrdata;
7772 srcr.len = sizeof srcrdata;
7773 keyblk.data = key_block;
7774 keyblk.len = block_needed;
7775 master.data = (unsigned char *)att->attrib.pValue;
7776 master.len = att->attrib.ulValueLen;
7777
7778 if (tlsPrfHash != HASH_AlgNULL) {
7779 status = TLS_P_hash(tlsPrfHash, &master, "key expansion",
7780 &srcr, &keyblk, isFIPS);
7781 } else {
7782 status = TLS_PRF(&master, "key expansion", &srcr, &keyblk,
7783 isFIPS);
7784 }
7785 if (status != SECSuccess) {
7786 goto key_and_mac_derive_fail;
7787 }
7788 } else {
7789 unsigned int block_bytes = 0;
7790 /* key_block =
7791 * MD5(master_secret + SHA('A' + master_secret +
7792 * ServerHello.random + ClientHello.random)) +
7793 * MD5(master_secret + SHA('BB' + master_secret +
7794 * ServerHello.random + ClientHello.random)) +
7795 * MD5(master_secret + SHA('CCC' + master_secret +
7796 * ServerHello.random + ClientHello.random)) +
7797 * [...];
7798 */
7799 for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) {
7800 SHA1_Begin(sha);
7801 SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
7802 SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
7803 att->attrib.ulValueLen);
7804 SHA1_Update(sha, srcrdata, sizeof srcrdata);
7805 SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
7806 PORT_Assert(outLen == SHA1_LENGTH);
7807 MD5_Begin(md5);
7808 MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
7809 att->attrib.ulValueLen);
7810 MD5_Update(md5, sha_out, outLen);
7811 MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
7812 PORT_Assert(outLen == MD5_LENGTH);
7813 block_bytes += outLen;
7814 }
7815 PORT_Memset(sha_out, 0, sizeof sha_out);
7816 }
7817
7818 /*
7819 * Put the key material where it goes.
7820 */
7821 i = 0; /* now shows how much consumed */
7822
7823 /*
7824 * The key_block is partitioned as follows:
7825 * client_write_MAC_secret[CipherSpec.hash_size]
7826 */
7827 crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
7828 &ssl3_keys_out->hClientMacSecret);
7829 if (crv != CKR_OK)
7830 goto key_and_mac_derive_fail;
7831
7832 i += macSize;
7833
7834 /*
7835 * server_write_MAC_secret[CipherSpec.hash_size]
7836 */
7837 crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
7838 &ssl3_keys_out->hServerMacSecret);
7839 if (crv != CKR_OK) {
7840 goto key_and_mac_derive_fail;
7841 }
7842 i += macSize;
7843
7844 if (keySize) {
7845 /*
7846 ** Generate Domestic write keys and IVs.
7847 ** client_write_key[CipherSpec.key_material]
7848 */
7849 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
7850 keySize, &ssl3_keys_out->hClientKey);
7851 if (crv != CKR_OK) {
7852 goto key_and_mac_derive_fail;
7853 }
7854 i += keySize;
7855
7856 /*
7857 ** server_write_key[CipherSpec.key_material]
7858 */
7859 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
7860 keySize, &ssl3_keys_out->hServerKey);
7861 if (crv != CKR_OK) {
7862 goto key_and_mac_derive_fail;
7863 }
7864 i += keySize;
7865
7866 /*
7867 ** client_write_IV[CipherSpec.IV_size]
7868 */
7869 if (IVSize > 0) {
7870 PORT_Memcpy(ssl3_keys_out->pIVClient,
7871 &key_block[i], IVSize);
7872 i += IVSize;
7873 }
7874
7875 /*
7876 ** server_write_IV[CipherSpec.IV_size]
7877 */
7878 if (IVSize > 0) {
7879 PORT_Memcpy(ssl3_keys_out->pIVServer,
7880 &key_block[i], IVSize);
7881 i += IVSize;
7882 }
7883 PORT_Assert(i <= sizeof key_block);
7884 }
7885
7886 crv = CKR_OK;
7887
7888 if (0) {
7889 key_and_mac_derive_fail:
7890 if (crv == CKR_OK)
7891 crv = CKR_FUNCTION_FAILED;
7892 sftk_freeSSLKeys(hSession, ssl3_keys_out);
7893 }
7894 PORT_Memset(srcrdata, 0, sizeof srcrdata);
7895 PORT_Memset(key_block, 0, sizeof key_block);
7896 MD5_DestroyContext(md5, PR_TRUE);
7897 SHA1_DestroyContext(sha, PR_TRUE);
7898 sftk_FreeObject(key);
7899 key = NULL;
7900 break;
7901 }
7902
7903 case CKM_DES3_ECB_ENCRYPT_DATA:
7904 case CKM_DES3_CBC_ENCRYPT_DATA: {
7905 void *cipherInfo;
7906 unsigned char des3key[MAX_DES3_KEY_SIZE];
7907 CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr;
7908 int mode;
7909 unsigned char *iv;
7910 unsigned char *data;
7911 CK_ULONG len;
7912
7913 if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) {
7914 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
7915 crv = CKR_MECHANISM_PARAM_INVALID;
7916 break;
7917 }
7918 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
7919 pMechanism->pParameter;
7920 mode = NSS_DES_EDE3;
7921 iv = NULL;
7922 data = stringPtr->pData;
7923 len = stringPtr->ulLen;
7924 } else {
7925 mode = NSS_DES_EDE3_CBC;
7926 desEncryptPtr =
7927 (CK_DES_CBC_ENCRYPT_DATA_PARAMS *)
7928 pMechanism->pParameter;
7929 iv = desEncryptPtr->iv;
7930 data = desEncryptPtr->pData;
7931 len = desEncryptPtr->length;
7932 }
7933 if (att->attrib.ulValueLen == 16) {
7934 PORT_Memcpy(des3key, att->attrib.pValue, 16);
7935 PORT_Memcpy(des3key + 16, des3key, 8);
7936 } else if (att->attrib.ulValueLen == 24) {
7937 PORT_Memcpy(des3key, att->attrib.pValue, 24);
7938 } else {
7939 crv = CKR_KEY_SIZE_RANGE;
7940 break;
7941 }
7942 cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE);
7943 PORT_Memset(des3key, 0, 24);
7944 if (cipherInfo == NULL) {
7945 crv = CKR_HOST_MEMORY;
7946 break;
7947 }
7948 crv = sftk_DeriveEncrypt((SFTKCipher)DES_Encrypt,
7949 cipherInfo, 8, key, keySize,
7950 data, len);
7951 DES_DestroyContext(cipherInfo, PR_TRUE);
7952 break;
7953 }
7954
7955 case CKM_AES_ECB_ENCRYPT_DATA:
7956 case CKM_AES_CBC_ENCRYPT_DATA: {
7957 void *cipherInfo;
7958 CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
7959 int mode;
7960 unsigned char *iv;
7961 unsigned char *data;
7962 CK_ULONG len;
7963
7964 if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) {
7965 mode = NSS_AES;
7966 iv = NULL;
7967 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
7968 crv = CKR_MECHANISM_PARAM_INVALID;
7969 break;
7970 }
7971 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
7972 data = stringPtr->pData;
7973 len = stringPtr->ulLen;
7974 } else {
7975 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
7976 crv = CKR_MECHANISM_PARAM_INVALID;
7977 break;
7978 }
7979 aesEncryptPtr =
7980 (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter;
7981 mode = NSS_AES_CBC;
7982 iv = aesEncryptPtr->iv;
7983 data = aesEncryptPtr->pData;
7984 len = aesEncryptPtr->length;
7985 }
7986
7987 cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue,
7988 iv, mode, PR_TRUE,
7989 att->attrib.ulValueLen, 16);
7990 if (cipherInfo == NULL) {
7991 crv = CKR_HOST_MEMORY;
7992 break;
7993 }
7994 crv = sftk_DeriveEncrypt((SFTKCipher)AES_Encrypt,
7995 cipherInfo, 16, key, keySize,
7996 data, len);
7997 AES_DestroyContext(cipherInfo, PR_TRUE);
7998 break;
7999 }
8000
8001 case CKM_CAMELLIA_ECB_ENCRYPT_DATA:
8002 case CKM_CAMELLIA_CBC_ENCRYPT_DATA: {
8003 void *cipherInfo;
8004 CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
8005 int mode;
8006 unsigned char *iv;
8007 unsigned char *data;
8008 CK_ULONG len;
8009
8010 if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) {
8011 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8012 crv = CKR_MECHANISM_PARAM_INVALID;
8013 break;
8014 }
8015 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
8016 pMechanism->pParameter;
8017 aesEncryptPtr = NULL;
8018 mode = NSS_CAMELLIA;
8019 data = stringPtr->pData;
8020 len = stringPtr->ulLen;
8021 iv = NULL;
8022 } else {
8023 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
8024 crv = CKR_MECHANISM_PARAM_INVALID;
8025 break;
8026 }
8027 stringPtr = NULL;
8028 aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
8029 pMechanism->pParameter;
8030 mode = NSS_CAMELLIA_CBC;
8031 iv = aesEncryptPtr->iv;
8032 data = aesEncryptPtr->pData;
8033 len = aesEncryptPtr->length;
8034 }
8035
8036 cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue,
8037 iv, mode, PR_TRUE,
8038 att->attrib.ulValueLen);
8039 if (cipherInfo == NULL) {
8040 crv = CKR_HOST_MEMORY;
8041 break;
8042 }
8043 crv = sftk_DeriveEncrypt((SFTKCipher)Camellia_Encrypt,
8044 cipherInfo, 16, key, keySize,
8045 data, len);
8046 Camellia_DestroyContext(cipherInfo, PR_TRUE);
8047 break;
8048 }
8049
8050 #ifndef NSS_DISABLE_DEPRECATED_SEED
8051 case CKM_SEED_ECB_ENCRYPT_DATA:
8052 case CKM_SEED_CBC_ENCRYPT_DATA: {
8053 void *cipherInfo;
8054 CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
8055 int mode;
8056 unsigned char *iv;
8057 unsigned char *data;
8058 CK_ULONG len;
8059
8060 if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) {
8061 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8062 crv = CKR_MECHANISM_PARAM_INVALID;
8063 break;
8064 }
8065 mode = NSS_SEED;
8066 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
8067 pMechanism->pParameter;
8068 aesEncryptPtr = NULL;
8069 data = stringPtr->pData;
8070 len = stringPtr->ulLen;
8071 iv = NULL;
8072 } else {
8073 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
8074 crv = CKR_MECHANISM_PARAM_INVALID;
8075 break;
8076 }
8077 mode = NSS_SEED_CBC;
8078 aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
8079 pMechanism->pParameter;
8080 iv = aesEncryptPtr->iv;
8081 data = aesEncryptPtr->pData;
8082 len = aesEncryptPtr->length;
8083 }
8084
8085 cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue,
8086 iv, mode, PR_TRUE);
8087 if (cipherInfo == NULL) {
8088 crv = CKR_HOST_MEMORY;
8089 break;
8090 }
8091 crv = sftk_DeriveEncrypt((SFTKCipher)SEED_Encrypt,
8092 cipherInfo, 16, key, keySize,
8093 data, len);
8094 SEED_DestroyContext(cipherInfo, PR_TRUE);
8095 break;
8096 }
8097 #endif /* NSS_DISABLE_DEPRECATED_SEED */
8098
8099 case CKM_CONCATENATE_BASE_AND_KEY: {
8100 SFTKObject *newKey;
8101
8102 crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8103 if (crv != CKR_OK)
8104 break;
8105
8106 session = sftk_SessionFromHandle(hSession);
8107 if (session == NULL) {
8108 crv = CKR_SESSION_HANDLE_INVALID;
8109 break;
8110 }
8111
8112 newKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
8113 pMechanism->pParameter,
8114 session);
8115 sftk_FreeSession(session);
8116 if (newKey == NULL) {
8117 crv = CKR_KEY_HANDLE_INVALID;
8118 break;
8119 }
8120
8121 if (sftk_isTrue(newKey, CKA_SENSITIVE)) {
8122 crv = sftk_forceAttribute(newKey, CKA_SENSITIVE, &cktrue,
8123 sizeof(CK_BBOOL));
8124 if (crv != CKR_OK) {
8125 sftk_FreeObject(newKey);
8126 break;
8127 }
8128 }
8129
8130 att2 = sftk_FindAttribute(newKey, CKA_VALUE);
8131 if (att2 == NULL) {
8132 sftk_FreeObject(newKey);
8133 crv = CKR_KEY_HANDLE_INVALID;
8134 break;
8135 }
8136 tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen;
8137 if (keySize == 0)
8138 keySize = tmpKeySize;
8139 if (keySize > tmpKeySize) {
8140 sftk_FreeObject(newKey);
8141 sftk_FreeAttribute(att2);
8142 crv = CKR_TEMPLATE_INCONSISTENT;
8143 break;
8144 }
8145 buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8146 if (buf == NULL) {
8147 sftk_FreeAttribute(att2);
8148 sftk_FreeObject(newKey);
8149 crv = CKR_HOST_MEMORY;
8150 break;
8151 }
8152
8153 PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
8154 PORT_Memcpy(buf + att->attrib.ulValueLen,
8155 att2->attrib.pValue, att2->attrib.ulValueLen);
8156
8157 crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8158 PORT_ZFree(buf, tmpKeySize);
8159 sftk_FreeAttribute(att2);
8160 sftk_FreeObject(newKey);
8161 break;
8162 }
8163
8164 case CKM_CONCATENATE_BASE_AND_DATA:
8165 crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8166 if (crv != CKR_OK)
8167 break;
8168
8169 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8170 crv = CKR_MECHANISM_PARAM_INVALID;
8171 break;
8172 }
8173 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8174 tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
8175 if (keySize == 0)
8176 keySize = tmpKeySize;
8177 if (keySize > tmpKeySize) {
8178 crv = CKR_TEMPLATE_INCONSISTENT;
8179 break;
8180 }
8181 buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8182 if (buf == NULL) {
8183 crv = CKR_HOST_MEMORY;
8184 break;
8185 }
8186
8187 PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
8188 PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData,
8189 stringPtr->ulLen);
8190
8191 crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8192 PORT_ZFree(buf, tmpKeySize);
8193 break;
8194 case CKM_CONCATENATE_DATA_AND_BASE:
8195 crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8196 if (crv != CKR_OK)
8197 break;
8198
8199 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8200 crv = CKR_MECHANISM_PARAM_INVALID;
8201 break;
8202 }
8203 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8204 tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
8205 if (keySize == 0)
8206 keySize = tmpKeySize;
8207 if (keySize > tmpKeySize) {
8208 crv = CKR_TEMPLATE_INCONSISTENT;
8209 break;
8210 }
8211 buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8212 if (buf == NULL) {
8213 crv = CKR_HOST_MEMORY;
8214 break;
8215 }
8216
8217 PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen);
8218 PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue,
8219 att->attrib.ulValueLen);
8220
8221 crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8222 PORT_ZFree(buf, tmpKeySize);
8223 break;
8224 case CKM_XOR_BASE_AND_DATA:
8225 crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8226 if (crv != CKR_OK)
8227 break;
8228
8229 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8230 crv = CKR_MECHANISM_PARAM_INVALID;
8231 break;
8232 }
8233 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8234 tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen);
8235 if (keySize == 0)
8236 keySize = tmpKeySize;
8237 if (keySize > tmpKeySize) {
8238 crv = CKR_TEMPLATE_INCONSISTENT;
8239 break;
8240 }
8241 buf = (unsigned char *)PORT_Alloc(keySize);
8242 if (buf == NULL) {
8243 crv = CKR_HOST_MEMORY;
8244 break;
8245 }
8246
8247 PORT_Memcpy(buf, att->attrib.pValue, keySize);
8248 for (i = 0; i < (int)keySize; i++) {
8249 buf[i] ^= stringPtr->pData[i];
8250 }
8251
8252 crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8253 PORT_ZFree(buf, keySize);
8254 break;
8255
8256 case CKM_EXTRACT_KEY_FROM_KEY: {
8257 if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) {
8258 crv = CKR_MECHANISM_PARAM_INVALID;
8259 break;
8260 }
8261 /* the following assumes 8 bits per byte */
8262 CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
8263 CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
8264 CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
8265
8266 crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8267 if (crv != CKR_OK)
8268 break;
8269
8270 if (keySize == 0) {
8271 crv = CKR_TEMPLATE_INCOMPLETE;
8272 break;
8273 }
8274 /* make sure we have enough bits in the original key */
8275 if (att->attrib.ulValueLen <
8276 (offset + keySize + ((shift != 0) ? 1 : 0))) {
8277 crv = CKR_MECHANISM_PARAM_INVALID;
8278 break;
8279 }
8280 buf = (unsigned char *)PORT_Alloc(keySize);
8281 if (buf == NULL) {
8282 crv = CKR_HOST_MEMORY;
8283 break;
8284 }
8285
8286 /* copy the bits we need into the new key */
8287 for (i = 0; i < (int)keySize; i++) {
8288 unsigned char *value =
8289 ((unsigned char *)att->attrib.pValue) + offset + i;
8290 if (shift) {
8291 buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
8292 } else {
8293 buf[i] = value[0];
8294 }
8295 }
8296
8297 crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8298 PORT_ZFree(buf, keySize);
8299 break;
8300 }
8301 case CKM_MD2_KEY_DERIVATION:
8302 if (keySize == 0)
8303 keySize = MD2_LENGTH;
8304 if (keySize > MD2_LENGTH) {
8305 crv = CKR_TEMPLATE_INCONSISTENT;
8306 break;
8307 }
8308 /* now allocate the hash contexts */
8309 md2 = MD2_NewContext();
8310 if (md2 == NULL) {
8311 crv = CKR_HOST_MEMORY;
8312 break;
8313 }
8314 MD2_Begin(md2);
8315 MD2_Update(md2, (const unsigned char *)att->attrib.pValue,
8316 att->attrib.ulValueLen);
8317 MD2_End(md2, key_block, &outLen, MD2_LENGTH);
8318 MD2_DestroyContext(md2, PR_TRUE);
8319
8320 crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);
8321 PORT_Memset(key_block, 0, MD2_LENGTH);
8322 break;
8323 #define DERIVE_KEY_HASH(hash) \
8324 case CKM_##hash##_KEY_DERIVATION: \
8325 if (keySize == 0) \
8326 keySize = hash##_LENGTH; \
8327 if (keySize > hash##_LENGTH) { \
8328 crv = CKR_TEMPLATE_INCONSISTENT; \
8329 break; \
8330 } \
8331 hash##_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, \
8332 att->attrib.ulValueLen); \
8333 crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); \
8334 PORT_Memset(key_block, 0, hash##_LENGTH); \
8335 break;
8336 DERIVE_KEY_HASH(MD5)
8337 DERIVE_KEY_HASH(SHA1)
8338 DERIVE_KEY_HASH(SHA224)
8339 DERIVE_KEY_HASH(SHA256)
8340 DERIVE_KEY_HASH(SHA384)
8341 DERIVE_KEY_HASH(SHA512)
8342
8343 case CKM_DH_PKCS_DERIVE: {
8344 SECItem derived, dhPublic;
8345 SECItem dhPrime, dhValue;
8346 const SECItem *subPrime;
8347 /* sourceKey - values for the local existing low key */
8348 /* get prime and value attributes */
8349 crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
8350 if (crv != CKR_OK)
8351 break;
8352
8353 dhPublic.data = pMechanism->pParameter;
8354 dhPublic.len = pMechanism->ulParameterLen;
8355
8356 /* if the prime is an approved prime, we can skip all the other
8357 * checks. */
8358 subPrime = sftk_VerifyDH_Prime(&dhPrime, isFIPS);
8359 if (subPrime == NULL) {
8360 SECItem dhSubPrime;
8361 /* If the caller set the subprime value, it means that
8362 * either the caller knows the subprime value and wants us
8363 * to validate the key against the subprime, or that the
8364 * caller wants us to verify that the prime is a safe prime
8365 * by passing in subprime = (prime-1)/2 */
8366 dhSubPrime.data = NULL;
8367 dhSubPrime.len = 0;
8368 crv = sftk_Attribute2SecItem(NULL, &dhSubPrime,
8369 sourceKey, CKA_SUBPRIME);
8370 /* we ignore the value of crv here, We treat a valid
8371 * return of len = 0 and a failure to find a subrime the same
8372 * NOTE: we free the subprime in both cases depending on
8373 * PORT_Free of NULL to be a noop */
8374 if (dhSubPrime.len != 0) {
8375 PRBool isSafe = PR_FALSE;
8376
8377 /* Callers can set dhSubPrime to q=(p-1)/2 to force
8378 * checks for safe primes. If so we only need to check
8379 * q and p for primality and skip the group test. */
8380 rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe);
8381 if (rv != SECSuccess) {
8382 /* either p or q was even and therefore not prime,
8383 * we can stop processing here and fail now */
8384 crv = CKR_ARGUMENTS_BAD;
8385 SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8386 SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8387 break;
8388 }
8389
8390 /* first make sure the primes are really prime */
8391 if (!KEA_PrimeCheck(&dhPrime)) {
8392 crv = CKR_ARGUMENTS_BAD;
8393 SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8394 SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8395 break;
8396 }
8397 if (!KEA_PrimeCheck(&dhSubPrime)) {
8398 crv = CKR_ARGUMENTS_BAD;
8399 SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8400 SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8401 break;
8402 }
8403 if (isFIPS || !isSafe) {
8404 /* With safe primes, there is only one other small
8405 * subgroup. As long as y isn't 0, 1, or -1 mod p,
8406 * any other y is safe. Only do the full check for
8407 * non-safe primes, except in FIPS mode we need
8408 * to do this check on all primes in which
8409 * we receive the subprime value */
8410 if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) {
8411 crv = CKR_ARGUMENTS_BAD;
8412 SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8413 SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8414 break;
8415 }
8416 }
8417 } else if (isFIPS) {
8418 /* In FIPS mode we only accept approved primes, or
8419 * primes with the full subprime value */
8420 crv = CKR_ARGUMENTS_BAD;
8421 SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8422 break;
8423 }
8424 /* checks are complete, no need for the subPrime any longer */
8425 SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8426 }
8427
8428 /* now that the prime is validated, get the private value */
8429 crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
8430 if (crv != CKR_OK) {
8431 SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8432 break;
8433 }
8434
8435 /* calculate private value - oct */
8436 rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
8437
8438 SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8439 SECITEM_ZfreeItem(&dhValue, PR_FALSE);
8440
8441 if (rv == SECSuccess) {
8442 sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
8443 SECITEM_ZfreeItem(&derived, PR_FALSE);
8444 crv = CKR_OK;
8445 } else
8446 crv = CKR_HOST_MEMORY;
8447
8448 break;
8449 }
8450
8451 case CKM_ECDH1_DERIVE:
8452 case CKM_ECDH1_COFACTOR_DERIVE: {
8453 SECItem ecScalar, ecPoint;
8454 SECItem tmp;
8455 PRBool withCofactor = PR_FALSE;
8456 unsigned char *secret;
8457 unsigned char *keyData = NULL;
8458 unsigned int secretlen, pubKeyLen;
8459 CK_ECDH1_DERIVE_PARAMS *mechParams;
8460 NSSLOWKEYPrivateKey *privKey;
8461 PLArenaPool *arena = NULL;
8462
8463 /* Check mechanism parameters */
8464 mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter;
8465 if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) ||
8466 ((mechParams->kdf == CKD_NULL) &&
8467 ((mechParams->ulSharedDataLen != 0) ||
8468 (mechParams->pSharedData != NULL)))) {
8469 crv = CKR_MECHANISM_PARAM_INVALID;
8470 break;
8471 }
8472
8473 privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv);
8474 if (privKey == NULL) {
8475 break;
8476 }
8477
8478 /* Now we are working with a non-NULL private key */
8479 SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue);
8480
8481 ecPoint.data = mechParams->pPublicData;
8482 ecPoint.len = mechParams->ulPublicDataLen;
8483
8484 pubKeyLen = EC_GetPointSize(&privKey->u.ec.ecParams);
8485
8486 /* if the len is too large, might be an encoded point */
8487 if (ecPoint.len > pubKeyLen) {
8488 SECItem newPoint;
8489
8490 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
8491 if (arena == NULL) {
8492 goto ec_loser;
8493 }
8494
8495 rv = SEC_QuickDERDecodeItem(arena, &newPoint,
8496 SEC_ASN1_GET(SEC_OctetStringTemplate),
8497 &ecPoint);
8498 if (rv != SECSuccess) {
8499 goto ec_loser;
8500 }
8501 ecPoint = newPoint;
8502 }
8503
8504 if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) {
8505 withCofactor = PR_TRUE;
8506 }
8507
8508 rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
8509 withCofactor, &tmp);
8510 SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
8511 ecScalar.data = NULL;
8512 if (privKey != sourceKey->objectInfo) {
8513 nsslowkey_DestroyPrivateKey(privKey);
8514 privKey = NULL;
8515 }
8516 if (arena) {
8517 PORT_FreeArena(arena, PR_FALSE);
8518 arena = NULL;
8519 }
8520
8521 if (rv != SECSuccess) {
8522 crv = sftk_MapCryptError(PORT_GetError());
8523 break;
8524 }
8525
8526 /*
8527 * apply the kdf function.
8528 */
8529 if (mechParams->kdf == CKD_NULL) {
8530 /*
8531 * tmp is the raw data created by ECDH_Derive,
8532 * secret and secretlen are the values we will
8533 * eventually pass as our generated key.
8534 */
8535 secret = tmp.data;
8536 secretlen = tmp.len;
8537 } else {
8538 secretlen = keySize;
8539 crv = sftk_ANSI_X9_63_kdf(&secret, keySize,
8540 &tmp, mechParams->pSharedData,
8541 mechParams->ulSharedDataLen, mechParams->kdf);
8542 PORT_ZFree(tmp.data, tmp.len);
8543 if (crv != CKR_OK) {
8544 break;
8545 }
8546 tmp.data = secret;
8547 tmp.len = secretlen;
8548 }
8549
8550 /*
8551 * if keySize is supplied, then we are generating a key of a specific
8552 * length. This is done by taking the least significant 'keySize'
8553 * bytes from the unsigned value calculated by ECDH. Note: this may
8554 * mean padding temp with extra leading zeros from what ECDH_Derive
8555 * already returned (which itself may contain leading zeros).
8556 */
8557 if (keySize) {
8558 if (secretlen < keySize) {
8559 keyData = PORT_ZAlloc(keySize);
8560 if (!keyData) {
8561 PORT_ZFree(tmp.data, tmp.len);
8562 crv = CKR_HOST_MEMORY;
8563 break;
8564 }
8565 PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen);
8566 secret = keyData;
8567 } else {
8568 secret += (secretlen - keySize);
8569 }
8570 secretlen = keySize;
8571 }
8572
8573 sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
8574 PORT_ZFree(tmp.data, tmp.len);
8575 if (keyData) {
8576 PORT_ZFree(keyData, keySize);
8577 }
8578 break;
8579
8580 ec_loser:
8581 crv = CKR_ARGUMENTS_BAD;
8582 SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
8583 if (privKey != sourceKey->objectInfo)
8584 nsslowkey_DestroyPrivateKey(privKey);
8585 if (arena) {
8586 PORT_FreeArena(arena, PR_TRUE);
8587 }
8588 break;
8589 }
8590 /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */
8591 case CKM_NSS_HKDF_SHA1:
8592 hashMech = CKM_SHA_1;
8593 goto hkdf;
8594 case CKM_NSS_HKDF_SHA256:
8595 hashMech = CKM_SHA256;
8596 goto hkdf;
8597 case CKM_NSS_HKDF_SHA384:
8598 hashMech = CKM_SHA384;
8599 goto hkdf;
8600 case CKM_NSS_HKDF_SHA512:
8601 hashMech = CKM_SHA512;
8602 goto hkdf;
8603 hkdf : {
8604 const CK_NSS_HKDFParams *params =
8605 (const CK_NSS_HKDFParams *)pMechanism->pParameter;
8606 CK_HKDF_PARAMS hkdfParams;
8607
8608 if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) {
8609 crv = CKR_MECHANISM_PARAM_INVALID;
8610 break;
8611 }
8612 hkdfParams.bExtract = params->bExtract;
8613 hkdfParams.bExpand = params->bExpand;
8614 if (params->pSalt) {
8615 hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA;
8616 } else {
8617 hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL;
8618 }
8619 hkdfParams.pSalt = params->pSalt;
8620 hkdfParams.ulSaltLen = params->ulSaltLen;
8621 hkdfParams.hSaltKey = CK_INVALID_HANDLE;
8622 hkdfParams.pInfo = params->pInfo;
8623 hkdfParams.ulInfoLen = params->ulInfoLen;
8624 hkdfParams.prfHashMechanism = hashMech;
8625
8626 crv = sftk_HKDF(&hkdfParams, hSession, sourceKey,
8627 att->attrib.pValue, att->attrib.ulValueLen,
8628 key, NULL, keySize, PR_FALSE, isFIPS);
8629 } break;
8630 case CKM_HKDF_DERIVE:
8631 case CKM_HKDF_DATA: /* only difference is the class of key */
8632 if ((pMechanism->pParameter == NULL) ||
8633 (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) {
8634 crv = CKR_MECHANISM_PARAM_INVALID;
8635 break;
8636 }
8637 crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter,
8638 hSession, sourceKey, att->attrib.pValue,
8639 att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE,
8640 isFIPS);
8641 break;
8642 case CKM_NSS_JPAKE_ROUND2_SHA1:
8643 hashType = HASH_AlgSHA1;
8644 goto jpake2;
8645 case CKM_NSS_JPAKE_ROUND2_SHA256:
8646 hashType = HASH_AlgSHA256;
8647 goto jpake2;
8648 case CKM_NSS_JPAKE_ROUND2_SHA384:
8649 hashType = HASH_AlgSHA384;
8650 goto jpake2;
8651 case CKM_NSS_JPAKE_ROUND2_SHA512:
8652 hashType = HASH_AlgSHA512;
8653 goto jpake2;
8654 jpake2:
8655 if (pMechanism->pParameter == NULL ||
8656 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params))
8657 crv = CKR_MECHANISM_PARAM_INVALID;
8658 if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN))
8659 crv = CKR_TEMPLATE_INCONSISTENT;
8660 if (crv == CKR_OK)
8661 crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8662 if (crv == CKR_OK)
8663 crv = jpake_Round2(hashType,
8664 (CK_NSS_JPAKERound2Params *)pMechanism->pParameter,
8665 sourceKey, key);
8666 break;
8667
8668 case CKM_NSS_JPAKE_FINAL_SHA1:
8669 hashType = HASH_AlgSHA1;
8670 goto jpakeFinal;
8671 case CKM_NSS_JPAKE_FINAL_SHA256:
8672 hashType = HASH_AlgSHA256;
8673 goto jpakeFinal;
8674 case CKM_NSS_JPAKE_FINAL_SHA384:
8675 hashType = HASH_AlgSHA384;
8676 goto jpakeFinal;
8677 case CKM_NSS_JPAKE_FINAL_SHA512:
8678 hashType = HASH_AlgSHA512;
8679 goto jpakeFinal;
8680 jpakeFinal:
8681 if (pMechanism->pParameter == NULL ||
8682 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams))
8683 crv = CKR_MECHANISM_PARAM_INVALID;
8684 /* We purposely do not do the derive sensitivity check; we want to be
8685 able to derive non-sensitive keys while allowing the ROUND1 and
8686 ROUND2 keys to be sensitive (which they always are, since they are
8687 in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE
8688 in the template in order for the resultant keyblock key to be
8689 sensitive.
8690 */
8691 if (crv == CKR_OK)
8692 crv = jpake_Final(hashType,
8693 (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter,
8694 sourceKey, key);
8695 break;
8696
8697 case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */
8698 case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
8699 case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */
8700 case CKM_SP800_108_COUNTER_KDF: /* fall through */
8701 case CKM_SP800_108_FEEDBACK_KDF: /* fall through */
8702 case CKM_SP800_108_DOUBLE_PIPELINE_KDF:
8703 crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8704 if (crv != CKR_OK) {
8705 break;
8706 }
8707
8708 crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize);
8709 break;
8710 default:
8711 crv = CKR_MECHANISM_INVALID;
8712 }
8713 if (att) {
8714 sftk_FreeAttribute(att);
8715 }
8716 sftk_FreeObject(sourceKey);
8717 if (crv != CKR_OK) {
8718 if (key)
8719 sftk_FreeObject(key);
8720 return crv;
8721 }
8722
8723 /* link the key object into the list */
8724 if (key) {
8725 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
8726 PORT_Assert(sessKey);
8727 /* get the session */
8728 sessKey->wasDerived = PR_TRUE;
8729 session = sftk_SessionFromHandle(hSession);
8730 if (session == NULL) {
8731 sftk_FreeObject(key);
8732 return CKR_HOST_MEMORY;
8733 }
8734
8735 crv = sftk_handleObject(key, session);
8736 session->lastOpWasFIPS = key->isFIPS;
8737 sftk_FreeSession(session);
8738 *phKey = key->handle;
8739 sftk_FreeObject(key);
8740 }
8741 return crv;
8742 }
8743
8744 /* NSC_GetFunctionStatus obtains an updated status of a function running
8745 * in parallel with an application. */
8746 CK_RV
NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)8747 NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
8748 {
8749 CHECK_FORK();
8750
8751 return CKR_FUNCTION_NOT_PARALLEL;
8752 }
8753
8754 /* NSC_CancelFunction cancels a function running in parallel */
8755 CK_RV
NSC_CancelFunction(CK_SESSION_HANDLE hSession)8756 NSC_CancelFunction(CK_SESSION_HANDLE hSession)
8757 {
8758 CHECK_FORK();
8759
8760 return CKR_FUNCTION_NOT_PARALLEL;
8761 }
8762
8763 /* NSC_GetOperationState saves the state of the cryptographic
8764 * operation in a session.
8765 * NOTE: This code only works for digest functions for now. eventually need
8766 * to add full flatten/resurect to our state stuff so that all types of state
8767 * can be saved */
8768 CK_RV
NSC_GetOperationState(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pOperationState,CK_ULONG_PTR pulOperationStateLen)8769 NSC_GetOperationState(CK_SESSION_HANDLE hSession,
8770 CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
8771 {
8772 SFTKSessionContext *context;
8773 SFTKSession *session;
8774 CK_RV crv;
8775 CK_ULONG pOSLen = *pulOperationStateLen;
8776
8777 CHECK_FORK();
8778
8779 /* make sure we're legal */
8780 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
8781 if (crv != CKR_OK)
8782 return crv;
8783
8784 *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType);
8785 if (pOperationState == NULL) {
8786 sftk_FreeSession(session);
8787 return CKR_OK;
8788 } else {
8789 if (pOSLen < *pulOperationStateLen) {
8790 return CKR_BUFFER_TOO_SMALL;
8791 }
8792 }
8793 PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType));
8794 pOperationState += sizeof(SFTKContextType);
8795 PORT_Memcpy(pOperationState, &context->currentMech,
8796 sizeof(CK_MECHANISM_TYPE));
8797 pOperationState += sizeof(CK_MECHANISM_TYPE);
8798 PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen);
8799 sftk_FreeSession(session);
8800 return CKR_OK;
8801 }
8802
8803 #define sftk_Decrement(stateSize, len) \
8804 stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0;
8805
8806 /* NSC_SetOperationState restores the state of the cryptographic
8807 * operation in a session. This is coded like it can restore lots of
8808 * states, but it only works for truly flat cipher structures. */
8809 CK_RV
NSC_SetOperationState(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pOperationState,CK_ULONG ulOperationStateLen,CK_OBJECT_HANDLE hEncryptionKey,CK_OBJECT_HANDLE hAuthenticationKey)8810 NSC_SetOperationState(CK_SESSION_HANDLE hSession,
8811 CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
8812 CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
8813 {
8814 SFTKSessionContext *context;
8815 SFTKSession *session;
8816 SFTKContextType type;
8817 CK_MECHANISM mech;
8818 CK_RV crv = CKR_OK;
8819
8820 CHECK_FORK();
8821
8822 while (ulOperationStateLen != 0) {
8823 /* get what type of state we're dealing with... */
8824 PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType));
8825
8826 /* fix up session contexts based on type */
8827 session = sftk_SessionFromHandle(hSession);
8828 if (session == NULL)
8829 return CKR_SESSION_HANDLE_INVALID;
8830 context = sftk_ReturnContextByType(session, type);
8831 sftk_SetContextByType(session, type, NULL);
8832 if (context) {
8833 sftk_FreeContext(context);
8834 }
8835 pOperationState += sizeof(SFTKContextType);
8836 sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType));
8837
8838 /* get the mechanism structure */
8839 PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE));
8840 pOperationState += sizeof(CK_MECHANISM_TYPE);
8841 sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
8842 /* should be filled in... but not necessary for hash */
8843 mech.pParameter = NULL;
8844 mech.ulParameterLen = 0;
8845 switch (type) {
8846 case SFTK_HASH:
8847 crv = NSC_DigestInit(hSession, &mech);
8848 if (crv != CKR_OK)
8849 break;
8850 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE,
8851 NULL);
8852 if (crv != CKR_OK)
8853 break;
8854 PORT_Memcpy(context->cipherInfo, pOperationState,
8855 context->cipherInfoLen);
8856 pOperationState += context->cipherInfoLen;
8857 sftk_Decrement(ulOperationStateLen, context->cipherInfoLen);
8858 break;
8859 default:
8860 /* do sign/encrypt/decrypt later */
8861 crv = CKR_SAVED_STATE_INVALID;
8862 }
8863 sftk_FreeSession(session);
8864 if (crv != CKR_OK)
8865 break;
8866 }
8867 return crv;
8868 }
8869
8870 /* Dual-function cryptographic operations */
8871
8872 /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
8873 * operation. */
8874 CK_RV
NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen,CK_BYTE_PTR pEncryptedPart,CK_ULONG_PTR pulEncryptedPartLen)8875 NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
8876 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
8877 CK_ULONG_PTR pulEncryptedPartLen)
8878 {
8879 CK_RV crv;
8880
8881 CHECK_FORK();
8882
8883 crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
8884 pulEncryptedPartLen);
8885 if (crv != CKR_OK)
8886 return crv;
8887 crv = NSC_DigestUpdate(hSession, pPart, ulPartLen);
8888
8889 return crv;
8890 }
8891
8892 /* NSC_DecryptDigestUpdate continues a multiple-part decryption and
8893 * digesting operation. */
8894 CK_RV
NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedPart,CK_ULONG ulEncryptedPartLen,CK_BYTE_PTR pPart,CK_ULONG_PTR pulPartLen)8895 NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
8896 CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
8897 CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
8898 {
8899 CK_RV crv;
8900
8901 CHECK_FORK();
8902
8903 crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen,
8904 pPart, pulPartLen);
8905 if (crv != CKR_OK)
8906 return crv;
8907 crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen);
8908
8909 return crv;
8910 }
8911
8912 /* NSC_SignEncryptUpdate continues a multiple-part signing and
8913 * encryption operation. */
8914 CK_RV
NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen,CK_BYTE_PTR pEncryptedPart,CK_ULONG_PTR pulEncryptedPartLen)8915 NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
8916 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
8917 CK_ULONG_PTR pulEncryptedPartLen)
8918 {
8919 CK_RV crv;
8920
8921 CHECK_FORK();
8922
8923 crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
8924 pulEncryptedPartLen);
8925 if (crv != CKR_OK)
8926 return crv;
8927 crv = NSC_SignUpdate(hSession, pPart, ulPartLen);
8928
8929 return crv;
8930 }
8931
8932 /* NSC_DecryptVerifyUpdate continues a multiple-part decryption
8933 * and verify operation. */
8934 CK_RV
NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)8935 NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
8936 CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
8937 CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
8938 {
8939 CK_RV crv;
8940
8941 CHECK_FORK();
8942
8943 crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
8944 pData, pulDataLen);
8945 if (crv != CKR_OK)
8946 return crv;
8947 crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
8948
8949 return crv;
8950 }
8951
8952 /* NSC_DigestKey continues a multi-part message-digesting operation,
8953 * by digesting the value of a secret key as part of the data already digested.
8954 */
8955 CK_RV
NSC_DigestKey(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hKey)8956 NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
8957 {
8958 SFTKSession *session = NULL;
8959 SFTKObject *key = NULL;
8960 SFTKAttribute *att;
8961 CK_RV crv;
8962
8963 CHECK_FORK();
8964
8965 session = sftk_SessionFromHandle(hSession);
8966 if (session == NULL)
8967 return CKR_SESSION_HANDLE_INVALID;
8968
8969 key = sftk_ObjectFromHandle(hKey, session);
8970 sftk_FreeSession(session);
8971 if (key == NULL)
8972 return CKR_KEY_HANDLE_INVALID;
8973
8974 /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
8975
8976 /* make sure it's a valid key for this operation */
8977 if (key->objclass != CKO_SECRET_KEY) {
8978 sftk_FreeObject(key);
8979 return CKR_KEY_TYPE_INCONSISTENT;
8980 }
8981 /* get the key value */
8982 att = sftk_FindAttribute(key, CKA_VALUE);
8983 sftk_FreeObject(key);
8984 if (!att) {
8985 return CKR_KEY_HANDLE_INVALID;
8986 }
8987 crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue,
8988 att->attrib.ulValueLen);
8989 sftk_FreeAttribute(att);
8990 return crv;
8991 }
8992