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