Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 "alghmac.h"
34 #include "softoken.h"
35 #include "secasn1.h"
36 #include "secerr.h"
38 #include "prprf.h"
40 #define __PASTE(x,y) x##y
42 /*
43 * we renamed all our internal functions, get the correct
44 * definitions for them...
45 */
46 #undef CK_PKCS11_FUNCTION_INFO
47 #undef CK_NEED_ARG_LIST
49 #define CK_EXTERN extern
50 #define CK_PKCS11_FUNCTION_INFO(func) \
51 CK_RV __PASTE(NS,func)
52 #define CK_NEED_ARG_LIST 1
54 #include "pkcs11f.h"
56 typedef struct {
57 PRUint8 client_version[2];
58 PRUint8 random[46];
59 } SSL3RSAPreMasterSecret;
61 static void sftk_Null(void *data, PRBool freeit)
62 {
63 return;
64 }
66 #ifndef NSS_DISABLE_ECC
67 #ifdef EC_DEBUG
68 #define SEC_PRINT(str1, str2, num, sitem) \
69 printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
70 str1, str2, num, sitem->len); \
71 for (i = 0; i < sitem->len; i++) { \
72 printf("%02x:", sitem->data[i]); \
73 } \
74 printf("\n")
75 #else
76 #define SEC_PRINT(a, b, c, d)
77 #endif
78 #endif /* NSS_DISABLE_ECC */
80 /*
81 * free routines.... Free local type allocated data, and convert
82 * other free routines to the destroy signature.
83 */
84 static void
85 sftk_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit)
86 {
87 nsslowkey_DestroyPrivateKey(key);
88 }
90 static void
91 sftk_Space(void *data, PRBool freeit)
92 {
93 PORT_Free(data);
94 }
96 /*
97 * map all the SEC_ERROR_xxx error codes that may be returned by freebl
98 * functions to CKR_xxx. return CKR_DEVICE_ERROR by default for backward
99 * compatibility.
100 */
101 static CK_RV
102 sftk_MapCryptError(int error)
103 {
104 switch (error) {
105 case SEC_ERROR_INVALID_ARGS:
106 case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */
107 return CKR_ARGUMENTS_BAD;
108 case SEC_ERROR_INPUT_LEN:
109 return CKR_DATA_LEN_RANGE;
110 case SEC_ERROR_OUTPUT_LEN:
111 return CKR_BUFFER_TOO_SMALL;
112 case SEC_ERROR_LIBRARY_FAILURE:
113 return CKR_GENERAL_ERROR;
114 case SEC_ERROR_NO_MEMORY:
115 return CKR_HOST_MEMORY;
116 case SEC_ERROR_BAD_SIGNATURE:
117 return CKR_SIGNATURE_INVALID;
118 case SEC_ERROR_INVALID_KEY:
119 return CKR_KEY_SIZE_RANGE;
120 case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */
121 return CKR_KEY_SIZE_RANGE; /* the closest error code */
122 case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM:
123 return CKR_TEMPLATE_INCONSISTENT;
124 /* EC functions set this error if NSS_DISABLE_ECC is defined */
125 case SEC_ERROR_UNSUPPORTED_KEYALG:
126 return CKR_MECHANISM_INVALID;
127 case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE:
128 return CKR_DOMAIN_PARAMS_INVALID;
129 /* key pair generation failed after max number of attempts */
130 case SEC_ERROR_NEED_RANDOM:
131 return CKR_FUNCTION_FAILED;
132 }
133 return CKR_DEVICE_ERROR;
134 }
136 /* used by Decrypt and UnwrapKey (indirectly) */
137 static CK_RV
138 sftk_MapDecryptError(int error)
139 {
140 switch (error) {
141 case SEC_ERROR_BAD_DATA:
142 return CKR_ENCRYPTED_DATA_INVALID;
143 default:
144 return sftk_MapCryptError(error);
145 }
146 }
148 /*
149 * return CKR_SIGNATURE_INVALID instead of CKR_DEVICE_ERROR by default for
150 * backward compatibilty.
151 */
152 static CK_RV
153 sftk_MapVerifyError(int error)
154 {
155 CK_RV crv = sftk_MapCryptError(error);
156 if (crv == CKR_DEVICE_ERROR)
157 crv = CKR_SIGNATURE_INVALID;
158 return crv;
159 }
162 /*
163 * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
164 * Deprecating a full des key to 40 bit key strenth.
165 */
166 static CK_RV
167 sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
168 {
169 unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
170 unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
171 unsigned char enc_src[8];
172 unsigned char enc_dest[8];
173 unsigned int leng,i;
174 DESContext *descx;
175 SECStatus rv;
178 /* zero the parity bits */
179 for (i=0; i < 8; i++) {
180 enc_src[i] = cdmfkey[i] & 0xfe;
181 }
183 /* encrypt with key 1 */
184 descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);
185 if (descx == NULL) return CKR_HOST_MEMORY;
186 rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);
187 DES_DestroyContext(descx,PR_TRUE);
188 if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError());
190 /* xor source with des, zero the parity bits and deprecate the key*/
191 for (i=0; i < 8; i++) {
192 if (i & 1) {
193 enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;
194 } else {
195 enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;
196 }
197 }
199 /* encrypt with key 2 */
200 descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);
201 if (descx == NULL) return CKR_HOST_MEMORY;
202 rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);
203 DES_DestroyContext(descx,PR_TRUE);
204 if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError());
206 /* set the corret parity on our new des key */
207 sftk_FormatDESKey(deskey, 8);
208 return CKR_OK;
209 }
212 /* NSC_DestroyObject destroys an object. */
213 CK_RV
214 NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
215 {
216 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
217 SFTKSession *session;
218 SFTKObject *object;
219 SFTKFreeStatus status;
221 CHECK_FORK();
223 if (slot == NULL) {
224 return CKR_SESSION_HANDLE_INVALID;
225 }
226 /*
227 * This whole block just makes sure we really can destroy the
228 * requested object.
229 */
230 session = sftk_SessionFromHandle(hSession);
231 if (session == NULL) {
232 return CKR_SESSION_HANDLE_INVALID;
233 }
235 object = sftk_ObjectFromHandle(hObject,session);
236 if (object == NULL) {
237 sftk_FreeSession(session);
238 return CKR_OBJECT_HANDLE_INVALID;
239 }
241 /* don't destroy a private object if we aren't logged in */
242 if ((!slot->isLoggedIn) && (slot->needLogin) &&
243 (sftk_isTrue(object,CKA_PRIVATE))) {
244 sftk_FreeSession(session);
245 sftk_FreeObject(object);
246 return CKR_USER_NOT_LOGGED_IN;
247 }
249 /* don't destroy a token object if we aren't in a rw session */
251 if (((session->info.flags & CKF_RW_SESSION) == 0) &&
252 (sftk_isTrue(object,CKA_TOKEN))) {
253 sftk_FreeSession(session);
254 sftk_FreeObject(object);
255 return CKR_SESSION_READ_ONLY;
256 }
258 sftk_DeleteObject(session,object);
260 sftk_FreeSession(session);
262 /*
263 * get some indication if the object is destroyed. Note: this is not
264 * 100%. Someone may have an object reference outstanding (though that
265 * should not be the case by here. Also note that the object is "half"
266 * destroyed. Our internal representation is destroyed, but it may still
267 * be in the data base.
268 */
269 status = sftk_FreeObject(object);
271 return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
272 }
275 /*
276 ************** Crypto Functions: Utilities ************************
277 */
278 /*
279 * Utility function for converting PSS/OAEP parameter types into
280 * HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447.
281 */
282 static HASH_HashType
283 GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech)
284 {
285 switch (mech) {
286 case CKM_SHA_1:
287 case CKG_MGF1_SHA1:
288 return HASH_AlgSHA1;
289 case CKM_SHA224:
290 case CKG_MGF1_SHA224:
291 return HASH_AlgSHA224;
292 case CKM_SHA256:
293 case CKG_MGF1_SHA256:
294 return HASH_AlgSHA256;
295 case CKM_SHA384:
296 case CKG_MGF1_SHA384:
297 return HASH_AlgSHA384;
298 case CKM_SHA512:
299 case CKG_MGF1_SHA512:
300 return HASH_AlgSHA512;
301 default:
302 return HASH_AlgNULL;
303 }
304 }
306 /*
307 * Returns true if "params" contains a valid set of PSS parameters
308 */
309 static PRBool
310 sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params)
311 {
312 if (!params) {
313 return PR_FALSE;
314 }
315 if (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL ||
316 GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) {
317 return PR_FALSE;
318 }
319 return PR_TRUE;
320 }
322 /*
323 * Returns true if "params" contains a valid set of OAEP parameters
324 */
325 static PRBool
326 sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params)
327 {
328 if (!params) {
329 return PR_FALSE;
330 }
331 /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which
332 * state:
333 * If the parameter is empty, pSourceData must be NULL and
334 * ulSourceDataLen must be zero.
335 */
336 if (params->source != CKZ_DATA_SPECIFIED ||
337 (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) ||
338 (GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) ||
339 (params->ulSourceDataLen == 0 && params->pSourceData != NULL) ||
340 (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) {
341 return PR_FALSE;
342 }
343 return PR_TRUE;
344 }
346 /*
347 * return a context based on the SFTKContext type.
348 */
349 SFTKSessionContext *
350 sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
351 {
352 switch (type) {
353 case SFTK_ENCRYPT:
354 case SFTK_DECRYPT:
355 return session->enc_context;
356 case SFTK_HASH:
357 return session->hash_context;
358 case SFTK_SIGN:
359 case SFTK_SIGN_RECOVER:
360 case SFTK_VERIFY:
361 case SFTK_VERIFY_RECOVER:
362 return session->hash_context;
363 }
364 return NULL;
365 }
367 /*
368 * change a context based on the SFTKContext type.
369 */
370 void
371 sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
372 SFTKSessionContext *context)
373 {
374 switch (type) {
375 case SFTK_ENCRYPT:
376 case SFTK_DECRYPT:
377 session->enc_context = context;
378 break;
379 case SFTK_HASH:
380 session->hash_context = context;
381 break;
382 case SFTK_SIGN:
383 case SFTK_SIGN_RECOVER:
384 case SFTK_VERIFY:
385 case SFTK_VERIFY_RECOVER:
386 session->hash_context = context;
387 break;
388 }
389 return;
390 }
392 /*
393 * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
394 * and C_XXX function. The function takes a session handle, the context type,
395 * and wether or not the session needs to be multipart. It returns the context,
396 * and optionally returns the session pointer (if sessionPtr != NULL) if session
397 * pointer is returned, the caller is responsible for freeing it.
398 */
399 static CK_RV
400 sftk_GetContext(CK_SESSION_HANDLE handle,SFTKSessionContext **contextPtr,
401 SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr)
402 {
403 SFTKSession *session;
404 SFTKSessionContext *context;
406 session = sftk_SessionFromHandle(handle);
407 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
408 context = sftk_ReturnContextByType(session,type);
409 /* make sure the context is valid */
410 if((context==NULL)||(context->type!=type)||(needMulti&&!(context->multi))){
411 sftk_FreeSession(session);
412 return CKR_OPERATION_NOT_INITIALIZED;
413 }
414 *contextPtr = context;
415 if (sessionPtr != NULL) {
416 *sessionPtr = session;
417 } else {
418 sftk_FreeSession(session);
419 }
420 return CKR_OK;
421 }
423 /** Terminate operation (in the PKCS#11 spec sense).
424 * Intuitive name for FreeContext/SetNullContext pair.
425 */
426 static void
427 sftk_TerminateOp( SFTKSession *session, SFTKContextType ctype,
428 SFTKSessionContext *context )
429 {
430 sftk_FreeContext( context );
431 sftk_SetContextByType( session, ctype, NULL );
432 }
434 /*
435 ************** Crypto Functions: Encrypt ************************
436 */
438 /*
439 * All the NSC_InitXXX functions have a set of common checks and processing they
440 * all need to do at the beginning. This is done here.
441 */
442 static CK_RV
443 sftk_InitGeneric(SFTKSession *session,SFTKSessionContext **contextPtr,
444 SFTKContextType ctype,SFTKObject **keyPtr,
445 CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
446 CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation)
447 {
448 SFTKObject *key = NULL;
449 SFTKAttribute *att;
450 SFTKSessionContext *context;
452 /* We can only init if there is not current context active */
453 if (sftk_ReturnContextByType(session,ctype) != NULL) {
454 return CKR_OPERATION_ACTIVE;
455 }
457 /* find the key */
458 if (keyPtr) {
459 key = sftk_ObjectFromHandle(hKey,session);
460 if (key == NULL) {
461 return CKR_KEY_HANDLE_INVALID;
462 }
464 /* make sure it's a valid key for this operation */
465 if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType))
466 || !sftk_isTrue(key,operation)) {
467 sftk_FreeObject(key);
468 return CKR_KEY_TYPE_INCONSISTENT;
469 }
470 /* get the key type */
471 att = sftk_FindAttribute(key,CKA_KEY_TYPE);
472 if (att == NULL) {
473 sftk_FreeObject(key);
474 return CKR_KEY_TYPE_INCONSISTENT;
475 }
476 PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE));
477 if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) {
478 sftk_FreeAttribute(att);
479 sftk_FreeObject(key);
480 return CKR_ATTRIBUTE_VALUE_INVALID;
481 }
482 PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE));
483 sftk_FreeAttribute(att);
484 *keyPtr = key;
485 }
487 /* allocate the context structure */
488 context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext));
489 if (context == NULL) {
490 if (key) sftk_FreeObject(key);
491 return CKR_HOST_MEMORY;
492 }
493 context->type = ctype;
494 context->multi = PR_TRUE;
495 context->rsa = PR_FALSE;
496 context->cipherInfo = NULL;
497 context->hashInfo = NULL;
498 context->doPad = PR_FALSE;
499 context->padDataLength = 0;
500 context->key = key;
501 context->blockSize = 0;
502 context->maxLen = 0;
504 *contextPtr = context;
505 return CKR_OK;
506 }
508 static int
509 sftk_aes_mode(CK_MECHANISM_TYPE mechanism)
510 {
511 switch (mechanism) {
512 case CKM_AES_CBC_PAD:
513 case CKM_AES_CBC:
514 return NSS_AES_CBC;
515 case CKM_AES_ECB:
516 return NSS_AES;
517 case CKM_AES_CTS:
518 return NSS_AES_CTS;
519 case CKM_AES_CTR:
520 return NSS_AES_CTR;
521 case CKM_AES_GCM:
522 return NSS_AES_GCM;
523 }
524 return -1;
525 }
527 static SECStatus
528 sftk_RSAEncryptRaw(NSSLOWKEYPublicKey *key, unsigned char *output,
529 unsigned int *outputLen, unsigned int maxLen,
530 const unsigned char *input, unsigned int inputLen)
531 {
532 SECStatus rv = SECFailure;
534 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
535 if (key->keyType != NSSLOWKEYRSAKey) {
536 PORT_SetError(SEC_ERROR_INVALID_KEY);
537 return SECFailure;
538 }
540 rv = RSA_EncryptRaw(&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 }
546 return rv;
547 }
549 static SECStatus
550 sftk_RSADecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output,
551 unsigned int *outputLen, unsigned int maxLen,
552 const unsigned char *input, unsigned int inputLen)
553 {
554 SECStatus rv = SECFailure;
556 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
557 if (key->keyType != NSSLOWKEYRSAKey) {
558 PORT_SetError(SEC_ERROR_INVALID_KEY);
559 return SECFailure;
560 }
562 rv = RSA_DecryptRaw(&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 }
568 return rv;
569 }
571 static SECStatus
572 sftk_RSAEncrypt(NSSLOWKEYPublicKey *key, unsigned char *output,
573 unsigned int *outputLen, unsigned int maxLen,
574 const unsigned char *input, unsigned int inputLen)
575 {
576 SECStatus rv = SECFailure;
578 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
579 if (key->keyType != NSSLOWKEYRSAKey) {
580 PORT_SetError(SEC_ERROR_INVALID_KEY);
581 return SECFailure;
582 }
584 rv = RSA_EncryptBlock(&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 }
590 return rv;
591 }
593 static SECStatus
594 sftk_RSADecrypt(NSSLOWKEYPrivateKey *key, unsigned char *output,
595 unsigned int *outputLen, unsigned int maxLen,
596 const unsigned char *input, unsigned int inputLen)
597 {
598 SECStatus rv = SECFailure;
600 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
601 if (key->keyType != NSSLOWKEYRSAKey) {
602 PORT_SetError(SEC_ERROR_INVALID_KEY);
603 return SECFailure;
604 }
606 rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
607 inputLen);
608 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
609 sftk_fatalError = PR_TRUE;
610 }
612 return rv;
613 }
615 static SECStatus
616 sftk_RSAEncryptOAEP(SFTKOAEPEncryptInfo *info, unsigned char *output,
617 unsigned int *outputLen, unsigned int maxLen,
618 const unsigned char *input, unsigned int inputLen)
619 {
620 HASH_HashType hashAlg;
621 HASH_HashType maskHashAlg;
623 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
624 if (info->key->keyType != NSSLOWKEYRSAKey) {
625 PORT_SetError(SEC_ERROR_INVALID_KEY);
626 return SECFailure;
627 }
629 hashAlg = GetHashTypeFromMechanism(info->params->hashAlg);
630 maskHashAlg = GetHashTypeFromMechanism(info->params->mgf);
632 return RSA_EncryptOAEP(&info->key->u.rsa, hashAlg, maskHashAlg,
633 (const unsigned char*)info->params->pSourceData,
634 info->params->ulSourceDataLen, NULL, 0,
635 output, outputLen, maxLen, input, inputLen);
636 }
638 static SECStatus
639 sftk_RSADecryptOAEP(SFTKOAEPDecryptInfo *info, unsigned char *output,
640 unsigned int *outputLen, unsigned int maxLen,
641 const unsigned char *input, unsigned int inputLen)
642 {
643 SECStatus rv = SECFailure;
644 HASH_HashType hashAlg;
645 HASH_HashType maskHashAlg;
647 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
648 if (info->key->keyType != NSSLOWKEYRSAKey) {
649 PORT_SetError(SEC_ERROR_INVALID_KEY);
650 return SECFailure;
651 }
653 hashAlg = GetHashTypeFromMechanism(info->params->hashAlg);
654 maskHashAlg = GetHashTypeFromMechanism(info->params->mgf);
656 rv = RSA_DecryptOAEP(&info->key->u.rsa, hashAlg, maskHashAlg,
657 (const unsigned char*)info->params->pSourceData,
658 info->params->ulSourceDataLen,
659 output, outputLen, maxLen, input, inputLen);
660 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
661 sftk_fatalError = PR_TRUE;
662 }
663 return rv;
664 }
666 /** NSC_CryptInit initializes an encryption/Decryption operation.
667 *
668 * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
669 * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block
670 * ciphers MAC'ing.
671 */
672 static CK_RV
673 sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
674 CK_OBJECT_HANDLE hKey,
675 CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage,
676 SFTKContextType contextType, PRBool isEncrypt)
677 {
678 SFTKSession *session;
679 SFTKObject *key;
680 SFTKSessionContext *context;
681 SFTKAttribute *att;
682 CK_RC2_CBC_PARAMS *rc2_param;
683 #if NSS_SOFTOKEN_DOES_RC5
684 CK_RC5_CBC_PARAMS *rc5_param;
685 SECItem rc5Key;
686 #endif
687 CK_KEY_TYPE key_type;
688 CK_RV crv = CKR_OK;
689 unsigned effectiveKeyLength;
690 unsigned char newdeskey[24];
691 PRBool useNewKey=PR_FALSE;
692 int t;
694 crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage );
695 if (crv != CKR_OK)
696 return crv;
698 session = sftk_SessionFromHandle(hSession);
699 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
701 crv = sftk_InitGeneric(session,&context,contextType,&key,hKey,&key_type,
702 isEncrypt ?CKO_PUBLIC_KEY:CKO_PRIVATE_KEY, keyUsage);
704 if (crv != CKR_OK) {
705 sftk_FreeSession(session);
706 return crv;
707 }
709 context->doPad = PR_FALSE;
710 switch(pMechanism->mechanism) {
711 case CKM_RSA_PKCS:
712 case CKM_RSA_X_509:
713 if (key_type != CKK_RSA) {
714 crv = CKR_KEY_TYPE_INCONSISTENT;
715 break;
716 }
717 context->multi = PR_FALSE;
718 context->rsa = PR_TRUE;
719 if (isEncrypt) {
720 NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key,CKK_RSA,&crv);
721 if (pubKey == NULL) {
722 crv = CKR_KEY_HANDLE_INVALID;
723 break;
724 }
725 context->maxLen = nsslowkey_PublicModulusLen(pubKey);
726 context->cipherInfo = (void *)pubKey;
727 context->update = (SFTKCipher)
728 (pMechanism->mechanism == CKM_RSA_X_509
729 ? sftk_RSAEncryptRaw : sftk_RSAEncrypt);
730 } else {
731 NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key,CKK_RSA,&crv);
732 if (privKey == NULL) {
733 crv = CKR_KEY_HANDLE_INVALID;
734 break;
735 }
736 context->maxLen = nsslowkey_PrivateModulusLen(privKey);
737 context->cipherInfo = (void *)privKey;
738 context->update = (SFTKCipher)
739 (pMechanism->mechanism == CKM_RSA_X_509
740 ? sftk_RSADecryptRaw : sftk_RSADecrypt);
741 }
742 context->destroy = sftk_Null;
743 break;
744 case CKM_RSA_PKCS_OAEP:
745 if (key_type != CKK_RSA) {
746 crv = CKR_KEY_TYPE_INCONSISTENT;
747 break;
748 }
749 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) ||
750 !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter)) {
751 crv = CKR_MECHANISM_PARAM_INVALID;
752 break;
753 }
754 context->multi = PR_FALSE;
755 context->rsa = PR_TRUE;
756 if (isEncrypt) {
757 SFTKOAEPEncryptInfo *info = PORT_New(SFTKOAEPEncryptInfo);
758 if (info == NULL) {
759 crv = CKR_HOST_MEMORY;
760 break;
761 }
762 info->params = pMechanism->pParameter;
763 info->key = sftk_GetPubKey(key, CKK_RSA, &crv);
764 if (info->key == NULL) {
765 PORT_Free(info);
766 crv = CKR_KEY_HANDLE_INVALID;
767 break;
768 }
769 context->update = (SFTKCipher) sftk_RSAEncryptOAEP;
770 context->maxLen = nsslowkey_PublicModulusLen(info->key);
771 context->cipherInfo = info;
772 } else {
773 SFTKOAEPDecryptInfo *info = PORT_New(SFTKOAEPDecryptInfo);
774 if (info == NULL) {
775 crv = CKR_HOST_MEMORY;
776 break;
777 }
778 info->params = pMechanism->pParameter;
779 info->key = sftk_GetPrivKey(key, CKK_RSA, &crv);
780 if (info->key == NULL) {
781 PORT_Free(info);
782 crv = CKR_KEY_HANDLE_INVALID;
783 break;
784 }
785 context->update = (SFTKCipher) sftk_RSADecryptOAEP;
786 context->maxLen = nsslowkey_PrivateModulusLen(info->key);
787 context->cipherInfo = info;
788 }
789 context->destroy = (SFTKDestroy) sftk_Space;
790 break;
791 case CKM_RC2_CBC_PAD:
792 context->doPad = PR_TRUE;
793 /* fall thru */
794 case CKM_RC2_ECB:
795 case CKM_RC2_CBC:
796 context->blockSize = 8;
797 if (key_type != CKK_RC2) {
798 crv = CKR_KEY_TYPE_INCONSISTENT;
799 break;
800 }
801 att = sftk_FindAttribute(key,CKA_VALUE);
802 if (att == NULL) {
803 crv = CKR_KEY_HANDLE_INVALID;
804 break;
805 }
806 rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
807 effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8;
808 context->cipherInfo =
809 RC2_CreateContext((unsigned char*)att->attrib.pValue,
810 att->attrib.ulValueLen, rc2_param->iv,
811 pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 :
812 NSS_RC2_CBC,effectiveKeyLength);
813 sftk_FreeAttribute(att);
814 if (context->cipherInfo == NULL) {
815 crv = CKR_HOST_MEMORY;
816 break;
817 }
818 context->update = (SFTKCipher) (isEncrypt ? RC2_Encrypt : RC2_Decrypt);
819 context->destroy = (SFTKDestroy) RC2_DestroyContext;
820 break;
821 #if NSS_SOFTOKEN_DOES_RC5
822 case CKM_RC5_CBC_PAD:
823 context->doPad = PR_TRUE;
824 /* fall thru */
825 case CKM_RC5_ECB:
826 case CKM_RC5_CBC:
827 if (key_type != CKK_RC5) {
828 crv = CKR_KEY_TYPE_INCONSISTENT;
829 break;
830 }
831 att = sftk_FindAttribute(key,CKA_VALUE);
832 if (att == NULL) {
833 crv = CKR_KEY_HANDLE_INVALID;
834 break;
835 }
836 rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
837 context->blockSize = rc5_param->ulWordsize*2;
838 rc5Key.data = (unsigned char*)att->attrib.pValue;
839 rc5Key.len = att->attrib.ulValueLen;
840 context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds,
841 rc5_param->ulWordsize,rc5_param->pIv,
842 pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
843 sftk_FreeAttribute(att);
844 if (context->cipherInfo == NULL) {
845 crv = CKR_HOST_MEMORY;
846 break;
847 }
848 context->update = (SFTKCipher) (isEncrypt ? RC5_Encrypt : RC5_Decrypt);
849 context->destroy = (SFTKDestroy) RC5_DestroyContext;
850 break;
851 #endif
852 case CKM_RC4:
853 if (key_type != CKK_RC4) {
854 crv = CKR_KEY_TYPE_INCONSISTENT;
855 break;
856 }
857 att = sftk_FindAttribute(key,CKA_VALUE);
858 if (att == NULL) {
859 crv = CKR_KEY_HANDLE_INVALID;
860 break;
861 }
862 context->cipherInfo =
863 RC4_CreateContext((unsigned char*)att->attrib.pValue,
864 att->attrib.ulValueLen);
865 sftk_FreeAttribute(att);
866 if (context->cipherInfo == NULL) {
867 crv = CKR_HOST_MEMORY; /* WRONG !!! */
868 break;
869 }
870 context->update = (SFTKCipher) (isEncrypt ? RC4_Encrypt : RC4_Decrypt);
871 context->destroy = (SFTKDestroy) RC4_DestroyContext;
872 break;
873 case CKM_CDMF_CBC_PAD:
874 context->doPad = PR_TRUE;
875 /* fall thru */
876 case CKM_CDMF_ECB:
877 case CKM_CDMF_CBC:
878 if (key_type != CKK_CDMF) {
879 crv = CKR_KEY_TYPE_INCONSISTENT;
880 break;
881 }
882 t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
883 if (crv != CKR_OK) break;
884 goto finish_des;
885 case CKM_DES_ECB:
886 if (key_type != CKK_DES) {
887 crv = CKR_KEY_TYPE_INCONSISTENT;
888 break;
889 }
890 t = NSS_DES;
891 goto finish_des;
892 case CKM_DES_CBC_PAD:
893 context->doPad = PR_TRUE;
894 /* fall thru */
895 case CKM_DES_CBC:
896 if (key_type != CKK_DES) {
897 crv = CKR_KEY_TYPE_INCONSISTENT;
898 break;
899 }
900 t = NSS_DES_CBC;
901 goto finish_des;
902 case CKM_DES3_ECB:
903 if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
904 crv = CKR_KEY_TYPE_INCONSISTENT;
905 break;
906 }
907 t = NSS_DES_EDE3;
908 goto finish_des;
909 case CKM_DES3_CBC_PAD:
910 context->doPad = PR_TRUE;
911 /* fall thru */
912 case CKM_DES3_CBC:
913 if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
914 crv = CKR_KEY_TYPE_INCONSISTENT;
915 break;
916 }
917 t = NSS_DES_EDE3_CBC;
918 finish_des:
919 context->blockSize = 8;
920 att = sftk_FindAttribute(key,CKA_VALUE);
921 if (att == NULL) {
922 crv = CKR_KEY_HANDLE_INVALID;
923 break;
924 }
925 if (key_type == CKK_DES2 &&
926 (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) {
927 /* extend DES2 key to DES3 key. */
928 memcpy(newdeskey, att->attrib.pValue, 16);
929 memcpy(newdeskey + 16, newdeskey, 8);
930 useNewKey=PR_TRUE;
931 } else if (key_type == CKK_CDMF) {
932 crv = sftk_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey);
933 if (crv != CKR_OK) {
934 sftk_FreeAttribute(att);
935 break;
936 }
937 useNewKey=PR_TRUE;
938 }
939 context->cipherInfo = DES_CreateContext(
940 useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue,
941 (unsigned char*)pMechanism->pParameter,t, isEncrypt);
942 if (useNewKey)
943 memset(newdeskey, 0, sizeof newdeskey);
944 sftk_FreeAttribute(att);
945 if (context->cipherInfo == NULL) {
946 crv = CKR_HOST_MEMORY;
947 break;
948 }
949 context->update = (SFTKCipher) (isEncrypt ? DES_Encrypt : DES_Decrypt);
950 context->destroy = (SFTKDestroy) DES_DestroyContext;
951 break;
952 case CKM_SEED_CBC_PAD:
953 context->doPad = PR_TRUE;
954 /* fall thru */
955 case CKM_SEED_CBC:
956 if (!pMechanism->pParameter ||
957 pMechanism->ulParameterLen != 16) {
958 crv = CKR_MECHANISM_PARAM_INVALID;
959 break;
960 }
961 /* fall thru */
962 case CKM_SEED_ECB:
963 context->blockSize = 16;
964 if (key_type != CKK_SEED) {
965 crv = CKR_KEY_TYPE_INCONSISTENT;
966 break;
967 }
968 att = sftk_FindAttribute(key,CKA_VALUE);
969 if (att == NULL) {
970 crv = CKR_KEY_HANDLE_INVALID;
971 break;
972 }
973 context->cipherInfo = SEED_CreateContext(
974 (unsigned char*)att->attrib.pValue,
975 (unsigned char*)pMechanism->pParameter,
976 pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC,
977 isEncrypt);
978 sftk_FreeAttribute(att);
979 if (context->cipherInfo == NULL) {
980 crv = CKR_HOST_MEMORY;
981 break;
982 }
983 context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt);
984 context->destroy = (SFTKDestroy) SEED_DestroyContext;
985 break;
987 case CKM_CAMELLIA_CBC_PAD:
988 context->doPad = PR_TRUE;
989 /* fall thru */
990 case CKM_CAMELLIA_CBC:
991 if (!pMechanism->pParameter ||
992 pMechanism->ulParameterLen != 16) {
993 crv = CKR_MECHANISM_PARAM_INVALID;
994 break;
995 }
996 /* fall thru */
997 case CKM_CAMELLIA_ECB:
998 context->blockSize = 16;
999 if (key_type != CKK_CAMELLIA) {
1000 crv = CKR_KEY_TYPE_INCONSISTENT;
1001 break;
1002 }
1003 att = sftk_FindAttribute(key,CKA_VALUE);
1004 if (att == NULL) {
1005 crv = CKR_KEY_HANDLE_INVALID;
1006 break;
1007 }
1008 context->cipherInfo = Camellia_CreateContext(
1009 (unsigned char*)att->attrib.pValue,
1010 (unsigned char*)pMechanism->pParameter,
1011 pMechanism->mechanism ==
1012 CKM_CAMELLIA_ECB ? NSS_CAMELLIA : NSS_CAMELLIA_CBC,
1013 isEncrypt, att->attrib.ulValueLen);
1014 sftk_FreeAttribute(att);
1015 if (context->cipherInfo == NULL) {
1016 crv = CKR_HOST_MEMORY;
1017 break;
1018 }
1019 context->update = (SFTKCipher) (isEncrypt ?
1020 Camellia_Encrypt : Camellia_Decrypt);
1021 context->destroy = (SFTKDestroy) Camellia_DestroyContext;
1022 break;
1024 case CKM_AES_CBC_PAD:
1025 context->doPad = PR_TRUE;
1026 /* fall thru */
1027 case CKM_AES_ECB:
1028 case CKM_AES_CBC:
1029 context->blockSize = 16;
1030 case CKM_AES_CTS:
1031 case CKM_AES_CTR:
1032 case CKM_AES_GCM:
1033 if (pMechanism->mechanism == CKM_AES_GCM) {
1034 context->multi = PR_FALSE;
1035 }
1036 if (key_type != CKK_AES) {
1037 crv = CKR_KEY_TYPE_INCONSISTENT;
1038 break;
1039 }
1040 att = sftk_FindAttribute(key,CKA_VALUE);
1041 if (att == NULL) {
1042 crv = CKR_KEY_HANDLE_INVALID;
1043 break;
1044 }
1045 context->cipherInfo = AES_CreateContext(
1046 (unsigned char*)att->attrib.pValue,
1047 (unsigned char*)pMechanism->pParameter,
1048 sftk_aes_mode(pMechanism->mechanism),
1049 isEncrypt, att->attrib.ulValueLen, 16);
1050 sftk_FreeAttribute(att);
1051 if (context->cipherInfo == NULL) {
1052 crv = CKR_HOST_MEMORY;
1053 break;
1054 }
1055 context->update = (SFTKCipher) (isEncrypt ? AES_Encrypt : AES_Decrypt);
1056 context->destroy = (SFTKDestroy) AES_DestroyContext;
1057 break;
1059 case CKM_NETSCAPE_AES_KEY_WRAP_PAD:
1060 context->doPad = PR_TRUE;
1061 /* fall thru */
1062 case CKM_NETSCAPE_AES_KEY_WRAP:
1063 context->multi = PR_FALSE;
1064 context->blockSize = 8;
1065 if (key_type != CKK_AES) {
1066 crv = CKR_KEY_TYPE_INCONSISTENT;
1067 break;
1068 }
1069 att = sftk_FindAttribute(key,CKA_VALUE);
1070 if (att == NULL) {
1071 crv = CKR_KEY_HANDLE_INVALID;
1072 break;
1073 }
1074 context->cipherInfo = AESKeyWrap_CreateContext(
1075 (unsigned char*)att->attrib.pValue,
1076 (unsigned char*)pMechanism->pParameter,
1077 isEncrypt, att->attrib.ulValueLen);
1078 sftk_FreeAttribute(att);
1079 if (context->cipherInfo == NULL) {
1080 crv = CKR_HOST_MEMORY;
1081 break;
1082 }
1083 context->update = (SFTKCipher) (isEncrypt ? AESKeyWrap_Encrypt
1084 : AESKeyWrap_Decrypt);
1085 context->destroy = (SFTKDestroy) AESKeyWrap_DestroyContext;
1086 break;
1088 default:
1089 crv = CKR_MECHANISM_INVALID;
1090 break;
1091 }
1093 if (crv != CKR_OK) {
1094 sftk_FreeContext(context);
1095 sftk_FreeSession(session);
1096 return crv;
1097 }
1098 sftk_SetContextByType(session, contextType, context);
1099 sftk_FreeSession(session);
1100 return CKR_OK;
1101 }
1103 /* NSC_EncryptInit initializes an encryption operation. */
1104 CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession,
1105 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1106 {
1107 CHECK_FORK();
1108 return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT,
1109 SFTK_ENCRYPT, PR_TRUE);
1110 }
1112 /* NSC_EncryptUpdate continues a multiple-part encryption operation. */
1113 CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
1114 CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
1115 CK_ULONG_PTR pulEncryptedPartLen)
1116 {
1117 SFTKSessionContext *context;
1118 unsigned int outlen,i;
1119 unsigned int padoutlen = 0;
1120 unsigned int maxout = *pulEncryptedPartLen;
1121 CK_RV crv;
1122 SECStatus rv;
1124 CHECK_FORK();
1126 /* make sure we're legal */
1127 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,NULL);
1128 if (crv != CKR_OK) return crv;
1130 if (!pEncryptedPart) {
1131 if (context->doPad) {
1132 CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength;
1133 CK_ULONG blocksToSend = totalDataAvailable/context->blockSize;
1135 *pulEncryptedPartLen = blocksToSend * context->blockSize;
1136 return CKR_OK;
1137 }
1138 *pulEncryptedPartLen = ulPartLen;
1139 return CKR_OK;
1140 }
1142 /* do padding */
1143 if (context->doPad) {
1144 /* deal with previous buffered data */
1145 if (context->padDataLength != 0) {
1146 /* fill in the padded to a full block size */
1147 for (i=context->padDataLength;
1148 (ulPartLen != 0) && i < context->blockSize; i++) {
1149 context->padBuf[i] = *pPart++;
1150 ulPartLen--;
1151 context->padDataLength++;
1152 }
1154 /* not enough data to encrypt yet? then return */
1155 if (context->padDataLength != context->blockSize) {
1156 *pulEncryptedPartLen = 0;
1157 return CKR_OK;
1158 }
1159 /* encrypt the current padded data */
1160 rv = (*context->update)(context->cipherInfo, pEncryptedPart,
1161 &padoutlen, context->blockSize, context->padBuf,
1162 context->blockSize);
1163 if (rv != SECSuccess) {
1164 return sftk_MapCryptError(PORT_GetError());
1165 }
1166 pEncryptedPart += padoutlen;
1167 maxout -= padoutlen;
1168 }
1169 /* save the residual */
1170 context->padDataLength = ulPartLen % context->blockSize;
1171 if (context->padDataLength) {
1172 PORT_Memcpy(context->padBuf,
1173 &pPart[ulPartLen-context->padDataLength],
1174 context->padDataLength);
1175 ulPartLen -= context->padDataLength;
1176 }
1177 /* if we've exhausted our new buffer, we're done */
1178 if (ulPartLen == 0) {
1179 *pulEncryptedPartLen = padoutlen;
1180 return CKR_OK;
1181 }
1182 }
1185 /* do it: NOTE: this assumes buf size in is >= buf size out! */
1186 rv = (*context->update)(context->cipherInfo,pEncryptedPart,
1187 &outlen, maxout, pPart, ulPartLen);
1188 *pulEncryptedPartLen = (CK_ULONG) (outlen + padoutlen);
1189 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1190 }
1193 /* NSC_EncryptFinal finishes a multiple-part encryption operation. */
1194 CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
1195 CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
1196 {
1197 SFTKSession *session;
1198 SFTKSessionContext *context;
1199 unsigned int outlen,i;
1200 unsigned int maxout = *pulLastEncryptedPartLen;
1201 CK_RV crv;
1202 SECStatus rv = SECSuccess;
1203 PRBool contextFinished = PR_TRUE;
1205 CHECK_FORK();
1207 /* make sure we're legal */
1208 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,&session);
1209 if (crv != CKR_OK) return crv;
1211 *pulLastEncryptedPartLen = 0;
1212 if (!pLastEncryptedPart) {
1213 /* caller is checking the amount of remaining data */
1214 if (context->blockSize > 0 && context->doPad) {
1215 *pulLastEncryptedPartLen = context->blockSize;
1216 contextFinished = PR_FALSE; /* still have padding to go */
1217 }
1218 goto finish;
1219 }
1221 /* do padding */
1222 if (context->doPad) {
1223 unsigned char padbyte = (unsigned char)
1224 (context->blockSize - context->padDataLength);
1225 /* fill out rest of pad buffer with pad magic*/
1226 for (i=context->padDataLength; i < context->blockSize; i++) {
1227 context->padBuf[i] = padbyte;
1228 }
1229 rv = (*context->update)(context->cipherInfo,pLastEncryptedPart,
1230 &outlen, maxout, context->padBuf, context->blockSize);
1231 if (rv == SECSuccess) *pulLastEncryptedPartLen = (CK_ULONG) outlen;
1232 }
1234 finish:
1235 if (contextFinished)
1236 sftk_TerminateOp( session, SFTK_ENCRYPT, context );
1237 sftk_FreeSession(session);
1238 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1239 }
1241 /* NSC_Encrypt encrypts single-part data. */
1242 CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
1243 CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
1244 CK_ULONG_PTR pulEncryptedDataLen)
1245 {
1246 SFTKSession *session;
1247 SFTKSessionContext *context;
1248 unsigned int outlen;
1249 unsigned int maxoutlen = *pulEncryptedDataLen;
1250 CK_RV crv;
1251 CK_RV crv2;
1252 SECStatus rv = SECSuccess;
1253 SECItem pText;
1255 pText.type = siBuffer;
1256 pText.data = pData;
1257 pText.len = ulDataLen;
1259 CHECK_FORK();
1261 /* make sure we're legal */
1262 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,&session);
1263 if (crv != CKR_OK) return crv;
1265 if (!pEncryptedData) {
1266 *pulEncryptedDataLen = context->rsa ? context->maxLen :
1267 ulDataLen + 2 * context->blockSize;
1268 goto finish;
1269 }
1271 if (context->doPad) {
1272 if (context->multi) {
1273 CK_ULONG finalLen;
1274 /* padding is fairly complicated, have the update and final
1275 * code deal with it */
1276 sftk_FreeSession(session);
1277 crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData,
1278 pulEncryptedDataLen);
1279 if (crv != CKR_OK)
1280 *pulEncryptedDataLen = 0;
1281 maxoutlen -= *pulEncryptedDataLen;
1282 pEncryptedData += *pulEncryptedDataLen;
1283 finalLen = maxoutlen;
1284 crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
1285 if (crv2 == CKR_OK)
1286 *pulEncryptedDataLen += finalLen;
1287 return crv == CKR_OK ? crv2 : crv;
1288 }
1289 /* doPad without multi means that padding must be done on the first
1290 ** and only update. There will be no final.
1291 */
1292 PORT_Assert(context->blockSize > 1);
1293 if (context->blockSize > 1) {
1294 CK_ULONG remainder = ulDataLen % context->blockSize;
1295 CK_ULONG padding = context->blockSize - remainder;
1296 pText.len += padding;
1297 pText.data = PORT_ZAlloc(pText.len);
1298 if (pText.data) {
1299 memcpy(pText.data, pData, ulDataLen);
1300 memset(pText.data + ulDataLen, padding, padding);
1301 } else {
1302 crv = CKR_HOST_MEMORY;
1303 goto fail;
1304 }
1305 }
1306 }
1308 /* do it: NOTE: this assumes buf size is big enough. */
1309 rv = (*context->update)(context->cipherInfo, pEncryptedData,
1310 &outlen, maxoutlen, pText.data, pText.len);
1311 crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1312 *pulEncryptedDataLen = (CK_ULONG) outlen;
1313 if (pText.data != pData)
1314 PORT_ZFree(pText.data, pText.len);
1315 fail:
1316 sftk_TerminateOp( session, SFTK_ENCRYPT, context );
1317 finish:
1318 sftk_FreeSession(session);
1320 return crv;
1321 }
1324 /*
1325 ************** Crypto Functions: Decrypt ************************
1326 */
1328 /* NSC_DecryptInit initializes a decryption operation. */
1329 CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession,
1330 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1331 {
1332 CHECK_FORK();
1333 return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT,
1334 SFTK_DECRYPT, PR_FALSE);
1335 }
1337 /* NSC_DecryptUpdate continues a multiple-part decryption operation. */
1338 CK_RV NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
1339 CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
1340 CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
1341 {
1342 SFTKSessionContext *context;
1343 unsigned int padoutlen = 0;
1344 unsigned int outlen;
1345 unsigned int maxout = *pulPartLen;
1346 CK_RV crv;
1347 SECStatus rv;
1349 CHECK_FORK();
1351 /* make sure we're legal */
1352 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,NULL);
1353 if (crv != CKR_OK) return crv;
1355 /* this can only happen on an NSS programming error */
1356 PORT_Assert((context->padDataLength == 0)
1357 || context->padDataLength == context->blockSize);
1360 if (context->doPad) {
1361 /* Check the data length for block ciphers. If we are padding,
1362 * then we must be using a block cipher. In the non-padding case
1363 * the error will be returned by the underlying decryption
1364 * function when we do the actual decrypt. We need to do the
1365 * check here to avoid returning a negative length to the caller
1366 * or reading before the beginning of the pEncryptedPart buffer.
1367 */
1368 if ((ulEncryptedPartLen == 0) ||
1369 (ulEncryptedPartLen % context->blockSize) != 0) {
1370 return CKR_ENCRYPTED_DATA_LEN_RANGE;
1371 }
1372 }
1374 if (!pPart) {
1375 if (context->doPad) {
1376 *pulPartLen =
1377 ulEncryptedPartLen + context->padDataLength - context->blockSize;
1378 return CKR_OK;
1379 }
1380 /* for stream ciphers there is are no constraints on ulEncryptedPartLen.
1381 * for block ciphers, it must be a multiple of blockSize. The error is
1382 * detected when this function is called again do decrypt the output.
1383 */
1384 *pulPartLen = ulEncryptedPartLen;
1385 return CKR_OK;
1386 }
1388 if (context->doPad) {
1389 /* first decrypt our saved buffer */
1390 if (context->padDataLength != 0) {
1391 rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
1392 maxout, context->padBuf, context->blockSize);
1393 if (rv != SECSuccess) return sftk_MapDecryptError(PORT_GetError());
1394 pPart += padoutlen;
1395 maxout -= padoutlen;
1396 }
1397 /* now save the final block for the next decrypt or the final */
1398 PORT_Memcpy(context->padBuf,&pEncryptedPart[ulEncryptedPartLen -
1399 context->blockSize], context->blockSize);
1400 context->padDataLength = context->blockSize;
1401 ulEncryptedPartLen -= context->padDataLength;
1402 }
1404 /* do it: NOTE: this assumes buf size in is >= buf size out! */
1405 rv = (*context->update)(context->cipherInfo,pPart, &outlen,
1406 maxout, pEncryptedPart, ulEncryptedPartLen);
1407 *pulPartLen = (CK_ULONG) (outlen + padoutlen);
1408 return (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
1409 }
1412 /* NSC_DecryptFinal finishes a multiple-part decryption operation. */
1413 CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
1414 CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
1415 {
1416 SFTKSession *session;
1417 SFTKSessionContext *context;
1418 unsigned int outlen;
1419 unsigned int maxout = *pulLastPartLen;
1420 CK_RV crv;
1421 SECStatus rv = SECSuccess;
1423 CHECK_FORK();
1425 /* make sure we're legal */
1426 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,&session);
1427 if (crv != CKR_OK) return crv;
1429 *pulLastPartLen = 0;
1430 if (!pLastPart) {
1431 /* caller is checking the amount of remaining data */
1432 if (context->padDataLength > 0) {
1433 *pulLastPartLen = context->padDataLength;
1434 }
1435 goto finish;
1436 }
1438 if (context->doPad) {
1439 /* decrypt our saved buffer */
1440 if (context->padDataLength != 0) {
1441 /* this assumes that pLastPart is big enough to hold the *whole*
1442 * buffer!!! */
1443 rv = (*context->update)(context->cipherInfo, pLastPart, &outlen,
1444 maxout, context->padBuf, context->blockSize);
1445 if (rv != SECSuccess) {
1446 crv = sftk_MapDecryptError(PORT_GetError());
1447 } else {
1448 unsigned int padSize =
1449 (unsigned int) pLastPart[context->blockSize-1];
1450 if ((padSize > context->blockSize) || (padSize == 0)) {
1451 crv = CKR_ENCRYPTED_DATA_INVALID;
1452 } else {
1453 unsigned int i;
1454 unsigned int badPadding = 0; /* used as a boolean */
1455 for (i = 0; i < padSize; i++) {
1456 badPadding |=
1457 (unsigned int) pLastPart[context->blockSize-1-i] ^
1458 padSize;
1459 }
1460 if (badPadding) {
1461 crv = CKR_ENCRYPTED_DATA_INVALID;
1462 } else {
1463 *pulLastPartLen = outlen - padSize;
1464 }
1465 }
1466 }
1467 }
1468 }
1470 sftk_TerminateOp( session, SFTK_DECRYPT, context );
1471 finish:
1472 sftk_FreeSession(session);
1473 return crv;
1474 }
1476 /* NSC_Decrypt decrypts encrypted data in a single part. */
1477 CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession,
1478 CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,
1479 CK_ULONG_PTR pulDataLen)
1480 {
1481 SFTKSession *session;
1482 SFTKSessionContext *context;
1483 unsigned int outlen;
1484 unsigned int maxoutlen = *pulDataLen;
1485 CK_RV crv;
1486 CK_RV crv2;
1487 SECStatus rv = SECSuccess;
1489 CHECK_FORK();
1491 /* make sure we're legal */
1492 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_FALSE,&session);
1493 if (crv != CKR_OK) return crv;
1495 if (!pData) {
1496 *pulDataLen = ulEncryptedDataLen + context->blockSize;
1497 goto finish;
1498 }
1500 if (context->doPad && context->multi) {
1501 CK_ULONG finalLen;
1502 /* padding is fairly complicated, have the update and final
1503 * code deal with it */
1504 sftk_FreeSession(session);
1505 crv = NSC_DecryptUpdate(hSession,pEncryptedData,ulEncryptedDataLen,
1506 pData, pulDataLen);
1507 if (crv != CKR_OK)
1508 *pulDataLen = 0;
1509 maxoutlen -= *pulDataLen;
1510 pData += *pulDataLen;
1511 finalLen = maxoutlen;
1512 crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
1513 if (crv2 == CKR_OK)
1514 *pulDataLen += finalLen;
1515 return crv == CKR_OK ? crv2 : crv;
1516 }
1518 rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
1519 pEncryptedData, ulEncryptedDataLen);
1520 /* XXX need to do MUCH better error mapping than this. */
1521 crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
1522 if (rv == SECSuccess && context->doPad) {
1523 unsigned int padding = pData[outlen - 1];
1524 if (padding > context->blockSize || !padding) {
1525 crv = CKR_ENCRYPTED_DATA_INVALID;
1526 } else {
1527 unsigned int i;
1528 unsigned int badPadding = 0; /* used as a boolean */
1529 for (i = 0; i < padding; i++) {
1530 badPadding |= (unsigned int) pData[outlen - 1 - i] ^ padding;
1531 }
1532 if (badPadding) {
1533 crv = CKR_ENCRYPTED_DATA_INVALID;
1534 } else {
1535 outlen -= padding;
1536 }
1537 }
1538 }
1539 *pulDataLen = (CK_ULONG) outlen;
1540 sftk_TerminateOp( session, SFTK_DECRYPT, context );
1541 finish:
1542 sftk_FreeSession(session);
1543 return crv;
1544 }
1548 /*
1549 ************** Crypto Functions: Digest (HASH) ************************
1550 */
1552 /* NSC_DigestInit initializes a message-digesting operation. */
1553 CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession,
1554 CK_MECHANISM_PTR pMechanism)
1555 {
1556 SFTKSession *session;
1557 SFTKSessionContext *context;
1558 CK_RV crv = CKR_OK;
1560 CHECK_FORK();
1562 session = sftk_SessionFromHandle(hSession);
1563 if (session == NULL)
1564 return CKR_SESSION_HANDLE_INVALID;
1565 crv = sftk_InitGeneric(session,&context,SFTK_HASH,NULL,0,NULL, 0, 0);
1566 if (crv != CKR_OK) {
1567 sftk_FreeSession(session);
1568 return crv;
1569 }
1572 #define INIT_MECH(mech,mmm) \
1573 case mech: { \
1574 mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \
1575 context->cipherInfo = (void *)mmm ## _ctx; \
1576 context->cipherInfoLen = mmm ## _FlattenSize(mmm ## _ctx); \
1577 context->currentMech = mech; \
1578 context->hashUpdate = (SFTKHash) mmm ## _Update; \
1579 context->end = (SFTKEnd) mmm ## _End; \
1580 context->destroy = (SFTKDestroy) mmm ## _DestroyContext; \
1581 context->maxLen = mmm ## _LENGTH; \
1582 if (mmm ## _ctx) \
1583 mmm ## _Begin(mmm ## _ctx); \
1584 else \
1585 crv = CKR_HOST_MEMORY; \
1586 break; \
1587 }
1589 switch(pMechanism->mechanism) {
1590 INIT_MECH(CKM_MD2, MD2)
1591 INIT_MECH(CKM_MD5, MD5)
1592 INIT_MECH(CKM_SHA_1, SHA1)
1593 INIT_MECH(CKM_SHA224, SHA224)
1594 INIT_MECH(CKM_SHA256, SHA256)
1595 INIT_MECH(CKM_SHA384, SHA384)
1596 INIT_MECH(CKM_SHA512, SHA512)
1598 default:
1599 crv = CKR_MECHANISM_INVALID;
1600 break;
1601 }
1603 if (crv != CKR_OK) {
1604 sftk_FreeContext(context);
1605 sftk_FreeSession(session);
1606 return crv;
1607 }
1608 sftk_SetContextByType(session, SFTK_HASH, context);
1609 sftk_FreeSession(session);
1610 return CKR_OK;
1611 }
1614 /* NSC_Digest digests data in a single part. */
1615 CK_RV NSC_Digest(CK_SESSION_HANDLE hSession,
1616 CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
1617 CK_ULONG_PTR pulDigestLen)
1618 {
1619 SFTKSession *session;
1620 SFTKSessionContext *context;
1621 unsigned int digestLen;
1622 unsigned int maxout = *pulDigestLen;
1623 CK_RV crv;
1625 CHECK_FORK();
1627 /* make sure we're legal */
1628 crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_FALSE,&session);
1629 if (crv != CKR_OK) return crv;
1631 if (pDigest == NULL) {
1632 *pulDigestLen = context->maxLen;
1633 goto finish;
1634 }
1636 /* do it: */
1637 (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
1638 /* NOTE: this assumes buf size is bigenough for the algorithm */
1639 (*context->end)(context->cipherInfo, pDigest, &digestLen,maxout);
1640 *pulDigestLen = digestLen;
1642 sftk_TerminateOp( session, SFTK_HASH, context );
1643 finish:
1644 sftk_FreeSession(session);
1645 return CKR_OK;
1646 }
1649 /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
1650 CK_RV NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
1651 CK_ULONG ulPartLen)
1652 {
1653 SFTKSessionContext *context;
1654 CK_RV crv;
1656 CHECK_FORK();
1658 /* make sure we're legal */
1659 crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_TRUE,NULL);
1660 if (crv != CKR_OK) return crv;
1661 /* do it: */
1662 (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);
1663 return CKR_OK;
1664 }
1667 /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
1668 CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,
1669 CK_ULONG_PTR pulDigestLen)
1670 {
1671 SFTKSession *session;
1672 SFTKSessionContext *context;
1673 unsigned int maxout = *pulDigestLen;
1674 unsigned int digestLen;
1675 CK_RV crv;
1677 CHECK_FORK();
1679 /* make sure we're legal */
1680 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
1681 if (crv != CKR_OK) return crv;
1683 if (pDigest != NULL) {
1684 (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
1685 *pulDigestLen = digestLen;
1686 sftk_TerminateOp( session, SFTK_HASH, context );
1687 } else {
1688 *pulDigestLen = context->maxLen;
1689 }
1691 sftk_FreeSession(session);
1692 return CKR_OK;
1693 }
1695 /*
1696 * these helper functions are used by Generic Macing and Signing functions
1697 * that use hashes as part of their operations.
1698 */
1699 #define DOSUB(mmm) \
1700 static CK_RV \
1701 sftk_doSub ## mmm(SFTKSessionContext *context) { \
1702 mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \
1703 context->hashInfo = (void *) mmm ## _ctx; \
1704 context->hashUpdate = (SFTKHash) mmm ## _Update; \
1705 context->end = (SFTKEnd) mmm ## _End; \
1706 context->hashdestroy = (SFTKDestroy) mmm ## _DestroyContext; \
1707 if (!context->hashInfo) { \
1708 return CKR_HOST_MEMORY; \
1709 } \
1710 mmm ## _Begin( mmm ## _ctx ); \
1711 return CKR_OK; \
1712 }
1714 DOSUB(MD2)
1715 DOSUB(MD5)
1716 DOSUB(SHA1)
1717 DOSUB(SHA224)
1718 DOSUB(SHA256)
1719 DOSUB(SHA384)
1720 DOSUB(SHA512)
1722 static SECStatus
1723 sftk_SignCopy(
1724 CK_ULONG *copyLen,
1725 void *out, unsigned int *outLength,
1726 unsigned int maxLength,
1727 const unsigned char *hashResult,
1728 unsigned int hashResultLength)
1729 {
1730 unsigned int toCopy = *copyLen;
1731 if (toCopy > maxLength) {
1732 toCopy = maxLength;
1733 }
1734 if (toCopy > hashResultLength) {
1735 toCopy = hashResultLength;
1736 }
1737 memcpy(out, hashResult, toCopy);
1738 if (outLength) {
1739 *outLength = toCopy;
1740 }
1741 return SECSuccess;
1742 }
1744 /* Verify is just a compare for HMAC */
1745 static SECStatus
1746 sftk_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen,
1747 unsigned char *hash, unsigned int hashLen)
1748 {
1749 return (PORT_Memcmp(sig,hash,*copyLen) == 0) ? SECSuccess : SECFailure ;
1750 }
1752 /*
1753 * common HMAC initalization routine
1754 */
1755 static CK_RV
1756 sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash,
1757 SFTKObject *key, CK_ULONG mac_size)
1758 {
1759 SFTKAttribute *keyval;
1760 HMACContext *HMACcontext;
1761 CK_ULONG *intpointer;
1762 const SECHashObject *hashObj = HASH_GetRawHashObject(hash);
1763 PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID);
1765 /* required by FIPS 198 Section 4 */
1766 if (isFIPS && (mac_size < 4 || mac_size < hashObj->length/2)) {
1767 return CKR_BUFFER_TOO_SMALL;
1768 }
1770 keyval = sftk_FindAttribute(key,CKA_VALUE);
1771 if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
1773 HMACcontext = HMAC_Create(hashObj,
1774 (const unsigned char*)keyval->attrib.pValue,
1775 keyval->attrib.ulValueLen, isFIPS);
1776 context->hashInfo = HMACcontext;
1777 context->multi = PR_TRUE;
1778 sftk_FreeAttribute(keyval);
1779 if (context->hashInfo == NULL) {
1780 if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) {
1781 return CKR_KEY_SIZE_RANGE;
1782 }
1783 return CKR_HOST_MEMORY;
1784 }
1785 context->hashUpdate = (SFTKHash) HMAC_Update;
1786 context->end = (SFTKEnd) HMAC_Finish;
1788 context->hashdestroy = (SFTKDestroy) HMAC_Destroy;
1789 intpointer = PORT_New(CK_ULONG);
1790 if (intpointer == NULL) {
1791 return CKR_HOST_MEMORY;
1792 }
1793 *intpointer = mac_size;
1794 context->cipherInfo = intpointer;
1795 context->destroy = (SFTKDestroy) sftk_Space;
1796 context->update = (SFTKCipher) sftk_SignCopy;
1797 context->verify = (SFTKVerify) sftk_HMACCmp;
1798 context->maxLen = hashObj->length;
1799 HMAC_Begin(HMACcontext);
1800 return CKR_OK;
1801 }
1803 /*
1804 * SSL Macing support. SSL Macs are inited, then update with the base
1805 * hashing algorithm, then finalized in sign and verify
1806 */
1808 /*
1809 * FROM SSL:
1810 * 60 bytes is 3 times the maximum length MAC size that is supported.
1811 * We probably should have one copy of this table. We still need this table
1812 * in ssl to 'sign' the handshake hashes.
1813 */
1814 static unsigned char ssl_pad_1 [60] = {
1815 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1816 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1817 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1818 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1819 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1820 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1821 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1822 0x36, 0x36, 0x36, 0x36
1823 };
1824 static unsigned char ssl_pad_2 [60] = {
1825 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1826 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1827 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1828 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1829 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1830 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1831 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1832 0x5c, 0x5c, 0x5c, 0x5c
1833 };
1835 static SECStatus
1836 sftk_SSLMACSign(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int *sigLen,
1837 unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
1838 {
1839 unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
1840 unsigned int out;
1842 info->begin(info->hashContext);
1843 info->update(info->hashContext,info->key,info->keySize);
1844 info->update(info->hashContext,ssl_pad_2,info->padSize);
1845 info->update(info->hashContext,hash,hashLen);
1846 info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH);
1847 PORT_Memcpy(sig,tmpBuf,info->macSize);
1848 *sigLen = info->macSize;
1849 return SECSuccess;
1850 }
1852 static SECStatus
1853 sftk_SSLMACVerify(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int sigLen,
1854 unsigned char *hash, unsigned int hashLen)
1855 {
1856 unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
1857 unsigned int out;
1859 info->begin(info->hashContext);
1860 info->update(info->hashContext,info->key,info->keySize);
1861 info->update(info->hashContext,ssl_pad_2,info->padSize);
1862 info->update(info->hashContext,hash,hashLen);
1863 info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH);
1864 return (PORT_Memcmp(sig,tmpBuf,info->macSize) == 0) ?
1865 SECSuccess : SECFailure;
1866 }
1868 /*
1869 * common HMAC initalization routine
1870 */
1871 static CK_RV
1872 sftk_doSSLMACInit(SFTKSessionContext *context,SECOidTag oid,
1873 SFTKObject *key, CK_ULONG mac_size)
1874 {
1875 SFTKAttribute *keyval;
1876 SFTKBegin begin;
1877 int padSize;
1878 SFTKSSLMACInfo *sslmacinfo;
1879 CK_RV crv = CKR_MECHANISM_INVALID;
1881 if (oid == SEC_OID_SHA1) {
1882 crv = sftk_doSubSHA1(context);
1883 if (crv != CKR_OK) return crv;
1884 begin = (SFTKBegin) SHA1_Begin;
1885 padSize = 40;
1886 } else {
1887 crv = sftk_doSubMD5(context);
1888 if (crv != CKR_OK) return crv;
1889 begin = (SFTKBegin) MD5_Begin;
1890 padSize = 48;
1891 }
1892 context->multi = PR_TRUE;
1894 keyval = sftk_FindAttribute(key,CKA_VALUE);
1895 if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
1897 context->hashUpdate(context->hashInfo,keyval->attrib.pValue,
1898 keyval->attrib.ulValueLen);
1899 context->hashUpdate(context->hashInfo,ssl_pad_1,padSize);
1900 sslmacinfo = (SFTKSSLMACInfo *) PORT_Alloc(sizeof(SFTKSSLMACInfo));
1901 if (sslmacinfo == NULL) {
1902 sftk_FreeAttribute(keyval);
1903 return CKR_HOST_MEMORY;
1904 }
1905 sslmacinfo->macSize = mac_size;
1906 sslmacinfo->hashContext = context->hashInfo;
1907 PORT_Memcpy(sslmacinfo->key,keyval->attrib.pValue,
1908 keyval->attrib.ulValueLen);
1909 sslmacinfo->keySize = keyval->attrib.ulValueLen;
1910 sslmacinfo->begin = begin;
1911 sslmacinfo->end = context->end;
1912 sslmacinfo->update = context->hashUpdate;
1913 sslmacinfo->padSize = padSize;
1914 sftk_FreeAttribute(keyval);
1915 context->cipherInfo = (void *) sslmacinfo;
1916 context->destroy = (SFTKDestroy) sftk_Space;
1917 context->update = (SFTKCipher) sftk_SSLMACSign;
1918 context->verify = (SFTKVerify) sftk_SSLMACVerify;
1919 context->maxLen = mac_size;
1920 return CKR_OK;
1921 }
1923 /*
1924 ************** Crypto Functions: Sign ************************
1925 */
1927 /**
1928 * Check if We're using CBCMacing and initialize the session context if we are.
1929 * @param contextType SFTK_SIGN or SFTK_VERIFY
1930 * @param keyUsage check whether key allows this usage
1931 */
1932 static CK_RV
1933 sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
1934 CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,
1935 SFTKContextType contextType)
1937 {
1938 CK_MECHANISM cbc_mechanism;
1939 CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
1940 CK_RC2_CBC_PARAMS rc2_params;
1941 #if NSS_SOFTOKEN_DOES_RC5
1942 CK_RC5_CBC_PARAMS rc5_params;
1943 CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
1944 #endif
1945 unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
1946 SFTKSessionContext *context;
1947 CK_RV crv;
1948 unsigned int blockSize;
1950 switch (pMechanism->mechanism) {
1951 case CKM_RC2_MAC_GENERAL:
1952 mac_bytes =
1953 ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
1954 /* fall through */
1955 case CKM_RC2_MAC:
1956 /* this works because ulEffectiveBits is in the same place in both the
1957 * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */
1958 rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *)
1959 pMechanism->pParameter)->ulEffectiveBits;
1960 PORT_Memset(rc2_params.iv,0,sizeof(rc2_params.iv));
1961 cbc_mechanism.mechanism = CKM_RC2_CBC;
1962 cbc_mechanism.pParameter = &rc2_params;
1963 cbc_mechanism.ulParameterLen = sizeof(rc2_params);
1964 blockSize = 8;
1965 break;
1966 #if NSS_SOFTOKEN_DOES_RC5
1967 case CKM_RC5_MAC_GENERAL:
1968 mac_bytes =
1969 ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
1970 /* fall through */
1971 case CKM_RC5_MAC:
1972 /* this works because ulEffectiveBits is in the same place in both the
1973 * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
1974 rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
1975 rc5_params.ulWordsize = rc5_mac->ulWordsize;
1976 rc5_params.ulRounds = rc5_mac->ulRounds;
1977 rc5_params.pIv = ivBlock;
1978 if( (blockSize = rc5_mac->ulWordsize*2) > SFTK_MAX_BLOCK_SIZE )
1979 return CKR_MECHANISM_PARAM_INVALID;
1980 rc5_params.ulIvLen = blockSize;
1981 PORT_Memset(ivBlock,0,blockSize);
1982 cbc_mechanism.mechanism = CKM_RC5_CBC;
1983 cbc_mechanism.pParameter = &rc5_params;
1984 cbc_mechanism.ulParameterLen = sizeof(rc5_params);
1985 break;
1986 #endif
1987 /* add cast and idea later */
1988 case CKM_DES_MAC_GENERAL:
1989 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1990 /* fall through */
1991 case CKM_DES_MAC:
1992 blockSize = 8;
1993 PORT_Memset(ivBlock,0,blockSize);
1994 cbc_mechanism.mechanism = CKM_DES_CBC;
1995 cbc_mechanism.pParameter = &ivBlock;
1996 cbc_mechanism.ulParameterLen = blockSize;
1997 break;
1998 case CKM_DES3_MAC_GENERAL:
1999 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2000 /* fall through */
2001 case CKM_DES3_MAC:
2002 blockSize = 8;
2003 PORT_Memset(ivBlock,0,blockSize);
2004 cbc_mechanism.mechanism = CKM_DES3_CBC;
2005 cbc_mechanism.pParameter = &ivBlock;
2006 cbc_mechanism.ulParameterLen = blockSize;
2007 break;
2008 case CKM_CDMF_MAC_GENERAL:
2009 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2010 /* fall through */
2011 case CKM_CDMF_MAC:
2012 blockSize = 8;
2013 PORT_Memset(ivBlock,0,blockSize);
2014 cbc_mechanism.mechanism = CKM_CDMF_CBC;
2015 cbc_mechanism.pParameter = &ivBlock;
2016 cbc_mechanism.ulParameterLen = blockSize;
2017 break;
2018 case CKM_SEED_MAC_GENERAL:
2019 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2020 /* fall through */
2021 case CKM_SEED_MAC:
2022 blockSize = 16;
2023 PORT_Memset(ivBlock,0,blockSize);
2024 cbc_mechanism.mechanism = CKM_SEED_CBC;
2025 cbc_mechanism.pParameter = &ivBlock;
2026 cbc_mechanism.ulParameterLen = blockSize;
2027 break;
2028 case CKM_CAMELLIA_MAC_GENERAL:
2029 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2030 /* fall through */
2031 case CKM_CAMELLIA_MAC:
2032 blockSize = 16;
2033 PORT_Memset(ivBlock,0,blockSize);
2034 cbc_mechanism.mechanism = CKM_CAMELLIA_CBC;
2035 cbc_mechanism.pParameter = &ivBlock;
2036 cbc_mechanism.ulParameterLen = blockSize;
2037 break;
2038 case CKM_AES_MAC_GENERAL:
2039 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2040 /* fall through */
2041 case CKM_AES_MAC:
2042 blockSize = 16;
2043 PORT_Memset(ivBlock,0,blockSize);
2044 cbc_mechanism.mechanism = CKM_AES_CBC;
2045 cbc_mechanism.pParameter = &ivBlock;
2046 cbc_mechanism.ulParameterLen = blockSize;
2047 break;
2048 default:
2049 return CKR_FUNCTION_NOT_SUPPORTED;
2050 }
2052 /* if MAC size is externally supplied, it should be checked.
2053 */
2054 if (mac_bytes == SFTK_INVALID_MAC_SIZE)
2055 mac_bytes = blockSize >> 1;
2056 else {
2057 if( mac_bytes > blockSize )
2058 return CKR_MECHANISM_PARAM_INVALID;
2059 }
2061 crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
2062 CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
2063 keyUsage, contextType, PR_TRUE );
2064 if (crv != CKR_OK) return crv;
2065 crv = sftk_GetContext(hSession,&context,contextType,PR_TRUE,NULL);
2067 /* this shouldn't happen! */
2068 PORT_Assert(crv == CKR_OK);
2069 if (crv != CKR_OK) return crv;
2070 context->blockSize = blockSize;
2071 context->macSize = mac_bytes;
2072 return CKR_OK;
2073 }
2075 /*
2076 * encode RSA PKCS #1 Signature data before signing...
2077 */
2078 static SECStatus
2079 sftk_RSAHashSign(SFTKHashSignInfo *info, unsigned char *sig,
2080 unsigned int *sigLen, unsigned int maxLen,
2081 const unsigned char *hash, unsigned int hashLen)
2082 {
2083 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2084 if (info->key->keyType != NSSLOWKEYRSAKey) {
2085 PORT_SetError(SEC_ERROR_INVALID_KEY);
2086 return SECFailure;
2087 }
2089 return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen,
2090 hash, hashLen);
2091 }
2093 /* XXX Old template; want to expunge it eventually. */
2094 static DERTemplate SECAlgorithmIDTemplate[] = {
2095 { DER_SEQUENCE,
2096 0, NULL, sizeof(SECAlgorithmID) },
2097 { DER_OBJECT_ID,
2098 offsetof(SECAlgorithmID,algorithm), },
2099 { DER_OPTIONAL | DER_ANY,
2100 offsetof(SECAlgorithmID,parameters), },
2101 { 0, }
2102 };
2104 /*
2105 * XXX OLD Template. Once all uses have been switched over to new one,
2106 * remove this.
2107 */
2108 static DERTemplate SGNDigestInfoTemplate[] = {
2109 { DER_SEQUENCE,
2110 0, NULL, sizeof(SGNDigestInfo) },
2111 { DER_INLINE,
2112 offsetof(SGNDigestInfo,digestAlgorithm),
2113 SECAlgorithmIDTemplate, },
2114 { DER_OCTET_STRING,
2115 offsetof(SGNDigestInfo,digest), },
2116 { 0, }
2117 };
2119 /*
2120 * encode RSA PKCS #1 Signature data before signing...
2121 */
2122 SECStatus
2123 RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
2124 unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
2125 const unsigned char *hash, unsigned int hashLen)
2126 {
2127 SECStatus rv = SECFailure;
2128 SECItem digder;
2129 PLArenaPool *arena = NULL;
2130 SGNDigestInfo *di = NULL;
2132 digder.data = NULL;
2134 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2135 if (!arena) {
2136 goto loser;
2137 }
2139 /* Construct digest info */
2140 di = SGN_CreateDigestInfo(hashOid, hash, hashLen);
2141 if (!di) {
2142 goto loser;
2143 }
2145 /* Der encode the digest as a DigestInfo */
2146 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
2147 if (rv != SECSuccess) {
2148 goto loser;
2149 }
2151 /*
2152 ** Encrypt signature after constructing appropriate PKCS#1 signature
2153 ** block
2154 */
2155 rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data,
2156 digder.len);
2157 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2158 sftk_fatalError = PR_TRUE;
2159 }
2161 loser:
2162 SGN_DestroyDigestInfo(di);
2163 if (arena != NULL) {
2164 PORT_FreeArena(arena, PR_FALSE);
2165 }
2166 return rv;
2167 }
2169 static SECStatus
2170 sftk_RSASign(NSSLOWKEYPrivateKey *key, unsigned char *output,
2171 unsigned int *outputLen, unsigned int maxOutputLen,
2172 const unsigned char *input, unsigned int inputLen)
2173 {
2174 SECStatus rv = SECFailure;
2176 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2177 if (key->keyType != NSSLOWKEYRSAKey) {
2178 PORT_SetError(SEC_ERROR_INVALID_KEY);
2179 return SECFailure;
2180 }
2182 rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input,
2183 inputLen);
2184 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2185 sftk_fatalError = PR_TRUE;
2186 }
2187 return rv;
2188 }
2190 static SECStatus
2191 sftk_RSASignRaw(NSSLOWKEYPrivateKey *key, unsigned char *output,
2192 unsigned int *outputLen, unsigned int maxOutputLen,
2193 const unsigned char *input, unsigned int inputLen)
2194 {
2195 SECStatus rv = SECFailure;
2197 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2198 if (key->keyType != NSSLOWKEYRSAKey) {
2199 PORT_SetError(SEC_ERROR_INVALID_KEY);
2200 return SECFailure;
2201 }
2203 rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input,
2204 inputLen);
2205 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2206 sftk_fatalError = PR_TRUE;
2207 }
2208 return rv;
2210 }
2212 static SECStatus
2213 sftk_RSASignPSS(SFTKHashSignInfo *info, unsigned char *sig,
2214 unsigned int *sigLen, unsigned int maxLen,
2215 const unsigned char *hash, unsigned int hashLen)
2216 {
2217 SECStatus rv = SECFailure;
2218 HASH_HashType hashAlg;
2219 HASH_HashType maskHashAlg;
2220 CK_RSA_PKCS_PSS_PARAMS *params = (CK_RSA_PKCS_PSS_PARAMS *)info->params;
2222 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2223 if (info->key->keyType != NSSLOWKEYRSAKey) {
2224 PORT_SetError(SEC_ERROR_INVALID_KEY);
2225 return SECFailure;
2226 }
2228 hashAlg = GetHashTypeFromMechanism(params->hashAlg);
2229 maskHashAlg = GetHashTypeFromMechanism(params->mgf);
2231 rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL,
2232 params->sLen, sig, sigLen, maxLen, hash, hashLen);
2233 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2234 sftk_fatalError = PR_TRUE;
2235 }
2236 return rv;
2237 }
2239 static SECStatus
2240 nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen,
2241 void *dataBuf, unsigned int dataLen)
2242 {
2243 SECItem signature, digest;
2244 NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
2246 signature.data = (unsigned char *)sigBuf;
2247 signature.len = sigLen;
2248 digest.data = (unsigned char *)dataBuf;
2249 digest.len = dataLen;
2250 return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest);
2251 }
2253 static SECStatus
2254 nsc_DSA_Sign_Stub(void *ctx, void *sigBuf,
2255 unsigned int *sigLen, unsigned int maxSigLen,
2256 void *dataBuf, unsigned int dataLen)
2257 {
2258 SECItem signature, digest;
2259 SECStatus rv;
2260 NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
2262 signature.data = (unsigned char *)sigBuf;
2263 signature.len = maxSigLen;
2264 digest.data = (unsigned char *)dataBuf;
2265 digest.len = dataLen;
2266 rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest);
2267 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2268 sftk_fatalError = PR_TRUE;
2269 }
2270 *sigLen = signature.len;
2271 return rv;
2272 }
2274 #ifndef NSS_DISABLE_ECC
2275 static SECStatus
2276 nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen,
2277 void *dataBuf, unsigned int dataLen)
2278 {
2279 SECItem signature, digest;
2280 NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
2282 signature.data = (unsigned char *)sigBuf;
2283 signature.len = sigLen;
2284 digest.data = (unsigned char *)dataBuf;
2285 digest.len = dataLen;
2286 return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest);
2287 }
2289 static SECStatus
2290 nsc_ECDSASignStub(void *ctx, void *sigBuf,
2291 unsigned int *sigLen, unsigned int maxSigLen,
2292 void *dataBuf, unsigned int dataLen)
2293 {
2294 SECItem signature, digest;
2295 SECStatus rv;
2296 NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
2298 signature.data = (unsigned char *)sigBuf;
2299 signature.len = maxSigLen;
2300 digest.data = (unsigned char *)dataBuf;
2301 digest.len = dataLen;
2302 rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest);
2303 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2304 sftk_fatalError = PR_TRUE;
2305 }
2306 *sigLen = signature.len;
2307 return rv;
2308 }
2309 #endif /* NSS_DISABLE_ECC */
2311 /* NSC_SignInit setups up the signing operations. There are three basic
2312 * types of signing:
2313 * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
2314 * to data in a single Sign operation (which often looks a lot like an
2315 * encrypt, with data coming in and data going out).
2316 * (2) Hash based signing, where we continually hash the data, then apply
2317 * some sort of signature to the end.
2318 * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key,
2319 * and only the final block is part of the mac.
2320 *
2321 * For case number 3, we initialize a context much like the Encryption Context
2322 * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and
2323 * C_Final by the following method... if it's not multi-part, and it's doesn't
2324 * have a hash context, it must be a block Encryption CBC MAC.
2325 *
2326 * For case number 2, we initialize a hash structure, as well as make it
2327 * multi-part. Updates are simple calls to the hash update function. Final
2328 * calls the hashend, then passes the result to the 'update' function (which
2329 * operates as a final signature function). In some hash based MAC'ing (as
2330 * opposed to hash base signatures), the update function is can be simply a
2331 * copy (as is the case with HMAC).
2332 */
2333 CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession,
2334 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2335 {
2336 SFTKSession *session;
2337 SFTKObject *key;
2338 SFTKSessionContext *context;
2339 CK_KEY_TYPE key_type;
2340 CK_RV crv = CKR_OK;
2341 NSSLOWKEYPrivateKey *privKey;
2342 SFTKHashSignInfo *info = NULL;
2344 CHECK_FORK();
2346 /* Block Cipher MACing Algorithms use a different Context init method..*/
2347 crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN);
2348 if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv;
2350 /* we're not using a block cipher mac */
2351 session = sftk_SessionFromHandle(hSession);
2352 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2353 crv = sftk_InitGeneric(session,&context,SFTK_SIGN,&key,hKey,&key_type,
2354 CKO_PRIVATE_KEY,CKA_SIGN);
2355 if (crv != CKR_OK) {
2356 sftk_FreeSession(session);
2357 return crv;
2358 }
2360 context->multi = PR_FALSE;
2362 #define INIT_RSA_SIGN_MECH(mmm) \
2363 case CKM_ ## mmm ## _RSA_PKCS: \
2364 context->multi = PR_TRUE; \
2365 crv = sftk_doSub ## mmm (context); \
2366 if (crv != CKR_OK) break; \
2367 context->update = (SFTKCipher) sftk_RSAHashSign; \
2368 info = PORT_New(SFTKHashSignInfo); \
2369 if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \
2370 info->hashOid = SEC_OID_ ## mmm ; \
2371 goto finish_rsa;
2373 switch(pMechanism->mechanism) {
2374 INIT_RSA_SIGN_MECH(MD5)
2375 INIT_RSA_SIGN_MECH(MD2)
2376 INIT_RSA_SIGN_MECH(SHA1)
2377 INIT_RSA_SIGN_MECH(SHA224)
2378 INIT_RSA_SIGN_MECH(SHA256)
2379 INIT_RSA_SIGN_MECH(SHA384)
2380 INIT_RSA_SIGN_MECH(SHA512)
2382 case CKM_RSA_PKCS:
2383 context->update = (SFTKCipher) sftk_RSASign;
2384 goto finish_rsa;
2385 case CKM_RSA_X_509:
2386 context->update = (SFTKCipher) sftk_RSASignRaw;
2387 finish_rsa:
2388 if (key_type != CKK_RSA) {
2389 crv = CKR_KEY_TYPE_INCONSISTENT;
2390 break;
2391 }
2392 context->rsa = PR_TRUE;
2393 privKey = sftk_GetPrivKey(key,CKK_RSA,&crv);
2394 if (privKey == NULL) {
2395 crv = CKR_KEY_TYPE_INCONSISTENT;
2396 break;
2397 }
2398 /* OK, info is allocated only if we're doing hash and sign mechanism.
2399 * It's necessary to be able to set the correct OID in the final
2400 * signature.
2401 */
2402 if (info) {
2403 info->key = privKey;
2404 context->cipherInfo = info;
2405 context->destroy = (SFTKDestroy)sftk_Space;
2406 } else {
2407 context->cipherInfo = privKey;
2408 context->destroy = (SFTKDestroy)sftk_Null;
2409 }
2410 context->maxLen = nsslowkey_PrivateModulusLen(privKey);
2411 break;
2412 case CKM_RSA_PKCS_PSS:
2413 if (key_type != CKK_RSA) {
2414 crv = CKR_KEY_TYPE_INCONSISTENT;
2415 break;
2416 }
2417 context->rsa = PR_TRUE;
2418 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
2419 !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)) {
2420 crv = CKR_MECHANISM_PARAM_INVALID;
2421 break;
2422 }
2423 info = PORT_New(SFTKHashSignInfo);
2424 if (info == NULL) {
2425 crv = CKR_HOST_MEMORY;
2426 break;
2427 }
2428 info->params = pMechanism->pParameter;
2429 info->key = sftk_GetPrivKey(key,CKK_RSA,&crv);
2430 if (info->key == NULL) {
2431 PORT_Free(info);
2432 break;
2433 }
2434 context->cipherInfo = info;
2435 context->destroy = (SFTKDestroy) sftk_Space;
2436 context->update = (SFTKCipher) sftk_RSASignPSS;
2437 context->maxLen = nsslowkey_PrivateModulusLen(info->key);
2438 break;
2440 case CKM_DSA_SHA1:
2441 context->multi = PR_TRUE;
2442 crv = sftk_doSubSHA1(context);
2443 if (crv != CKR_OK) break;
2444 /* fall through */
2445 case CKM_DSA:
2446 if (key_type != CKK_DSA) {
2447 crv = CKR_KEY_TYPE_INCONSISTENT;
2448 break;
2449 }
2450 privKey = sftk_GetPrivKey(key,CKK_DSA,&crv);
2451 if (privKey == NULL) {
2452 break;
2453 }
2454 context->cipherInfo = privKey;
2455 context->update = (SFTKCipher) nsc_DSA_Sign_Stub;
2456 context->destroy = (privKey == key->objectInfo) ?
2457 (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey;
2458 context->maxLen = DSA_MAX_SIGNATURE_LEN;
2460 break;
2462 #ifndef NSS_DISABLE_ECC
2463 case CKM_ECDSA_SHA1:
2464 context->multi = PR_TRUE;
2465 crv = sftk_doSubSHA1(context);
2466 if (crv != CKR_OK) break;
2467 /* fall through */
2468 case CKM_ECDSA:
2469 if (key_type != CKK_EC) {
2470 crv = CKR_KEY_TYPE_INCONSISTENT;
2471 break;
2472 }
2473 privKey = sftk_GetPrivKey(key,CKK_EC,&crv);
2474 if (privKey == NULL) {
2475 crv = CKR_HOST_MEMORY;
2476 break;
2477 }
2478 context->cipherInfo = privKey;
2479 context->update = (SFTKCipher) nsc_ECDSASignStub;
2480 context->destroy = (privKey == key->objectInfo) ?
2481 (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey;
2482 context->maxLen = MAX_ECKEY_LEN * 2;
2484 break;
2485 #endif /* NSS_DISABLE_ECC */
2487 #define INIT_HMAC_MECH(mmm) \
2488 case CKM_ ## mmm ## _HMAC_GENERAL: \
2489 crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, \
2490 *(CK_ULONG *)pMechanism->pParameter); \
2491 break; \
2492 case CKM_ ## mmm ## _HMAC: \
2493 crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, mmm ## _LENGTH); \
2494 break;
2496 INIT_HMAC_MECH(MD2)
2497 INIT_HMAC_MECH(MD5)
2498 INIT_HMAC_MECH(SHA224)
2499 INIT_HMAC_MECH(SHA256)
2500 INIT_HMAC_MECH(SHA384)
2501 INIT_HMAC_MECH(SHA512)
2503 case CKM_SHA_1_HMAC_GENERAL:
2504 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,
2505 *(CK_ULONG *)pMechanism->pParameter);
2506 break;
2507 case CKM_SHA_1_HMAC:
2508 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH);
2509 break;
2511 case CKM_SSL3_MD5_MAC:
2512 crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key,
2513 *(CK_ULONG *)pMechanism->pParameter);
2514 break;
2515 case CKM_SSL3_SHA1_MAC:
2516 crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key,
2517 *(CK_ULONG *)pMechanism->pParameter);
2518 break;
2519 case CKM_TLS_PRF_GENERAL:
2520 crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL);
2521 break;
2522 case CKM_NSS_TLS_PRF_GENERAL_SHA256:
2523 crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256);
2524 break;
2526 case CKM_NSS_HMAC_CONSTANT_TIME: {
2527 sftk_MACConstantTimeCtx *ctx =
2528 sftk_HMACConstantTime_New(pMechanism,key);
2529 CK_ULONG *intpointer;
2531 if (ctx == NULL) {
2532 crv = CKR_ARGUMENTS_BAD;
2533 break;
2534 }
2535 intpointer = PORT_New(CK_ULONG);
2536 if (intpointer == NULL) {
2537 crv = CKR_HOST_MEMORY;
2538 break;
2539 }
2540 *intpointer = ctx->hash->length;
2542 context->cipherInfo = intpointer;
2543 context->hashInfo = ctx;
2544 context->currentMech = pMechanism->mechanism;
2545 context->hashUpdate = sftk_HMACConstantTime_Update;
2546 context->hashdestroy = sftk_MACConstantTime_DestroyContext;
2547 context->end = sftk_MACConstantTime_EndHash;
2548 context->update = (SFTKCipher) sftk_SignCopy;
2549 context->destroy = sftk_Space;
2550 context->maxLen = 64;
2551 context->multi = PR_TRUE;
2552 break;
2553 }
2555 case CKM_NSS_SSL3_MAC_CONSTANT_TIME: {
2556 sftk_MACConstantTimeCtx *ctx =
2557 sftk_SSLv3MACConstantTime_New(pMechanism,key);
2558 CK_ULONG *intpointer;
2560 if (ctx == NULL) {
2561 crv = CKR_ARGUMENTS_BAD;
2562 break;
2563 }
2564 intpointer = PORT_New(CK_ULONG);
2565 if (intpointer == NULL) {
2566 crv = CKR_HOST_MEMORY;
2567 break;
2568 }
2569 *intpointer = ctx->hash->length;
2571 context->cipherInfo = intpointer;
2572 context->hashInfo = ctx;
2573 context->currentMech = pMechanism->mechanism;
2574 context->hashUpdate = sftk_SSLv3MACConstantTime_Update;
2575 context->hashdestroy = sftk_MACConstantTime_DestroyContext;
2576 context->end = sftk_MACConstantTime_EndHash;
2577 context->update = (SFTKCipher) sftk_SignCopy;
2578 context->destroy = sftk_Space;
2579 context->maxLen = 64;
2580 context->multi = PR_TRUE;
2581 break;
2582 }
2584 default:
2585 crv = CKR_MECHANISM_INVALID;
2586 break;
2587 }
2589 if (crv != CKR_OK) {
2590 if (info) PORT_Free(info);
2591 sftk_FreeContext(context);
2592 sftk_FreeSession(session);
2593 return crv;
2594 }
2595 sftk_SetContextByType(session, SFTK_SIGN, context);
2596 sftk_FreeSession(session);
2597 return CKR_OK;
2598 }
2600 /** MAC one block of data by block cipher
2601 */
2602 static CK_RV
2603 sftk_MACBlock( SFTKSessionContext *ctx, void *blk )
2604 {
2605 unsigned int outlen;
2606 return ( SECSuccess == (ctx->update)( ctx->cipherInfo, ctx->macBuf, &outlen,
2607 SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize ))
2608 ? CKR_OK : sftk_MapCryptError(PORT_GetError());
2609 }
2611 /** MAC last (incomplete) block of data by block cipher
2612 *
2613 * Call once, then terminate MACing operation.
2614 */
2615 static CK_RV
2616 sftk_MACFinal( SFTKSessionContext *ctx )
2617 {
2618 unsigned int padLen = ctx->padDataLength;
2619 /* pad and proceed the residual */
2620 if( padLen ) {
2621 /* shd clr ctx->padLen to make sftk_MACFinal idempotent */
2622 PORT_Memset( ctx->padBuf + padLen, 0, ctx->blockSize - padLen );
2623 return sftk_MACBlock( ctx, ctx->padBuf );
2624 } else
2625 return CKR_OK;
2626 }
2628 /** The common implementation for {Sign,Verify}Update. (S/V only vary in their
2629 * setup and final operations).
2630 *
2631 * A call which results in an error terminates the operation [PKCS#11,v2.11]
2632 */
2633 static CK_RV
2634 sftk_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
2635 CK_ULONG ulPartLen,SFTKContextType type)
2636 {
2637 SFTKSession *session;
2638 SFTKSessionContext *context;
2639 CK_RV crv;
2641 /* make sure we're legal */
2642 crv = sftk_GetContext(hSession,&context,type, PR_TRUE, &session );
2643 if (crv != CKR_OK) return crv;
2645 if (context->hashInfo) {
2646 (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen);
2647 } else {
2648 /* must be block cipher MACing */
2650 unsigned int blkSize = context->blockSize;
2651 unsigned char *residual = /* free room in context->padBuf */
2652 context->padBuf + context->padDataLength;
2653 unsigned int minInput = /* min input for MACing at least one block */
2654 blkSize - context->padDataLength;
2656 /* not enough data even for one block */
2657 if( ulPartLen < minInput ) {
2658 PORT_Memcpy( residual, pPart, ulPartLen );
2659 context->padDataLength += ulPartLen;
2660 goto cleanup;
2661 }
2662 /* MACing residual */
2663 if( context->padDataLength ) {
2664 PORT_Memcpy( residual, pPart, minInput );
2665 ulPartLen -= minInput;
2666 pPart += minInput;
2667 if( CKR_OK != (crv = sftk_MACBlock( context, context->padBuf )) )
2668 goto terminate;
2669 }
2670 /* MACing full blocks */
2671 while( ulPartLen >= blkSize )
2672 {
2673 if( CKR_OK != (crv = sftk_MACBlock( context, pPart )) )
2674 goto terminate;
2675 ulPartLen -= blkSize;
2676 pPart += blkSize;
2677 }
2678 /* save the residual */
2679 if( (context->padDataLength = ulPartLen) )
2680 PORT_Memcpy( context->padBuf, pPart, ulPartLen );
2681 } /* blk cipher MACing */
2683 goto cleanup;
2685 terminate:
2686 sftk_TerminateOp( session, type, context );
2687 cleanup:
2688 sftk_FreeSession(session);
2689 return crv;
2690 }
2692 /* NSC_SignUpdate continues a multiple-part signature operation,
2693 * where the signature is (will be) an appendix to the data,
2694 * and plaintext cannot be recovered from the signature
2695 *
2696 * A call which results in an error terminates the operation [PKCS#11,v2.11]
2697 */
2698 CK_RV NSC_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
2699 CK_ULONG ulPartLen)
2700 {
2701 CHECK_FORK();
2702 return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN);
2703 }
2706 /* NSC_SignFinal finishes a multiple-part signature operation,
2707 * returning the signature. */
2708 CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,
2709 CK_ULONG_PTR pulSignatureLen)
2710 {
2711 SFTKSession *session;
2712 SFTKSessionContext *context;
2713 unsigned int outlen;
2714 unsigned int maxoutlen = *pulSignatureLen;
2715 CK_RV crv;
2717 CHECK_FORK();
2719 /* make sure we're legal */
2720 crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_TRUE,&session);
2721 if (crv != CKR_OK) return crv;
2723 if (context->hashInfo) {
2724 unsigned int digestLen;
2725 unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
2727 if( !pSignature ) {
2728 outlen = context->maxLen; goto finish;
2729 }
2730 (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
2731 if( SECSuccess != (context->update)(context->cipherInfo, pSignature,
2732 &outlen, maxoutlen, tmpbuf, digestLen))
2733 crv = sftk_MapCryptError(PORT_GetError());
2734 /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate.
2735 * Keeping "too small" CK_RV intact is a standard violation, but allows
2736 * application read EXACT signature length */
2737 } else {
2738 /* must be block cipher MACing */
2739 outlen = context->macSize;
2740 /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/
2741 if( !pSignature || maxoutlen < outlen ) {
2742 if( pSignature ) crv = CKR_BUFFER_TOO_SMALL;
2743 goto finish;
2744 }
2745 if( CKR_OK == (crv = sftk_MACFinal( context )) )
2746 PORT_Memcpy(pSignature, context->macBuf, outlen );
2747 }
2749 sftk_TerminateOp( session, SFTK_SIGN, context );
2750 finish:
2751 *pulSignatureLen = outlen;
2752 sftk_FreeSession(session);
2753 return crv;
2754 }
2756 /* NSC_Sign signs (encrypts with private key) data in a single part,
2757 * where the signature is (will be) an appendix to the data,
2758 * and plaintext cannot be recovered from the signature */
2759 CK_RV NSC_Sign(CK_SESSION_HANDLE hSession,
2760 CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,
2761 CK_ULONG_PTR pulSignatureLen)
2762 {
2763 SFTKSession *session;
2764 SFTKSessionContext *context;
2765 CK_RV crv;
2767 CHECK_FORK();
2769 /* make sure we're legal */
2770 crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_FALSE,&session);
2771 if (crv != CKR_OK) return crv;
2773 if (!pSignature) {
2774 /* see also how C_SignUpdate implements this */
2775 *pulSignatureLen = (!context->multi || context->hashInfo)
2776 ? context->maxLen
2777 : context->macSize; /* must be block cipher MACing */
2778 goto finish;
2779 }
2781 /* multi part Signing are completely implemented by SignUpdate and
2782 * sign Final */
2783 if (context->multi) {
2784 /* SignFinal can't follow failed SignUpdate */
2785 if( CKR_OK == (crv = NSC_SignUpdate(hSession,pData,ulDataLen) ))
2786 crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen);
2787 } else {
2788 /* single-part PKC signature (e.g. CKM_ECDSA) */
2789 unsigned int outlen;
2790 unsigned int maxoutlen = *pulSignatureLen;
2791 if( SECSuccess != (*context->update)(context->cipherInfo, pSignature,
2792 &outlen, maxoutlen, pData, ulDataLen))
2793 crv = sftk_MapCryptError(PORT_GetError());
2794 *pulSignatureLen = (CK_ULONG) outlen;
2795 /* "too small" here is certainly continuable */
2796 if( crv != CKR_BUFFER_TOO_SMALL )
2797 sftk_TerminateOp(session, SFTK_SIGN, context);
2798 } /* single-part */
2800 finish:
2801 sftk_FreeSession(session);
2802 return crv;
2803 }
2806 /*
2807 ************** Crypto Functions: Sign Recover ************************
2808 */
2809 /* NSC_SignRecoverInit initializes a signature operation,
2810 * where the (digest) data can be recovered from the signature.
2811 * E.g. encryption with the user's private key */
2812 CK_RV NSC_SignRecoverInit(CK_SESSION_HANDLE hSession,
2813 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
2814 {
2815 CHECK_FORK();
2817 switch (pMechanism->mechanism) {
2818 case CKM_RSA_PKCS:
2819 case CKM_RSA_X_509:
2820 return NSC_SignInit(hSession,pMechanism,hKey);
2821 default:
2822 break;
2823 }
2824 return CKR_MECHANISM_INVALID;
2825 }
2828 /* NSC_SignRecover signs data in a single operation
2829 * where the (digest) data can be recovered from the signature.
2830 * E.g. encryption with the user's private key */
2831 CK_RV NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
2832 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
2833 {
2834 CHECK_FORK();
2836 return NSC_Sign(hSession,pData,ulDataLen,pSignature,pulSignatureLen);
2837 }
2839 /*
2840 ************** Crypto Functions: verify ************************
2841 */
2843 /* Handle RSA Signature formatting */
2844 static SECStatus
2845 sftk_hashCheckSign(SFTKHashVerifyInfo *info, const unsigned char *sig,
2846 unsigned int sigLen, const unsigned char *digest,
2847 unsigned int digestLen)
2848 {
2849 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2850 if (info->key->keyType != NSSLOWKEYRSAKey) {
2851 PORT_SetError(SEC_ERROR_INVALID_KEY);
2852 return SECFailure;
2853 }
2855 return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest,
2856 digestLen);
2857 }
2859 SECStatus
2860 RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key,
2861 const unsigned char *sig, unsigned int sigLen,
2862 const unsigned char *digestData, unsigned int digestLen)
2863 {
2864 unsigned char *pkcs1DigestInfoData;
2865 SECItem pkcs1DigestInfo;
2866 SECItem digest;
2867 unsigned int bufferSize;
2868 SECStatus rv;
2870 /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */
2871 bufferSize = key->u.rsa.modulus.len;
2872 pkcs1DigestInfoData = PORT_ZAlloc(bufferSize);
2873 if (!pkcs1DigestInfoData) {
2874 PORT_SetError(SEC_ERROR_NO_MEMORY);
2875 return SECFailure;
2876 }
2878 pkcs1DigestInfo.data = pkcs1DigestInfoData;
2879 pkcs1DigestInfo.len = bufferSize;
2881 /* decrypt the block */
2882 rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data,
2883 &pkcs1DigestInfo.len, pkcs1DigestInfo.len,
2884 sig, sigLen);
2885 if (rv != SECSuccess) {
2886 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
2887 } else {
2888 digest.data = (PRUint8*) digestData;
2889 digest.len = digestLen;
2890 rv = _SGN_VerifyPKCS1DigestInfo(
2891 digestOid, &digest, &pkcs1DigestInfo,
2892 PR_TRUE /*XXX: unsafeAllowMissingParameters*/);
2893 }
2895 PORT_Free(pkcs1DigestInfoData);
2896 return rv;
2897 }
2899 static SECStatus
2900 sftk_RSACheckSign(NSSLOWKEYPublicKey *key, const unsigned char *sig,
2901 unsigned int sigLen, const unsigned char *digest,
2902 unsigned int digestLen)
2903 {
2904 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2905 if (key->keyType != NSSLOWKEYRSAKey) {
2906 PORT_SetError(SEC_ERROR_INVALID_KEY);
2907 return SECFailure;
2908 }
2910 return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen);
2911 }
2913 static SECStatus
2914 sftk_RSACheckSignRaw(NSSLOWKEYPublicKey *key, const unsigned char *sig,
2915 unsigned int sigLen, const unsigned char *digest,
2916 unsigned int digestLen)
2917 {
2918 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2919 if (key->keyType != NSSLOWKEYRSAKey) {
2920 PORT_SetError(SEC_ERROR_INVALID_KEY);
2921 return SECFailure;
2922 }
2924 return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen);
2925 }
2927 static SECStatus
2928 sftk_RSACheckSignPSS(SFTKHashVerifyInfo *info, const unsigned char *sig,
2929 unsigned int sigLen, const unsigned char *digest,
2930 unsigned int digestLen)
2931 {
2932 HASH_HashType hashAlg;
2933 HASH_HashType maskHashAlg;
2934 CK_RSA_PKCS_PSS_PARAMS *params = (CK_RSA_PKCS_PSS_PARAMS *)info->params;
2936 PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2937 if (info->key->keyType != NSSLOWKEYRSAKey) {
2938 PORT_SetError(SEC_ERROR_INVALID_KEY);
2939 return SECFailure;
2940 }
2942 hashAlg = GetHashTypeFromMechanism(params->hashAlg);
2943 maskHashAlg = GetHashTypeFromMechanism(params->mgf);
2945 return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg,
2946 params->sLen, sig, sigLen, digest, digestLen);
2947 }
2949 /* NSC_VerifyInit initializes a verification operation,
2950 * where the signature is an appendix to the data,
2951 * and plaintext cannot be recovered from the signature (e.g. DSA) */
2952 CK_RV NSC_VerifyInit(CK_SESSION_HANDLE hSession,
2953 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
2954 {
2955 SFTKSession *session;
2956 SFTKObject *key;
2957 SFTKSessionContext *context;
2958 CK_KEY_TYPE key_type;
2959 CK_RV crv = CKR_OK;
2960 NSSLOWKEYPublicKey *pubKey;
2961 SFTKHashVerifyInfo *info = NULL;
2963 CHECK_FORK();
2965 /* Block Cipher MACing Algorithms use a different Context init method..*/
2966 crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY);
2967 if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv;
2969 session = sftk_SessionFromHandle(hSession);
2970 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2971 crv = sftk_InitGeneric(session,&context,SFTK_VERIFY,&key,hKey,&key_type,
2972 CKO_PUBLIC_KEY,CKA_VERIFY);
2973 if (crv != CKR_OK) {
2974 sftk_FreeSession(session);
2975 return crv;
2976 }
2978 context->multi = PR_FALSE;
2980 #define INIT_RSA_VFY_MECH(mmm) \
2981 case CKM_ ## mmm ## _RSA_PKCS: \
2982 context->multi = PR_TRUE; \
2983 crv = sftk_doSub ## mmm (context); \
2984 if (crv != CKR_OK) break; \
2985 context->verify = (SFTKVerify) sftk_hashCheckSign; \
2986 info = PORT_New(SFTKHashVerifyInfo); \
2987 if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \
2988 info->hashOid = SEC_OID_ ## mmm ; \
2989 goto finish_rsa;
2991 switch(pMechanism->mechanism) {
2992 INIT_RSA_VFY_MECH(MD5)
2993 INIT_RSA_VFY_MECH(MD2)
2994 INIT_RSA_VFY_MECH(SHA1)
2995 INIT_RSA_VFY_MECH(SHA224)
2996 INIT_RSA_VFY_MECH(SHA256)
2997 INIT_RSA_VFY_MECH(SHA384)
2998 INIT_RSA_VFY_MECH(SHA512)
3000 case CKM_RSA_PKCS:
3001 context->verify = (SFTKVerify) sftk_RSACheckSign;
3002 goto finish_rsa;
3003 case CKM_RSA_X_509:
3004 context->verify = (SFTKVerify) sftk_RSACheckSignRaw;
3005 finish_rsa:
3006 if (key_type != CKK_RSA) {
3007 if (info) PORT_Free(info);
3008 crv = CKR_KEY_TYPE_INCONSISTENT;
3009 break;
3010 }
3011 context->rsa = PR_TRUE;
3012 pubKey = sftk_GetPubKey(key,CKK_RSA,&crv);
3013 if (pubKey == NULL) {
3014 if (info) PORT_Free(info);
3015 crv = CKR_KEY_TYPE_INCONSISTENT;
3016 break;
3017 }
3018 if (info) {
3019 info->key = pubKey;
3020 context->cipherInfo = info;
3021 context->destroy = sftk_Space;
3022 } else {
3023 context->cipherInfo = pubKey;
3024 context->destroy = sftk_Null;
3025 }
3026 break;
3027 case CKM_RSA_PKCS_PSS:
3028 if (key_type != CKK_RSA) {
3029 crv = CKR_KEY_TYPE_INCONSISTENT;
3030 break;
3031 }
3032 context->rsa = PR_TRUE;
3033 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
3034 !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)) {
3035 crv = CKR_MECHANISM_PARAM_INVALID;
3036 break;
3037 }
3038 info = PORT_New(SFTKHashVerifyInfo);
3039 if (info == NULL) {
3040 crv = CKR_HOST_MEMORY;
3041 break;
3042 }
3043 info->params = pMechanism->pParameter;
3044 info->key = sftk_GetPubKey(key,CKK_RSA,&crv);
3045 if (info->key == NULL) {
3046 PORT_Free(info);
3047 break;
3048 }
3049 context->cipherInfo = info;
3050 context->destroy = (SFTKDestroy) sftk_Space;
3051 context->verify = (SFTKVerify) sftk_RSACheckSignPSS;
3052 break;
3053 case CKM_DSA_SHA1:
3054 context->multi = PR_TRUE;
3055 crv = sftk_doSubSHA1(context);
3056 if (crv != CKR_OK) break;
3057 /* fall through */
3058 case CKM_DSA:
3059 if (key_type != CKK_DSA) {
3060 crv = CKR_KEY_TYPE_INCONSISTENT;
3061 break;
3062 }
3063 pubKey = sftk_GetPubKey(key,CKK_DSA,&crv);
3064 if (pubKey == NULL) {
3065 break;
3066 }
3067 context->cipherInfo = pubKey;
3068 context->verify = (SFTKVerify) nsc_DSA_Verify_Stub;
3069 context->destroy = sftk_Null;
3070 break;
3071 #ifndef NSS_DISABLE_ECC
3072 case CKM_ECDSA_SHA1:
3073 context->multi = PR_TRUE;
3074 crv = sftk_doSubSHA1(context);
3075 if (crv != CKR_OK) break;
3076 /* fall through */
3077 case CKM_ECDSA:
3078 if (key_type != CKK_EC) {
3079 crv = CKR_KEY_TYPE_INCONSISTENT;
3080 break;
3081 }
3082 pubKey = sftk_GetPubKey(key,CKK_EC,&crv);
3083 if (pubKey == NULL) {
3084 crv = CKR_HOST_MEMORY;
3085 break;
3086 }
3087 context->cipherInfo = pubKey;
3088 context->verify = (SFTKVerify) nsc_ECDSAVerifyStub;
3089 context->destroy = sftk_Null;
3090 break;
3091 #endif /* NSS_DISABLE_ECC */
3093 INIT_HMAC_MECH(MD2)
3094 INIT_HMAC_MECH(MD5)
3095 INIT_HMAC_MECH(SHA224)
3096 INIT_HMAC_MECH(SHA256)
3097 INIT_HMAC_MECH(SHA384)
3098 INIT_HMAC_MECH(SHA512)
3100 case CKM_SHA_1_HMAC_GENERAL:
3101 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,
3102 *(CK_ULONG *)pMechanism->pParameter);
3103 break;
3104 case CKM_SHA_1_HMAC:
3105 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH);
3106 break;
3108 case CKM_SSL3_MD5_MAC:
3109 crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key,
3110 *(CK_ULONG *)pMechanism->pParameter);
3111 break;
3112 case CKM_SSL3_SHA1_MAC:
3113 crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key,
3114 *(CK_ULONG *)pMechanism->pParameter);
3115 break;
3116 case CKM_TLS_PRF_GENERAL:
3117 crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL);
3118 break;
3119 case CKM_NSS_TLS_PRF_GENERAL_SHA256:
3120 crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256);
3121 break;
3123 default:
3124 crv = CKR_MECHANISM_INVALID;
3125 break;
3126 }
3128 if (crv != CKR_OK) {
3129 if (info) PORT_Free(info);
3130 sftk_FreeContext(context);
3131 sftk_FreeSession(session);
3132 return crv;
3133 }
3134 sftk_SetContextByType(session, SFTK_VERIFY, context);
3135 sftk_FreeSession(session);
3136 return CKR_OK;
3137 }
3139 /* NSC_Verify verifies a signature in a single-part operation,
3140 * where the signature is an appendix to the data,
3141 * and plaintext cannot be recovered from the signature */
3142 CK_RV NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
3143 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
3144 {
3145 SFTKSession *session;
3146 SFTKSessionContext *context;
3147 CK_RV crv;
3149 CHECK_FORK();
3151 /* make sure we're legal */
3152 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_FALSE,&session);
3153 if (crv != CKR_OK) return crv;
3155 /* multi part Verifying are completely implemented by VerifyUpdate and
3156 * VerifyFinal */
3157 if (context->multi) {
3158 /* VerifyFinal can't follow failed VerifyUpdate */
3159 if( CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen)))
3160 crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen);
3161 } else {
3162 if (SECSuccess != (*context->verify)(context->cipherInfo,pSignature,
3163 ulSignatureLen, pData, ulDataLen))
3164 crv = sftk_MapCryptError(PORT_GetError());
3166 sftk_TerminateOp( session, SFTK_VERIFY, context );
3167 }
3168 sftk_FreeSession(session);
3169 return crv;
3170 }
3173 /* NSC_VerifyUpdate continues a multiple-part verification operation,
3174 * where the signature is an appendix to the data,
3175 * and plaintext cannot be recovered from the signature
3176 *
3177 * A call which results in an error terminates the operation [PKCS#11,v2.11]
3178 */
3179 CK_RV NSC_VerifyUpdate( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3180 CK_ULONG ulPartLen)
3181 {
3182 CHECK_FORK();
3183 return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY);
3184 }
3187 /* NSC_VerifyFinal finishes a multiple-part verification operation,
3188 * checking the signature. */
3189 CK_RV NSC_VerifyFinal(CK_SESSION_HANDLE hSession,
3190 CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)
3191 {
3192 SFTKSession *session;
3193 SFTKSessionContext *context;
3194 CK_RV crv;
3196 CHECK_FORK();
3198 if (!pSignature)
3199 return CKR_ARGUMENTS_BAD;
3201 /* make sure we're legal */
3202 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_TRUE,&session);
3203 if (crv != CKR_OK)
3204 return crv;
3206 if (context->hashInfo) {
3207 unsigned int digestLen;
3208 unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
3210 (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
3211 if( SECSuccess != (context->verify)(context->cipherInfo, pSignature,
3212 ulSignatureLen, tmpbuf, digestLen))
3213 crv = sftk_MapCryptError(PORT_GetError());
3214 } else if (ulSignatureLen != context->macSize) {
3215 /* must be block cipher MACing */
3216 crv = CKR_SIGNATURE_LEN_RANGE;
3217 } else if (CKR_OK == (crv = sftk_MACFinal(context))) {
3218 if (PORT_Memcmp(pSignature, context->macBuf, ulSignatureLen))
3219 crv = CKR_SIGNATURE_INVALID;
3220 }
3222 sftk_TerminateOp( session, SFTK_VERIFY, context );
3223 sftk_FreeSession(session);
3224 return crv;
3226 }
3228 /*
3229 ************** Crypto Functions: Verify Recover ************************
3230 */
3231 static SECStatus
3232 sftk_RSACheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char *data,
3233 unsigned int *dataLen, unsigned int maxDataLen,
3234 const unsigned char *sig, unsigned int sigLen)
3235 {
3236 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3237 if (key->keyType != NSSLOWKEYRSAKey) {
3238 PORT_SetError(SEC_ERROR_INVALID_KEY);
3239 return SECFailure;
3240 }
3242 return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen,
3243 sig, sigLen);
3244 }
3246 static SECStatus
3247 sftk_RSACheckSignRecoverRaw(NSSLOWKEYPublicKey *key, unsigned char *data,
3248 unsigned int *dataLen, unsigned int maxDataLen,
3249 const unsigned char *sig, unsigned int sigLen)
3250 {
3251 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3252 if (key->keyType != NSSLOWKEYRSAKey) {
3253 PORT_SetError(SEC_ERROR_INVALID_KEY);
3254 return SECFailure;
3255 }
3257 return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen,
3258 sig, sigLen);
3259 }
3261 /* NSC_VerifyRecoverInit initializes a signature verification operation,
3262 * where the data is recovered from the signature.
3263 * E.g. Decryption with the user's public key */
3264 CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
3265 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
3266 {
3267 SFTKSession *session;
3268 SFTKObject *key;
3269 SFTKSessionContext *context;
3270 CK_KEY_TYPE key_type;
3271 CK_RV crv = CKR_OK;
3272 NSSLOWKEYPublicKey *pubKey;
3274 CHECK_FORK();
3276 session = sftk_SessionFromHandle(hSession);
3277 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3278 crv = sftk_InitGeneric(session,&context,SFTK_VERIFY_RECOVER,
3279 &key,hKey,&key_type,CKO_PUBLIC_KEY,CKA_VERIFY_RECOVER);
3280 if (crv != CKR_OK) {
3281 sftk_FreeSession(session);
3282 return crv;
3283 }
3285 context->multi = PR_TRUE;
3287 switch(pMechanism->mechanism) {
3288 case CKM_RSA_PKCS:
3289 case CKM_RSA_X_509:
3290 if (key_type != CKK_RSA) {
3291 crv = CKR_KEY_TYPE_INCONSISTENT;
3292 break;
3293 }
3294 context->multi = PR_FALSE;
3295 context->rsa = PR_TRUE;
3296 pubKey = sftk_GetPubKey(key,CKK_RSA,&crv);
3297 if (pubKey == NULL) {
3298 break;
3299 }
3300 context->cipherInfo = pubKey;
3301 context->update = (SFTKCipher) (pMechanism->mechanism == CKM_RSA_X_509
3302 ? sftk_RSACheckSignRecoverRaw : sftk_RSACheckSignRecover);
3303 context->destroy = sftk_Null;
3304 break;
3305 default:
3306 crv = CKR_MECHANISM_INVALID;
3307 break;
3308 }
3310 if (crv != CKR_OK) {
3311 PORT_Free(context);
3312 sftk_FreeSession(session);
3313 return crv;
3314 }
3315 sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context);
3316 sftk_FreeSession(session);
3317 return CKR_OK;
3318 }
3321 /* NSC_VerifyRecover verifies a signature in a single-part operation,
3322 * where the data is recovered from the signature.
3323 * E.g. Decryption with the user's public key */
3324 CK_RV NSC_VerifyRecover(CK_SESSION_HANDLE hSession,
3325 CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,
3326 CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)
3327 {
3328 SFTKSession *session;
3329 SFTKSessionContext *context;
3330 unsigned int outlen;
3331 unsigned int maxoutlen = *pulDataLen;
3332 CK_RV crv;
3333 SECStatus rv;
3335 CHECK_FORK();
3337 /* make sure we're legal */
3338 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY_RECOVER,
3339 PR_FALSE,&session);
3340 if (crv != CKR_OK) return crv;
3341 if (pData == NULL) {
3342 /* to return the actual size, we need to do the decrypt, just return
3343 * the max size, which is the size of the input signature. */
3344 *pulDataLen = ulSignatureLen;
3345 rv = SECSuccess;
3346 goto finish;
3347 }
3349 rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
3350 pSignature, ulSignatureLen);
3351 *pulDataLen = (CK_ULONG) outlen;
3353 sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context);
3354 finish:
3355 sftk_FreeSession(session);
3356 return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError());
3357 }
3359 /*
3360 **************************** Random Functions: ************************
3361 */
3363 /* NSC_SeedRandom mixes additional seed material into the token's random number
3364 * generator. */
3365 CK_RV NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
3366 CK_ULONG ulSeedLen)
3367 {
3368 SECStatus rv;
3370 CHECK_FORK();
3372 rv = RNG_RandomUpdate(pSeed, ulSeedLen);
3373 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
3374 }
3376 /* NSC_GenerateRandom generates random data. */
3377 CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
3378 CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
3379 {
3380 SECStatus rv;
3382 CHECK_FORK();
3384 rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen);
3385 /*
3386 * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't
3387 * seeded with enough entropy.
3388 */
3389 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
3390 }
3392 /*
3393 **************************** Key Functions: ************************
3394 */
3397 /*
3398 * generate a password based encryption key. This code uses
3399 * PKCS5 to do the work.
3400 */
3401 static CK_RV
3402 nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
3403 void *buf, CK_ULONG *key_length, PRBool faulty3DES)
3404 {
3405 SECItem *pbe_key = NULL, iv, pwitem;
3406 CK_PBE_PARAMS *pbe_params = NULL;
3407 CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
3409 *key_length = 0;
3410 iv.data = NULL; iv.len = 0;
3412 if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
3413 pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
3414 pwitem.data = (unsigned char *)pbkd2_params->pPassword;
3415 /* was this a typo in the PKCS #11 spec? */
3416 pwitem.len = *pbkd2_params->ulPasswordLen;
3417 } else {
3418 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
3419 pwitem.data = (unsigned char *)pbe_params->pPassword;
3420 pwitem.len = pbe_params->ulPasswordLen;
3421 }
3422 pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES);
3423 if (pbe_key == NULL) {
3424 return CKR_HOST_MEMORY;
3425 }
3427 PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
3428 *key_length = pbe_key->len;
3429 SECITEM_ZfreeItem(pbe_key, PR_TRUE);
3430 pbe_key = NULL;
3432 if (iv.data) {
3433 if (pbe_params && pbe_params->pInitVector != NULL) {
3434 PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len);
3435 }
3436 PORT_Free(iv.data);
3437 }
3439 return CKR_OK;
3440 }
3442 /*
3443 * this is coded for "full" support. These selections will be limitted to
3444 * the official subset by freebl.
3445 */
3446 static unsigned int
3447 sftk_GetSubPrimeFromPrime(unsigned int primeBits)
3448 {
3449 if (primeBits <= 1024) {
3450 return 160;
3451 } else if (primeBits <= 2048) {
3452 return 224;
3453 } else if (primeBits <= 3072) {
3454 return 256;
3455 } else if (primeBits <= 7680) {
3456 return 384;
3457 } else {
3458 return 512;
3459 }
3460 }
3462 static CK_RV
3463 nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
3464 {
3465 SFTKAttribute *attribute;
3466 CK_ULONG counter;
3467 unsigned int seedBits = 0;
3468 unsigned int subprimeBits = 0;
3469 unsigned int primeBits;
3470 unsigned int j = 8; /* default to 1024 bits */
3471 CK_RV crv = CKR_OK;
3472 PQGParams *params = NULL;
3473 PQGVerify *vfy = NULL;
3474 SECStatus rv;
3476 attribute = sftk_FindAttribute(key, CKA_PRIME_BITS);
3477 if (attribute == NULL) {
3478 return CKR_TEMPLATE_INCOMPLETE;
3479 }
3480 primeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
3481 sftk_FreeAttribute(attribute);
3482 if (primeBits < 1024) {
3483 j = PQG_PBITS_TO_INDEX(primeBits);
3484 if (j == (unsigned int)-1) {
3485 return CKR_ATTRIBUTE_VALUE_INVALID;
3486 }
3487 }
3489 attribute = sftk_FindAttribute(key, CKA_NETSCAPE_PQG_SEED_BITS);
3490 if (attribute != NULL) {
3491 seedBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
3492 sftk_FreeAttribute(attribute);
3493 }
3495 attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS);
3496 if (attribute != NULL) {
3497 subprimeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
3498 sftk_FreeAttribute(attribute);
3499 }
3501 sftk_DeleteAttributeType(key,CKA_PRIME_BITS);
3502 sftk_DeleteAttributeType(key,CKA_SUBPRIME_BITS);
3503 sftk_DeleteAttributeType(key,CKA_NETSCAPE_PQG_SEED_BITS);
3505 /* use the old PQG interface if we have old input data */
3506 if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) {
3507 if (seedBits == 0) {
3508 rv = PQG_ParamGen(j, ¶ms, &vfy);
3509 } else {
3510 rv = PQG_ParamGenSeedLen(j,seedBits/8, ¶ms, &vfy);
3511 }
3512 } else {
3513 if (subprimeBits == 0) {
3514 subprimeBits = sftk_GetSubPrimeFromPrime(primeBits);
3515 }
3516 if (seedBits == 0) {
3517 seedBits = primeBits;
3518 }
3519 rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits/8, ¶ms, &vfy);
3520 }
3524 if (rv != SECSuccess) {
3525 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
3526 sftk_fatalError = PR_TRUE;
3527 }
3528 return sftk_MapCryptError(PORT_GetError());
3529 }
3530 crv = sftk_AddAttributeType(key,CKA_PRIME,
3531 params->prime.data, params->prime.len);
3532 if (crv != CKR_OK) goto loser;
3533 crv = sftk_AddAttributeType(key,CKA_SUBPRIME,
3534 params->subPrime.data, params->subPrime.len);
3535 if (crv != CKR_OK) goto loser;
3536 crv = sftk_AddAttributeType(key,CKA_BASE,
3537 params->base.data, params->base.len);
3538 if (crv != CKR_OK) goto loser;
3539 counter = vfy->counter;
3540 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_COUNTER,
3541 &counter, sizeof(counter));
3542 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_SEED,
3543 vfy->seed.data, vfy->seed.len);
3544 if (crv != CKR_OK) goto loser;
3545 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_H,
3546 vfy->h.data, vfy->h.len);
3547 if (crv != CKR_OK) goto loser;
3549 loser:
3550 PQG_DestroyParams(params);
3552 if (vfy) {
3553 PQG_DestroyVerify(vfy);
3554 }
3555 return crv;
3556 }
3559 static CK_RV
3560 nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
3561 CK_ULONG *key_length)
3562 {
3563 CK_RV crv = CKR_OK;
3565 switch (mechanism) {
3566 case CKM_RC2_KEY_GEN:
3567 *key_type = CKK_RC2;
3568 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3569 break;
3570 #if NSS_SOFTOKEN_DOES_RC5
3571 case CKM_RC5_KEY_GEN:
3572 *key_type = CKK_RC5;
3573 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3574 break;
3575 #endif
3576 case CKM_RC4_KEY_GEN:
3577 *key_type = CKK_RC4;
3578 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3579 break;
3580 case CKM_GENERIC_SECRET_KEY_GEN:
3581 *key_type = CKK_GENERIC_SECRET;
3582 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3583 break;
3584 case CKM_CDMF_KEY_GEN:
3585 *key_type = CKK_CDMF;
3586 *key_length = 8;
3587 break;
3588 case CKM_DES_KEY_GEN:
3589 *key_type = CKK_DES;
3590 *key_length = 8;
3591 break;
3592 case CKM_DES2_KEY_GEN:
3593 *key_type = CKK_DES2;
3594 *key_length = 16;
3595 break;
3596 case CKM_DES3_KEY_GEN:
3597 *key_type = CKK_DES3;
3598 *key_length = 24;
3599 break;
3600 case CKM_SEED_KEY_GEN:
3601 *key_type = CKK_SEED;
3602 *key_length = 16;
3603 break;
3604 case CKM_CAMELLIA_KEY_GEN:
3605 *key_type = CKK_CAMELLIA;
3606 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3607 break;
3608 case CKM_AES_KEY_GEN:
3609 *key_type = CKK_AES;
3610 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3611 break;
3612 default:
3613 PORT_Assert(0);
3614 crv = CKR_MECHANISM_INVALID;
3615 break;
3616 }
3618 return crv;
3619 }
3621 CK_RV
3622 nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
3623 {
3624 SECItem salt;
3625 CK_PBE_PARAMS *pbe_params = NULL;
3626 NSSPKCS5PBEParameter *params;
3627 PLArenaPool *arena = NULL;
3628 SECStatus rv;
3630 *pbe = NULL;
3632 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
3633 if (arena == NULL) {
3634 return CKR_HOST_MEMORY;
3635 }
3637 params = (NSSPKCS5PBEParameter *) PORT_ArenaZAlloc(arena,
3638 sizeof(NSSPKCS5PBEParameter));
3639 if (params == NULL) {
3640 PORT_FreeArena(arena,PR_TRUE);
3641 return CKR_HOST_MEMORY;
3642 }
3644 params->poolp = arena;
3645 params->ivLen = 0;
3646 params->pbeType = NSSPKCS5_PKCS12_V2;
3647 params->hashType = HASH_AlgSHA1;
3648 params->encAlg = SEC_OID_SHA1; /* any invalid value */
3649 params->is2KeyDES = PR_FALSE;
3650 params->keyID = pbeBitGenIntegrityKey;
3651 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
3652 params->iter = pbe_params->ulIteration;
3654 salt.data = (unsigned char *)pbe_params->pSalt;
3655 salt.len = (unsigned int)pbe_params->ulSaltLen;
3656 rv = SECITEM_CopyItem(arena,¶ms->salt,&salt);
3657 if (rv != SECSuccess) {
3658 PORT_FreeArena(arena,PR_TRUE);
3659 return CKR_HOST_MEMORY;
3660 }
3661 switch (pMechanism->mechanism) {
3662 case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
3663 case CKM_PBA_SHA1_WITH_SHA1_HMAC:
3664 params->hashType = HASH_AlgSHA1;
3665 params->keyLen = 20;
3666 break;
3667 case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
3668 params->hashType = HASH_AlgMD5;
3669 params->keyLen = 16;
3670 break;
3671 case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
3672 params->hashType = HASH_AlgMD2;
3673 params->keyLen = 16;
3674 break;
3675 default:
3676 PORT_FreeArena(arena,PR_TRUE);
3677 return CKR_MECHANISM_INVALID;
3678 }
3679 *pbe = params;
3680 return CKR_OK;
3681 }
3683 /* maybe this should be table driven? */
3684 static CK_RV
3685 nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
3686 CK_KEY_TYPE *key_type, CK_ULONG *key_length)
3687 {
3688 CK_RV crv = CKR_OK;
3689 SECOidData *oid;
3690 CK_PBE_PARAMS *pbe_params = NULL;
3691 NSSPKCS5PBEParameter *params = NULL;
3692 CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
3693 SECItem salt;
3694 CK_ULONG iteration = 0;
3696 *pbe = NULL;
3698 oid = SECOID_FindOIDByMechanism(pMechanism->mechanism);
3699 if (oid == NULL) {
3700 return CKR_MECHANISM_INVALID;
3701 }
3703 if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
3704 pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
3705 if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) {
3706 return CKR_MECHANISM_PARAM_INVALID;
3707 }
3708 salt.data = (unsigned char *)pbkd2_params->pSaltSourceData;
3709 salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen;
3710 iteration = pbkd2_params->iterations;
3711 } else {
3712 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
3713 salt.data = (unsigned char *)pbe_params->pSalt;
3714 salt.len = (unsigned int)pbe_params->ulSaltLen;
3715 iteration = pbe_params->ulIteration;
3716 }
3717 params=nsspkcs5_NewParam(oid->offset, &salt, iteration);
3718 if (params == NULL) {
3719 return CKR_MECHANISM_INVALID;
3720 }
3722 switch (params->encAlg) {
3723 case SEC_OID_DES_CBC:
3724 *key_type = CKK_DES;
3725 *key_length = params->keyLen;
3726 break;
3727 case SEC_OID_DES_EDE3_CBC:
3728 *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3;
3729 *key_length = params->keyLen;
3730 break;
3731 case SEC_OID_RC2_CBC:
3732 *key_type = CKK_RC2;
3733 *key_length = params->keyLen;
3734 break;
3735 case SEC_OID_RC4:
3736 *key_type = CKK_RC4;
3737 *key_length = params->keyLen;
3738 break;
3739 case SEC_OID_PKCS5_PBKDF2:
3740 /* sigh, PKCS #11 currently only defines SHA1 for the KDF hash type.
3741 * we do the check here because this where we would handle multiple
3742 * hash types in the future */
3743 if (pbkd2_params == NULL ||
3744 pbkd2_params->prf != CKP_PKCS5_PBKD2_HMAC_SHA1) {
3745 crv = CKR_MECHANISM_PARAM_INVALID;
3746 break;
3747 }
3748 /* key type must already be set */
3749 if (*key_type == CKK_INVALID_KEY_TYPE) {
3750 crv = CKR_TEMPLATE_INCOMPLETE;
3751 break;
3752 }
3753 /* PBKDF2 needs to calculate the key length from the other parameters
3754 */
3755 if (*key_length == 0) {
3756 *key_length = sftk_MapKeySize(*key_type);
3757 }
3758 if (*key_length == 0) {
3759 crv = CKR_TEMPLATE_INCOMPLETE;
3760 break;
3761 }
3762 params->keyLen = *key_length;
3763 break;
3764 default:
3765 crv = CKR_MECHANISM_INVALID;
3766 nsspkcs5_DestroyPBEParameter(params);
3767 break;
3768 }
3769 if (crv == CKR_OK) {
3770 *pbe = params;
3771 }
3772 return crv;
3773 }
3775 /* NSC_GenerateKey generates a secret key, creating a new key object. */
3776 CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
3777 CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,
3778 CK_OBJECT_HANDLE_PTR phKey)
3779 {
3780 SFTKObject *key;
3781 SFTKSession *session;
3782 PRBool checkWeak = PR_FALSE;
3783 CK_ULONG key_length = 0;
3784 CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE;
3785 CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
3786 CK_RV crv = CKR_OK;
3787 CK_BBOOL cktrue = CK_TRUE;
3788 int i;
3789 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
3790 unsigned char buf[MAX_KEY_LEN];
3791 enum {nsc_pbe, nsc_ssl, nsc_bulk, nsc_param, nsc_jpake} key_gen_type;
3792 NSSPKCS5PBEParameter *pbe_param;
3793 SSL3RSAPreMasterSecret *rsa_pms;
3794 CK_VERSION *version;
3795 /* in very old versions of NSS, there were implementation errors with key
3796 * generation methods. We want to beable to read these, but not
3797 * produce them any more. The affected algorithm was 3DES.
3798 */
3799 PRBool faultyPBE3DES = PR_FALSE;
3800 HASH_HashType hashType;
3802 CHECK_FORK();
3804 if (!slot) {
3805 return CKR_SESSION_HANDLE_INVALID;
3806 }
3807 /*
3808 * now lets create an object to hang the attributes off of
3809 */
3810 key = sftk_NewObject(slot); /* fill in the handle later */
3811 if (key == NULL) {
3812 return CKR_HOST_MEMORY;
3813 }
3815 /*
3816 * load the template values into the object
3817 */
3818 for (i=0; i < (int) ulCount; i++) {
3819 if (pTemplate[i].type == CKA_VALUE_LEN) {
3820 key_length = *(CK_ULONG *)pTemplate[i].pValue;
3821 continue;
3822 }
3823 /* some algorithms need keytype specified */
3824 if (pTemplate[i].type == CKA_KEY_TYPE) {
3825 key_type = *(CK_ULONG *)pTemplate[i].pValue;
3826 continue;
3827 }
3829 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i]));
3830 if (crv != CKR_OK) break;
3831 }
3832 if (crv != CKR_OK) {
3833 sftk_FreeObject(key);
3834 return crv;
3835 }
3837 /* make sure we don't have any class, key_type, or value fields */
3838 sftk_DeleteAttributeType(key,CKA_CLASS);
3839 sftk_DeleteAttributeType(key,CKA_KEY_TYPE);
3840 sftk_DeleteAttributeType(key,CKA_VALUE);
3842 /* Now Set up the parameters to generate the key (based on mechanism) */
3843 key_gen_type = nsc_bulk; /* bulk key by default */
3844 switch (pMechanism->mechanism) {
3845 case CKM_CDMF_KEY_GEN:
3846 case CKM_DES_KEY_GEN:
3847 case CKM_DES2_KEY_GEN:
3848 case CKM_DES3_KEY_GEN:
3849 checkWeak = PR_TRUE;
3850 /* fall through */
3851 case CKM_RC2_KEY_GEN:
3852 case CKM_RC4_KEY_GEN:
3853 case CKM_GENERIC_SECRET_KEY_GEN:
3854 case CKM_SEED_KEY_GEN:
3855 case CKM_CAMELLIA_KEY_GEN:
3856 case CKM_AES_KEY_GEN:
3857 #if NSS_SOFTOKEN_DOES_RC5
3858 case CKM_RC5_KEY_GEN:
3859 #endif
3860 crv = nsc_SetupBulkKeyGen(pMechanism->mechanism,&key_type,&key_length);
3861 break;
3862 case CKM_SSL3_PRE_MASTER_KEY_GEN:
3863 key_type = CKK_GENERIC_SECRET;
3864 key_length = 48;
3865 key_gen_type = nsc_ssl;
3866 break;
3867 case CKM_PBA_SHA1_WITH_SHA1_HMAC:
3868 case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
3869 case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
3870 case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
3871 key_gen_type = nsc_pbe;
3872 key_type = CKK_GENERIC_SECRET;
3873 crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param);
3874 break;
3875 case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
3876 faultyPBE3DES = PR_TRUE;
3877 /* fall through */
3878 case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:
3879 case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
3880 case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
3881 case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC:
3882 case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4:
3883 case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4:
3884 case CKM_PBE_SHA1_DES3_EDE_CBC:
3885 case CKM_PBE_SHA1_DES2_EDE_CBC:
3886 case CKM_PBE_SHA1_RC2_128_CBC:
3887 case CKM_PBE_SHA1_RC2_40_CBC:
3888 case CKM_PBE_SHA1_RC4_128:
3889 case CKM_PBE_SHA1_RC4_40:
3890 case CKM_PBE_MD5_DES_CBC:
3891 case CKM_PBE_MD2_DES_CBC:
3892 case CKM_PKCS5_PBKD2:
3893 key_gen_type = nsc_pbe;
3894 crv = nsc_SetupPBEKeyGen(pMechanism,&pbe_param, &key_type, &key_length);
3895 break;
3896 case CKM_DSA_PARAMETER_GEN:
3897 key_gen_type = nsc_param;
3898 key_type = CKK_DSA;
3899 objclass = CKO_KG_PARAMETERS;
3900 crv = CKR_OK;
3901 break;
3902 case CKM_NSS_JPAKE_ROUND1_SHA1: hashType = HASH_AlgSHA1; goto jpake1;
3903 case CKM_NSS_JPAKE_ROUND1_SHA256: hashType = HASH_AlgSHA256; goto jpake1;
3904 case CKM_NSS_JPAKE_ROUND1_SHA384: hashType = HASH_AlgSHA384; goto jpake1;
3905 case CKM_NSS_JPAKE_ROUND1_SHA512: hashType = HASH_AlgSHA512; goto jpake1;
3906 jpake1:
3907 key_gen_type = nsc_jpake;
3908 key_type = CKK_NSS_JPAKE_ROUND1;
3909 objclass = CKO_PRIVATE_KEY;
3910 if (pMechanism->pParameter == NULL ||
3911 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) {
3912 crv = CKR_MECHANISM_PARAM_INVALID;
3913 break;
3914 }
3915 if (sftk_isTrue(key, CKA_TOKEN)) {
3916 crv = CKR_TEMPLATE_INCONSISTENT;
3917 break;
3918 }
3919 crv = CKR_OK;
3920 break;
3921 default:
3922 crv = CKR_MECHANISM_INVALID;
3923 break;
3924 }
3926 /* make sure we aren't going to overflow the buffer */
3927 if (sizeof(buf) < key_length) {
3928 /* someone is getting pretty optimistic about how big their key can
3929 * be... */
3930 crv = CKR_TEMPLATE_INCONSISTENT;
3931 }
3933 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3935 /* if there was no error,
3936 * key_type *MUST* be set in the switch statement above */
3937 PORT_Assert( key_type != CKK_INVALID_KEY_TYPE );
3939 /*
3940 * now to the actual key gen.
3941 */
3942 switch (key_gen_type) {
3943 case nsc_pbe:
3944 crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length,
3945 faultyPBE3DES);
3946 nsspkcs5_DestroyPBEParameter(pbe_param);
3947 break;
3948 case nsc_ssl:
3949 rsa_pms = (SSL3RSAPreMasterSecret *)buf;
3950 version = (CK_VERSION *)pMechanism->pParameter;
3951 rsa_pms->client_version[0] = version->major;
3952 rsa_pms->client_version[1] = version->minor;
3953 crv =
3954 NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random));
3955 break;
3956 case nsc_bulk:
3957 /* get the key, check for weak keys and repeat if found */
3958 do {
3959 crv = NSC_GenerateRandom(0, buf, key_length);
3960 } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf,key_type));
3961 break;
3962 case nsc_param:
3963 /* generate parameters */
3964 *buf = 0;
3965 crv = nsc_parameter_gen(key_type,key);
3966 break;
3967 case nsc_jpake:
3968 crv = jpake_Round1(hashType,
3969 (CK_NSS_JPAKERound1Params *) pMechanism->pParameter,
3970 key);
3971 break;
3972 }
3974 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3976 /* Add the class, key_type, and value */
3977 crv = sftk_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS));
3978 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3979 crv = sftk_AddAttributeType(key,CKA_KEY_TYPE,&key_type,sizeof(CK_KEY_TYPE));
3980 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3981 if (key_length != 0) {
3982 crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length);
3983 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3984 }
3986 /* get the session */
3987 session = sftk_SessionFromHandle(hSession);
3988 if (session == NULL) {
3989 sftk_FreeObject(key);
3990 return CKR_SESSION_HANDLE_INVALID;
3991 }
3993 /*
3994 * handle the base object stuff
3995 */
3996 crv = sftk_handleObject(key,session);
3997 sftk_FreeSession(session);
3998 if (sftk_isTrue(key,CKA_SENSITIVE)) {
3999 sftk_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL));
4000 }
4001 if (!sftk_isTrue(key,CKA_EXTRACTABLE)) {
4002 sftk_forceAttribute(key,CKA_NEVER_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL));
4003 }
4005 *phKey = key->handle;
4006 sftk_FreeObject(key);
4007 return crv;
4008 }
4010 #define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */
4011 #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */
4013 /*
4014 * FIPS 140-2 pairwise consistency check utilized to validate key pair.
4015 *
4016 * This function returns
4017 * CKR_OK if pairwise consistency check passed
4018 * CKR_GENERAL_ERROR if pairwise consistency check failed
4019 * other error codes if paiswise consistency check could not be
4020 * performed, for example, CKR_HOST_MEMORY.
4021 */
4022 static CK_RV
4023 sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
4024 SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType)
4025 {
4026 /*
4027 * Key type Mechanism type
4028 * --------------------------------
4029 * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS
4030 * others => CKM_INVALID_MECHANISM
4031 *
4032 * For sign/verify: CKK_RSA => CKM_RSA_PKCS
4033 * CKK_DSA => CKM_DSA
4034 * CKK_EC => CKM_ECDSA
4035 * others => CKM_INVALID_MECHANISM
4036 *
4037 * None of these mechanisms has a parameter.
4038 */
4039 CK_MECHANISM mech = {0, NULL, 0};
4041 CK_ULONG modulusLen;
4042 CK_ULONG subPrimeLen;
4043 PRBool isEncryptable = PR_FALSE;
4044 PRBool canSignVerify = PR_FALSE;
4045 PRBool isDerivable = PR_FALSE;
4046 CK_RV crv;
4048 /* Variables used for Encrypt/Decrypt functions. */
4049 unsigned char *known_message = (unsigned char *)"Known Crypto Message";
4050 unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH];
4051 CK_ULONG bytes_decrypted;
4052 unsigned char *ciphertext;
4053 unsigned char *text_compared;
4054 CK_ULONG bytes_encrypted;
4055 CK_ULONG bytes_compared;
4056 CK_ULONG pairwise_digest_length = PAIRWISE_DIGEST_LENGTH;
4058 /* Variables used for Signature/Verification functions. */
4059 /* Must be at least 256 bits for DSA2 digest */
4060 unsigned char *known_digest = (unsigned char *)
4061 "Mozilla Rules the World through NSS!";
4062 unsigned char *signature;
4063 CK_ULONG signature_length;
4065 if (keyType == CKK_RSA) {
4066 SFTKAttribute *attribute;
4068 /* Get modulus length of private key. */
4069 attribute = sftk_FindAttribute(privateKey, CKA_MODULUS);
4070 if (attribute == NULL) {
4071 return CKR_DEVICE_ERROR;
4072 }
4073 modulusLen = attribute->attrib.ulValueLen;
4074 if (*(unsigned char *)attribute->attrib.pValue == 0) {
4075 modulusLen--;
4076 }
4077 sftk_FreeAttribute(attribute);
4078 } else if (keyType == CKK_DSA) {
4079 SFTKAttribute *attribute;
4081 /* Get subprime length of private key. */
4082 attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME);
4083 if (attribute == NULL) {
4084 return CKR_DEVICE_ERROR;
4085 }
4086 subPrimeLen = attribute->attrib.ulValueLen;
4087 if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) {
4088 subPrimeLen--;
4089 }
4090 sftk_FreeAttribute(attribute);
4091 }
4093 /**************************************************/
4094 /* Pairwise Consistency Check of Encrypt/Decrypt. */
4095 /**************************************************/
4097 isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT);
4099 /*
4100 * If the decryption attribute is set, attempt to encrypt
4101 * with the public key and decrypt with the private key.
4102 */
4103 if (isEncryptable) {
4104 if (keyType != CKK_RSA) {
4105 return CKR_DEVICE_ERROR;
4106 }
4107 bytes_encrypted = modulusLen;
4108 mech.mechanism = CKM_RSA_PKCS;
4110 /* Allocate space for ciphertext. */
4111 ciphertext = (unsigned char *) PORT_ZAlloc(bytes_encrypted);
4112 if (ciphertext == NULL) {
4113 return CKR_HOST_MEMORY;
4114 }
4116 /* Prepare for encryption using the public key. */
4117 crv = NSC_EncryptInit(hSession, &mech, publicKey->handle);
4118 if (crv != CKR_OK) {
4119 PORT_Free(ciphertext);
4120 return crv;
4121 }
4123 /* Encrypt using the public key. */
4124 crv = NSC_Encrypt(hSession,
4125 known_message,
4126 PAIRWISE_MESSAGE_LENGTH,
4127 ciphertext,
4128 &bytes_encrypted);
4129 if (crv != CKR_OK) {
4130 PORT_Free(ciphertext);
4131 return crv;
4132 }
4134 /* Always use the smaller of these two values . . . */
4135 bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH);
4137 /*
4138 * If there was a failure, the plaintext
4139 * goes at the end, therefore . . .
4140 */
4141 text_compared = ciphertext + bytes_encrypted - bytes_compared;
4143 /*
4144 * Check to ensure that ciphertext does
4145 * NOT EQUAL known input message text
4146 * per FIPS PUB 140-2 directive.
4147 */
4148 if (PORT_Memcmp(text_compared, known_message,
4149 bytes_compared) == 0) {
4150 /* Set error to Invalid PRIVATE Key. */
4151 PORT_SetError(SEC_ERROR_INVALID_KEY);
4152 PORT_Free(ciphertext);
4153 return CKR_GENERAL_ERROR;
4154 }
4156 /* Prepare for decryption using the private key. */
4157 crv = NSC_DecryptInit(hSession, &mech, privateKey->handle);
4158 if (crv != CKR_OK) {
4159 PORT_Free(ciphertext);
4160 return crv;
4161 }
4163 memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH);
4165 /*
4166 * Initialize bytes decrypted to be the
4167 * expected PAIRWISE_MESSAGE_LENGTH.
4168 */
4169 bytes_decrypted = PAIRWISE_MESSAGE_LENGTH;
4171 /*
4172 * Decrypt using the private key.
4173 * NOTE: No need to reset the
4174 * value of bytes_encrypted.
4175 */
4176 crv = NSC_Decrypt(hSession,
4177 ciphertext,
4178 bytes_encrypted,
4179 plaintext,
4180 &bytes_decrypted);
4182 /* Finished with ciphertext; free it. */
4183 PORT_Free(ciphertext);
4185 if (crv != CKR_OK) {
4186 return crv;
4187 }
4189 /*
4190 * Check to ensure that the output plaintext
4191 * does EQUAL known input message text.
4192 */
4193 if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) ||
4194 (PORT_Memcmp(plaintext, known_message,
4195 PAIRWISE_MESSAGE_LENGTH) != 0)) {
4196 /* Set error to Bad PUBLIC Key. */
4197 PORT_SetError(SEC_ERROR_BAD_KEY);
4198 return CKR_GENERAL_ERROR;
4199 }
4200 }
4202 /**********************************************/
4203 /* Pairwise Consistency Check of Sign/Verify. */
4204 /**********************************************/
4206 canSignVerify = sftk_isTrue(privateKey, CKA_SIGN);
4208 if (canSignVerify) {
4209 /* Determine length of signature. */
4210 switch (keyType) {
4211 case CKK_RSA:
4212 signature_length = modulusLen;
4213 mech.mechanism = CKM_RSA_PKCS;
4214 break;
4215 case CKK_DSA:
4216 signature_length = DSA_MAX_SIGNATURE_LEN;
4217 pairwise_digest_length = subPrimeLen;
4218 mech.mechanism = CKM_DSA;
4219 break;
4220 #ifndef NSS_DISABLE_ECC
4221 case CKK_EC:
4222 signature_length = MAX_ECKEY_LEN * 2;
4223 mech.mechanism = CKM_ECDSA;
4224 break;
4225 #endif
4226 default:
4227 return CKR_DEVICE_ERROR;
4228 }
4230 /* Allocate space for signature data. */
4231 signature = (unsigned char *) PORT_ZAlloc(signature_length);
4232 if (signature == NULL) {
4233 return CKR_HOST_MEMORY;
4234 }
4236 /* Sign the known hash using the private key. */
4237 crv = NSC_SignInit(hSession, &mech, privateKey->handle);
4238 if (crv != CKR_OK) {
4239 PORT_Free(signature);
4240 return crv;
4241 }
4243 crv = NSC_Sign(hSession,
4244 known_digest,
4245 pairwise_digest_length,
4246 signature,
4247 &signature_length);
4248 if (crv != CKR_OK) {
4249 PORT_Free(signature);
4250 return crv;
4251 }
4253 /* Verify the known hash using the public key. */
4254 crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
4255 if (crv != CKR_OK) {
4256 PORT_Free(signature);
4257 return crv;
4258 }
4260 crv = NSC_Verify(hSession,
4261 known_digest,
4262 pairwise_digest_length,
4263 signature,
4264 signature_length);
4266 /* Free signature data. */
4267 PORT_Free(signature);
4269 if ((crv == CKR_SIGNATURE_LEN_RANGE) ||
4270 (crv == CKR_SIGNATURE_INVALID)) {
4271 return CKR_GENERAL_ERROR;
4272 }
4273 if (crv != CKR_OK) {
4274 return crv;
4275 }
4276 }
4278 /**********************************************/
4279 /* Pairwise Consistency Check for Derivation */
4280 /**********************************************/
4282 isDerivable = sftk_isTrue(privateKey, CKA_DERIVE);
4284 if (isDerivable) {
4285 /*
4286 * We are not doing consistency check for Diffie-Hellman Key -
4287 * otherwise it would be here
4288 * This is also true for Elliptic Curve Diffie-Hellman keys
4289 * NOTE: EC keys are currently subjected to pairwise
4290 * consistency check for signing/verification.
4291 */
4292 /*
4293 * FIPS 140-2 had the following pairwise consistency test for
4294 * public and private keys used for key agreement:
4295 * If the keys are used to perform key agreement, then the
4296 * cryptographic module shall create a second, compatible
4297 * key pair. The cryptographic module shall perform both
4298 * sides of the key agreement algorithm and shall compare
4299 * the resulting shared values. If the shared values are
4300 * not equal, the test shall fail.
4301 * This test was removed in Change Notice 3.
4302 */
4304 }
4306 return CKR_OK;
4307 }
4309 /* NSC_GenerateKeyPair generates a public-key/private-key pair,
4310 * creating new key objects. */
4311 CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession,
4312 CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
4313 CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
4314 CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
4315 CK_OBJECT_HANDLE_PTR phPrivateKey)
4316 {
4317 SFTKObject * publicKey,*privateKey;
4318 SFTKSession * session;
4319 CK_KEY_TYPE key_type;
4320 CK_RV crv = CKR_OK;
4321 CK_BBOOL cktrue = CK_TRUE;
4322 SECStatus rv;
4323 CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
4324 CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
4325 int i;
4326 SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession);
4327 unsigned int bitSize;
4329 /* RSA */
4330 int public_modulus_bits = 0;
4331 SECItem pubExp;
4332 RSAPrivateKey * rsaPriv;
4334 /* DSA */
4335 PQGParams pqgParam;
4336 DHParams dhParam;
4337 DSAPrivateKey * dsaPriv;
4339 /* Diffie Hellman */
4340 int private_value_bits = 0;
4341 DHPrivateKey * dhPriv;
4343 #ifndef NSS_DISABLE_ECC
4344 /* Elliptic Curve Cryptography */
4345 SECItem ecEncodedParams; /* DER Encoded parameters */
4346 ECPrivateKey * ecPriv;
4347 ECParams * ecParams;
4348 #endif /* NSS_DISABLE_ECC */
4350 CHECK_FORK();
4352 if (!slot) {
4353 return CKR_SESSION_HANDLE_INVALID;
4354 }
4355 /*
4356 * now lets create an object to hang the attributes off of
4357 */
4358 publicKey = sftk_NewObject(slot); /* fill in the handle later */
4359 if (publicKey == NULL) {
4360 return CKR_HOST_MEMORY;
4361 }
4363 /*
4364 * load the template values into the publicKey
4365 */
4366 for (i=0; i < (int) ulPublicKeyAttributeCount; i++) {
4367 if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {
4368 public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
4369 continue;
4370 }
4372 crv = sftk_AddAttributeType(publicKey,
4373 sftk_attr_expand(&pPublicKeyTemplate[i]));
4374 if (crv != CKR_OK) break;
4375 }
4377 if (crv != CKR_OK) {
4378 sftk_FreeObject(publicKey);
4379 return CKR_HOST_MEMORY;
4380 }
4382 privateKey = sftk_NewObject(slot); /* fill in the handle later */
4383 if (privateKey == NULL) {
4384 sftk_FreeObject(publicKey);
4385 return CKR_HOST_MEMORY;
4386 }
4387 /*
4388 * now load the private key template
4389 */
4390 for (i=0; i < (int) ulPrivateKeyAttributeCount; i++) {
4391 if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {
4392 private_value_bits = *(CK_ULONG *)pPrivateKeyTemplate[i].pValue;
4393 continue;
4394 }
4396 crv = sftk_AddAttributeType(privateKey,
4397 sftk_attr_expand(&pPrivateKeyTemplate[i]));
4398 if (crv != CKR_OK) break;
4399 }
4401 if (crv != CKR_OK) {
4402 sftk_FreeObject(publicKey);
4403 sftk_FreeObject(privateKey);
4404 return CKR_HOST_MEMORY;
4405 }
4406 sftk_DeleteAttributeType(privateKey,CKA_CLASS);
4407 sftk_DeleteAttributeType(privateKey,CKA_KEY_TYPE);
4408 sftk_DeleteAttributeType(privateKey,CKA_VALUE);
4409 sftk_DeleteAttributeType(publicKey,CKA_CLASS);
4410 sftk_DeleteAttributeType(publicKey,CKA_KEY_TYPE);
4411 sftk_DeleteAttributeType(publicKey,CKA_VALUE);
4413 /* Now Set up the parameters to generate the key (based on mechanism) */
4414 switch (pMechanism->mechanism) {
4415 case CKM_RSA_PKCS_KEY_PAIR_GEN:
4416 /* format the keys */
4417 sftk_DeleteAttributeType(publicKey,CKA_MODULUS);
4418 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
4419 sftk_DeleteAttributeType(privateKey,CKA_MODULUS);
4420 sftk_DeleteAttributeType(privateKey,CKA_PRIVATE_EXPONENT);
4421 sftk_DeleteAttributeType(privateKey,CKA_PUBLIC_EXPONENT);
4422 sftk_DeleteAttributeType(privateKey,CKA_PRIME_1);
4423 sftk_DeleteAttributeType(privateKey,CKA_PRIME_2);
4424 sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_1);
4425 sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_2);
4426 sftk_DeleteAttributeType(privateKey,CKA_COEFFICIENT);
4427 key_type = CKK_RSA;
4428 if (public_modulus_bits == 0) {
4429 crv = CKR_TEMPLATE_INCOMPLETE;
4430 break;
4431 }
4432 if (public_modulus_bits < RSA_MIN_MODULUS_BITS) {
4433 crv = CKR_ATTRIBUTE_VALUE_INVALID;
4434 break;
4435 }
4436 if (public_modulus_bits % 2 != 0) {
4437 crv = CKR_ATTRIBUTE_VALUE_INVALID;
4438 break;
4439 }
4441 /* extract the exponent */
4442 crv=sftk_Attribute2SSecItem(NULL,&pubExp,publicKey,CKA_PUBLIC_EXPONENT);
4443 if (crv != CKR_OK) break;
4444 bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len);
4445 if (bitSize < 2) {
4446 crv = CKR_ATTRIBUTE_VALUE_INVALID;
4447 break;
4448 }
4449 crv = sftk_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT,
4450 sftk_item_expand(&pubExp));
4451 if (crv != CKR_OK) {
4452 PORT_Free(pubExp.data);
4453 break;
4454 }
4456 rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);
4457 PORT_Free(pubExp.data);
4458 if (rsaPriv == NULL) {
4459 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4460 sftk_fatalError = PR_TRUE;
4461 }
4462 crv = sftk_MapCryptError(PORT_GetError());
4463 break;
4464 }
4465 /* now fill in the RSA dependent paramenters in the public key */
4466 crv = sftk_AddAttributeType(publicKey,CKA_MODULUS,
4467 sftk_item_expand(&rsaPriv->modulus));
4468 if (crv != CKR_OK) goto kpg_done;
4469 /* now fill in the RSA dependent paramenters in the private key */
4470 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
4471 sftk_item_expand(&rsaPriv->modulus));
4472 if (crv != CKR_OK) goto kpg_done;
4473 crv = sftk_AddAttributeType(privateKey,CKA_MODULUS,
4474 sftk_item_expand(&rsaPriv->modulus));
4475 if (crv != CKR_OK) goto kpg_done;
4476 crv = sftk_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT,
4477 sftk_item_expand(&rsaPriv->privateExponent));
4478 if (crv != CKR_OK) goto kpg_done;
4479 crv = sftk_AddAttributeType(privateKey,CKA_PRIME_1,
4480 sftk_item_expand(&rsaPriv->prime1));
4481 if (crv != CKR_OK) goto kpg_done;
4482 crv = sftk_AddAttributeType(privateKey,CKA_PRIME_2,
4483 sftk_item_expand(&rsaPriv->prime2));
4484 if (crv != CKR_OK) goto kpg_done;
4485 crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_1,
4486 sftk_item_expand(&rsaPriv->exponent1));
4487 if (crv != CKR_OK) goto kpg_done;
4488 crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_2,
4489 sftk_item_expand(&rsaPriv->exponent2));
4490 if (crv != CKR_OK) goto kpg_done;
4491 crv = sftk_AddAttributeType(privateKey,CKA_COEFFICIENT,
4492 sftk_item_expand(&rsaPriv->coefficient));
4493 kpg_done:
4494 /* Should zeroize the contents first, since this func doesn't. */
4495 PORT_FreeArena(rsaPriv->arena, PR_TRUE);
4496 break;
4497 case CKM_DSA_KEY_PAIR_GEN:
4498 sftk_DeleteAttributeType(publicKey,CKA_VALUE);
4499 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
4500 sftk_DeleteAttributeType(privateKey,CKA_PRIME);
4501 sftk_DeleteAttributeType(privateKey,CKA_SUBPRIME);
4502 sftk_DeleteAttributeType(privateKey,CKA_BASE);
4503 key_type = CKK_DSA;
4505 /* extract the necessary parameters and copy them to the private key */
4506 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.prime,publicKey,CKA_PRIME);
4507 if (crv != CKR_OK) break;
4508 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.subPrime,publicKey,
4509 CKA_SUBPRIME);
4510 if (crv != CKR_OK) {
4511 PORT_Free(pqgParam.prime.data);
4512 break;
4513 }
4514 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.base,publicKey,CKA_BASE);
4515 if (crv != CKR_OK) {
4516 PORT_Free(pqgParam.prime.data);
4517 PORT_Free(pqgParam.subPrime.data);
4518 break;
4519 }
4520 crv = sftk_AddAttributeType(privateKey,CKA_PRIME,
4521 sftk_item_expand(&pqgParam.prime));
4522 if (crv != CKR_OK) {
4523 PORT_Free(pqgParam.prime.data);
4524 PORT_Free(pqgParam.subPrime.data);
4525 PORT_Free(pqgParam.base.data);
4526 break;
4527 }
4528 crv = sftk_AddAttributeType(privateKey,CKA_SUBPRIME,
4529 sftk_item_expand(&pqgParam.subPrime));
4530 if (crv != CKR_OK) {
4531 PORT_Free(pqgParam.prime.data);
4532 PORT_Free(pqgParam.subPrime.data);
4533 PORT_Free(pqgParam.base.data);
4534 break;
4535 }
4536 crv = sftk_AddAttributeType(privateKey,CKA_BASE,
4537 sftk_item_expand(&pqgParam.base));
4538 if (crv != CKR_OK) {
4539 PORT_Free(pqgParam.prime.data);
4540 PORT_Free(pqgParam.subPrime.data);
4541 PORT_Free(pqgParam.base.data);
4542 break;
4543 }
4545 /*
4546 * these are checked by DSA_NewKey
4547 */
4548 bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data,
4549 pqgParam.subPrime.len);
4550 if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) {
4551 crv = CKR_TEMPLATE_INCOMPLETE;
4552 PORT_Free(pqgParam.prime.data);
4553 PORT_Free(pqgParam.subPrime.data);
4554 PORT_Free(pqgParam.base.data);
4555 break;
4556 }
4557 bitSize = sftk_GetLengthInBits(pqgParam.prime.data,pqgParam.prime.len);
4558 if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) {
4559 crv = CKR_TEMPLATE_INCOMPLETE;
4560 PORT_Free(pqgParam.prime.data);
4561 PORT_Free(pqgParam.subPrime.data);
4562 PORT_Free(pqgParam.base.data);
4563 break;
4564 }
4565 bitSize = sftk_GetLengthInBits(pqgParam.base.data,pqgParam.base.len);
4566 if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) {
4567 crv = CKR_TEMPLATE_INCOMPLETE;
4568 PORT_Free(pqgParam.prime.data);
4569 PORT_Free(pqgParam.subPrime.data);
4570 PORT_Free(pqgParam.base.data);
4571 break;
4572 }
4574 /* Generate the key */
4575 rv = DSA_NewKey(&pqgParam, &dsaPriv);
4577 PORT_Free(pqgParam.prime.data);
4578 PORT_Free(pqgParam.subPrime.data);
4579 PORT_Free(pqgParam.base.data);
4581 if (rv != SECSuccess) {
4582 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4583 sftk_fatalError = PR_TRUE;
4584 }
4585 crv = sftk_MapCryptError(PORT_GetError());
4586 break;
4587 }
4589 /* store the generated key into the attributes */
4590 crv = sftk_AddAttributeType(publicKey,CKA_VALUE,
4591 sftk_item_expand(&dsaPriv->publicValue));
4592 if (crv != CKR_OK) goto dsagn_done;
4594 /* now fill in the RSA dependent paramenters in the private key */
4595 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
4596 sftk_item_expand(&dsaPriv->publicValue));
4597 if (crv != CKR_OK) goto dsagn_done;
4598 crv = sftk_AddAttributeType(privateKey,CKA_VALUE,
4599 sftk_item_expand(&dsaPriv->privateValue));
4601 dsagn_done:
4602 /* should zeroize, since this function doesn't. */
4603 PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
4604 break;
4606 case CKM_DH_PKCS_KEY_PAIR_GEN:
4607 sftk_DeleteAttributeType(privateKey,CKA_PRIME);
4608 sftk_DeleteAttributeType(privateKey,CKA_BASE);
4609 sftk_DeleteAttributeType(privateKey,CKA_VALUE);
4610 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
4611 key_type = CKK_DH;
4613 /* extract the necessary parameters and copy them to private keys */
4614 crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey,
4615 CKA_PRIME);
4616 if (crv != CKR_OK) break;
4617 crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
4618 if (crv != CKR_OK) {
4619 PORT_Free(dhParam.prime.data);
4620 break;
4621 }
4622 crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
4623 sftk_item_expand(&dhParam.prime));
4624 if (crv != CKR_OK) {
4625 PORT_Free(dhParam.prime.data);
4626 PORT_Free(dhParam.base.data);
4627 break;
4628 }
4629 crv = sftk_AddAttributeType(privateKey, CKA_BASE,
4630 sftk_item_expand(&dhParam.base));
4631 if (crv != CKR_OK) {
4632 PORT_Free(dhParam.prime.data);
4633 PORT_Free(dhParam.base.data);
4634 break;
4635 }
4636 bitSize = sftk_GetLengthInBits(dhParam.prime.data,dhParam.prime.len);
4637 if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) {
4638 crv = CKR_TEMPLATE_INCOMPLETE;
4639 PORT_Free(dhParam.prime.data);
4640 PORT_Free(dhParam.base.data);
4641 break;
4642 }
4643 bitSize = sftk_GetLengthInBits(dhParam.base.data,dhParam.base.len);
4644 if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) {
4645 crv = CKR_TEMPLATE_INCOMPLETE;
4646 PORT_Free(dhParam.prime.data);
4647 PORT_Free(dhParam.base.data);
4648 break;
4649 }
4651 rv = DH_NewKey(&dhParam, &dhPriv);
4652 PORT_Free(dhParam.prime.data);
4653 PORT_Free(dhParam.base.data);
4654 if (rv != SECSuccess) {
4655 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4656 sftk_fatalError = PR_TRUE;
4657 }
4658 crv = sftk_MapCryptError(PORT_GetError());
4659 break;
4660 }
4662 crv=sftk_AddAttributeType(publicKey, CKA_VALUE,
4663 sftk_item_expand(&dhPriv->publicValue));
4664 if (crv != CKR_OK) goto dhgn_done;
4666 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
4667 sftk_item_expand(&dhPriv->publicValue));
4668 if (crv != CKR_OK) goto dhgn_done;
4670 crv=sftk_AddAttributeType(privateKey, CKA_VALUE,
4671 sftk_item_expand(&dhPriv->privateValue));
4673 dhgn_done:
4674 /* should zeroize, since this function doesn't. */
4675 PORT_FreeArena(dhPriv->arena, PR_TRUE);
4676 break;
4678 #ifndef NSS_DISABLE_ECC
4679 case CKM_EC_KEY_PAIR_GEN:
4680 sftk_DeleteAttributeType(privateKey,CKA_EC_PARAMS);
4681 sftk_DeleteAttributeType(privateKey,CKA_VALUE);
4682 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
4683 key_type = CKK_EC;
4685 /* extract the necessary parameters and copy them to private keys */
4686 crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
4687 CKA_EC_PARAMS);
4688 if (crv != CKR_OK) break;
4690 crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
4691 sftk_item_expand(&ecEncodedParams));
4692 if (crv != CKR_OK) {
4693 PORT_Free(ecEncodedParams.data);
4694 break;
4695 }
4697 /* Decode ec params before calling EC_NewKey */
4698 rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
4699 PORT_Free(ecEncodedParams.data);
4700 if (rv != SECSuccess) {
4701 crv = sftk_MapCryptError(PORT_GetError());
4702 break;
4703 }
4704 rv = EC_NewKey(ecParams, &ecPriv);
4705 PORT_FreeArena(ecParams->arena, PR_TRUE);
4706 if (rv != SECSuccess) {
4707 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4708 sftk_fatalError = PR_TRUE;
4709 }
4710 crv = sftk_MapCryptError(PORT_GetError());
4711 break;
4712 }
4714 if (getenv("NSS_USE_DECODED_CKA_EC_POINT")) {
4715 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
4716 sftk_item_expand(&ecPriv->publicValue));
4717 } else {
4718 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
4719 &ecPriv->publicValue,
4720 SEC_ASN1_GET(SEC_OctetStringTemplate));
4721 if (!pubValue) {
4722 crv = CKR_ARGUMENTS_BAD;
4723 goto ecgn_done;
4724 }
4725 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
4726 sftk_item_expand(pubValue));
4727 SECITEM_FreeItem(pubValue, PR_TRUE);
4728 }
4729 if (crv != CKR_OK) goto ecgn_done;
4731 crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
4732 sftk_item_expand(&ecPriv->privateValue));
4733 if (crv != CKR_OK) goto ecgn_done;
4735 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
4736 sftk_item_expand(&ecPriv->publicValue));
4737 ecgn_done:
4738 /* should zeroize, since this function doesn't. */
4739 PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
4740 break;
4741 #endif /* NSS_DISABLE_ECC */
4743 default:
4744 crv = CKR_MECHANISM_INVALID;
4745 }
4747 if (crv != CKR_OK) {
4748 sftk_FreeObject(privateKey);
4749 sftk_FreeObject(publicKey);
4750 return crv;
4751 }
4754 /* Add the class, key_type The loop lets us check errors blow out
4755 * on errors and clean up at the bottom */
4756 session = NULL; /* make pedtantic happy... session cannot leave the*/
4757 /* loop below NULL unless an error is set... */
4758 do {
4759 crv = sftk_AddAttributeType(privateKey,CKA_CLASS,&privClass,
4760 sizeof(CK_OBJECT_CLASS));
4761 if (crv != CKR_OK) break;
4762 crv = sftk_AddAttributeType(publicKey,CKA_CLASS,&pubClass,
4763 sizeof(CK_OBJECT_CLASS));
4764 if (crv != CKR_OK) break;
4765 crv = sftk_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type,
4766 sizeof(CK_KEY_TYPE));
4767 if (crv != CKR_OK) break;
4768 crv = sftk_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type,
4769 sizeof(CK_KEY_TYPE));
4770 if (crv != CKR_OK) break;
4771 session = sftk_SessionFromHandle(hSession);
4772 if (session == NULL) crv = CKR_SESSION_HANDLE_INVALID;
4773 } while (0);
4775 if (crv != CKR_OK) {
4776 sftk_FreeObject(privateKey);
4777 sftk_FreeObject(publicKey);
4778 return crv;
4779 }
4781 /*
4782 * handle the base object cleanup for the public Key
4783 */
4784 crv = sftk_handleObject(privateKey,session);
4785 if (crv != CKR_OK) {
4786 sftk_FreeSession(session);
4787 sftk_FreeObject(privateKey);
4788 sftk_FreeObject(publicKey);
4789 return crv;
4790 }
4792 /*
4793 * handle the base object cleanup for the private Key
4794 * If we have any problems, we destroy the public Key we've
4795 * created and linked.
4796 */
4797 crv = sftk_handleObject(publicKey,session);
4798 sftk_FreeSession(session);
4799 if (crv != CKR_OK) {
4800 sftk_FreeObject(publicKey);
4801 NSC_DestroyObject(hSession,privateKey->handle);
4802 sftk_FreeObject(privateKey);
4803 return crv;
4804 }
4805 if (sftk_isTrue(privateKey,CKA_SENSITIVE)) {
4806 sftk_forceAttribute(privateKey,CKA_ALWAYS_SENSITIVE,
4807 &cktrue,sizeof(CK_BBOOL));
4808 }
4809 if (sftk_isTrue(publicKey,CKA_SENSITIVE)) {
4810 sftk_forceAttribute(publicKey,CKA_ALWAYS_SENSITIVE,
4811 &cktrue,sizeof(CK_BBOOL));
4812 }
4813 if (!sftk_isTrue(privateKey,CKA_EXTRACTABLE)) {
4814 sftk_forceAttribute(privateKey,CKA_NEVER_EXTRACTABLE,
4815 &cktrue,sizeof(CK_BBOOL));
4816 }
4817 if (!sftk_isTrue(publicKey,CKA_EXTRACTABLE)) {
4818 sftk_forceAttribute(publicKey,CKA_NEVER_EXTRACTABLE,
4819 &cktrue,sizeof(CK_BBOOL));
4820 }
4822 /* Perform FIPS 140-2 pairwise consistency check. */
4823 crv = sftk_PairwiseConsistencyCheck(hSession,
4824 publicKey, privateKey, key_type);
4825 if (crv != CKR_OK) {
4826 NSC_DestroyObject(hSession,publicKey->handle);
4827 sftk_FreeObject(publicKey);
4828 NSC_DestroyObject(hSession,privateKey->handle);
4829 sftk_FreeObject(privateKey);
4830 if (sftk_audit_enabled) {
4831 char msg[128];
4832 PR_snprintf(msg,sizeof msg,
4833 "C_GenerateKeyPair(hSession=0x%08lX, "
4834 "pMechanism->mechanism=0x%08lX)=0x%08lX "
4835 "self-test: pair-wise consistency test failed",
4836 (PRUint32)hSession,(PRUint32)pMechanism->mechanism,
4837 (PRUint32)crv);
4838 sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg);
4839 }
4840 return crv;
4841 }
4843 *phPrivateKey = privateKey->handle;
4844 *phPublicKey = publicKey->handle;
4845 sftk_FreeObject(publicKey);
4846 sftk_FreeObject(privateKey);
4848 return CKR_OK;
4849 }
4851 static SECItem *sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp)
4852 {
4853 NSSLOWKEYPrivateKey *lk = NULL;
4854 NSSLOWKEYPrivateKeyInfo *pki = NULL;
4855 SFTKAttribute *attribute = NULL;
4856 PLArenaPool *arena = NULL;
4857 SECOidTag algorithm = SEC_OID_UNKNOWN;
4858 void *dummy, *param = NULL;
4859 SECStatus rv = SECSuccess;
4860 SECItem *encodedKey = NULL;
4861 #ifndef NSS_DISABLE_ECC
4862 SECItem *fordebug;
4863 int savelen;
4864 #endif
4866 if(!key) {
4867 *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */
4868 return NULL;
4869 }
4871 attribute = sftk_FindAttribute(key, CKA_KEY_TYPE);
4872 if(!attribute) {
4873 *crvp = CKR_KEY_TYPE_INCONSISTENT;
4874 return NULL;
4875 }
4877 lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp);
4878 sftk_FreeAttribute(attribute);
4879 if(!lk) {
4880 return NULL;
4881 }
4883 arena = PORT_NewArena(2048); /* XXX different size? */
4884 if(!arena) {
4885 *crvp = CKR_HOST_MEMORY;
4886 rv = SECFailure;
4887 goto loser;
4888 }
4890 pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
4891 sizeof(NSSLOWKEYPrivateKeyInfo));
4892 if(!pki) {
4893 *crvp = CKR_HOST_MEMORY;
4894 rv = SECFailure;
4895 goto loser;
4896 }
4897 pki->arena = arena;
4899 param = NULL;
4900 switch(lk->keyType) {
4901 case NSSLOWKEYRSAKey:
4902 prepare_low_rsa_priv_key_for_asn1(lk);
4903 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
4904 nsslowkey_RSAPrivateKeyTemplate);
4905 algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
4906 break;
4907 case NSSLOWKEYDSAKey:
4908 prepare_low_dsa_priv_key_export_for_asn1(lk);
4909 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
4910 nsslowkey_DSAPrivateKeyExportTemplate);
4911 prepare_low_pqg_params_for_asn1(&lk->u.dsa.params);
4912 param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
4913 nsslowkey_PQGParamsTemplate);
4914 algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
4915 break;
4916 #ifndef NSS_DISABLE_ECC
4917 case NSSLOWKEYECKey:
4918 prepare_low_ec_priv_key_for_asn1(lk);
4919 /* Public value is encoded as a bit string so adjust length
4920 * to be in bits before ASN encoding and readjust
4921 * immediately after.
4922 *
4923 * Since the SECG specification recommends not including the
4924 * parameters as part of ECPrivateKey, we zero out the curveOID
4925 * length before encoding and restore it later.
4926 */
4927 lk->u.ec.publicValue.len <<= 3;
4928 savelen = lk->u.ec.ecParams.curveOID.len;
4929 lk->u.ec.ecParams.curveOID.len = 0;
4930 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
4931 nsslowkey_ECPrivateKeyTemplate);
4932 lk->u.ec.ecParams.curveOID.len = savelen;
4933 lk->u.ec.publicValue.len >>= 3;
4935 fordebug = &pki->privateKey;
4936 SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType,
4937 fordebug);
4939 param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding);
4941 algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
4942 break;
4943 #endif /* NSS_DISABLE_ECC */
4944 case NSSLOWKEYDHKey:
4945 default:
4946 dummy = NULL;
4947 break;
4948 }
4950 if(!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) {
4951 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
4952 rv = SECFailure;
4953 goto loser;
4954 }
4956 rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm,
4957 (SECItem*)param);
4958 if(rv != SECSuccess) {
4959 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
4960 rv = SECFailure;
4961 goto loser;
4962 }
4964 dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
4965 NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
4966 if(!dummy) {
4967 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
4968 rv = SECFailure;
4969 goto loser;
4970 }
4972 encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
4973 nsslowkey_PrivateKeyInfoTemplate);
4974 *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR;
4976 #ifndef NSS_DISABLE_ECC
4977 fordebug = encodedKey;
4978 SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType,
4979 fordebug);
4980 #endif
4981 loser:
4982 if(arena) {
4983 PORT_FreeArena(arena, PR_TRUE);
4984 }
4986 if(lk && (lk != key->objectInfo)) {
4987 nsslowkey_DestroyPrivateKey(lk);
4988 }
4990 if(param) {
4991 SECITEM_ZfreeItem((SECItem*)param, PR_TRUE);
4992 }
4994 if(rv != SECSuccess) {
4995 return NULL;
4996 }
4998 return encodedKey;
4999 }
5001 /* it doesn't matter yet, since we colapse error conditions in the
5002 * level above, but we really should map those few key error differences */
5003 static CK_RV
5004 sftk_mapWrap(CK_RV crv)
5005 {
5006 switch (crv) {
5007 case CKR_ENCRYPTED_DATA_INVALID: crv = CKR_WRAPPED_KEY_INVALID; break;
5008 }
5009 return crv;
5010 }
5012 /* NSC_WrapKey wraps (i.e., encrypts) a key. */
5013 CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession,
5014 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
5015 CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
5016 CK_ULONG_PTR pulWrappedKeyLen)
5017 {
5018 SFTKSession *session;
5019 SFTKAttribute *attribute;
5020 SFTKObject *key;
5021 CK_RV crv;
5023 CHECK_FORK();
5025 session = sftk_SessionFromHandle(hSession);
5026 if (session == NULL) {
5027 return CKR_SESSION_HANDLE_INVALID;
5028 }
5030 key = sftk_ObjectFromHandle(hKey,session);
5031 sftk_FreeSession(session);
5032 if (key == NULL) {
5033 return CKR_KEY_HANDLE_INVALID;
5034 }
5036 switch(key->objclass) {
5037 case CKO_SECRET_KEY:
5038 {
5039 SFTKSessionContext *context = NULL;
5040 SECItem pText;
5042 attribute = sftk_FindAttribute(key,CKA_VALUE);
5044 if (attribute == NULL) {
5045 crv = CKR_KEY_TYPE_INCONSISTENT;
5046 break;
5047 }
5048 crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
5049 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
5050 if (crv != CKR_OK) {
5051 sftk_FreeAttribute(attribute);
5052 break;
5053 }
5055 pText.type = siBuffer;
5056 pText.data = (unsigned char *)attribute->attrib.pValue;
5057 pText.len = attribute->attrib.ulValueLen;
5059 /* Find out if this is a block cipher. */
5060 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,NULL);
5061 if (crv != CKR_OK || !context)
5062 break;
5063 if (context->blockSize > 1) {
5064 unsigned int remainder = pText.len % context->blockSize;
5065 if (!context->doPad && remainder) {
5066 /* When wrapping secret keys with unpadded block ciphers,
5067 ** the keys are zero padded, if necessary, to fill out
5068 ** a full block.
5069 */
5070 pText.len += context->blockSize - remainder;
5071 pText.data = PORT_ZAlloc(pText.len);
5072 if (pText.data)
5073 memcpy(pText.data, attribute->attrib.pValue,
5074 attribute->attrib.ulValueLen);
5075 else {
5076 crv = CKR_HOST_MEMORY;
5077 break;
5078 }
5079 }
5080 }
5082 crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data,
5083 pText.len, pWrappedKey, pulWrappedKeyLen);
5084 /* always force a finalize, both on errors and when
5085 * we are just getting the size */
5086 if (crv != CKR_OK || pWrappedKey == NULL) {
5087 CK_RV lcrv ;
5088 lcrv = sftk_GetContext(hSession,&context,
5089 SFTK_ENCRYPT,PR_FALSE,NULL);
5090 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
5091 if (lcrv == CKR_OK && context) {
5092 sftk_FreeContext(context);
5093 }
5094 }
5096 if (pText.data != (unsigned char *)attribute->attrib.pValue)
5097 PORT_ZFree(pText.data, pText.len);
5098 sftk_FreeAttribute(attribute);
5099 break;
5100 }
5102 case CKO_PRIVATE_KEY:
5103 {
5104 SECItem *bpki = sftk_PackagePrivateKey(key, &crv);
5105 SFTKSessionContext *context = NULL;
5107 if(!bpki) {
5108 break;
5109 }
5111 crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
5112 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
5113 if(crv != CKR_OK) {
5114 SECITEM_ZfreeItem(bpki, PR_TRUE);
5115 crv = CKR_KEY_TYPE_INCONSISTENT;
5116 break;
5117 }
5119 crv = NSC_Encrypt(hSession, bpki->data, bpki->len,
5120 pWrappedKey, pulWrappedKeyLen);
5121 /* always force a finalize */
5122 if (crv != CKR_OK || pWrappedKey == NULL) {
5123 CK_RV lcrv ;
5124 lcrv = sftk_GetContext(hSession,&context,
5125 SFTK_ENCRYPT,PR_FALSE,NULL);
5126 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
5127 if (lcrv == CKR_OK && context) {
5128 sftk_FreeContext(context);
5129 }
5130 }
5131 SECITEM_ZfreeItem(bpki, PR_TRUE);
5132 break;
5133 }
5135 default:
5136 crv = CKR_KEY_TYPE_INCONSISTENT;
5137 break;
5138 }
5139 sftk_FreeObject(key);
5141 return sftk_mapWrap(crv);
5142 }
5144 /*
5145 * import a pprivate key info into the desired slot
5146 */
5147 static SECStatus
5148 sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
5149 {
5150 CK_BBOOL cktrue = CK_TRUE;
5151 CK_KEY_TYPE keyType = CKK_RSA;
5152 SECStatus rv = SECFailure;
5153 const SEC_ASN1Template *keyTemplate, *paramTemplate;
5154 void *paramDest = NULL;
5155 PLArenaPool *arena;
5156 NSSLOWKEYPrivateKey *lpk = NULL;
5157 NSSLOWKEYPrivateKeyInfo *pki = NULL;
5158 CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
5160 arena = PORT_NewArena(2048);
5161 if(!arena) {
5162 return SECFailure;
5163 }
5165 pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
5166 sizeof(NSSLOWKEYPrivateKeyInfo));
5167 if(!pki) {
5168 PORT_FreeArena(arena, PR_FALSE);
5169 return SECFailure;
5170 }
5172 if(SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki)
5173 != SECSuccess) {
5174 PORT_FreeArena(arena, PR_TRUE);
5175 return SECFailure;
5176 }
5178 lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena,
5179 sizeof(NSSLOWKEYPrivateKey));
5180 if(lpk == NULL) {
5181 goto loser;
5182 }
5183 lpk->arena = arena;
5185 switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
5186 case SEC_OID_PKCS1_RSA_ENCRYPTION:
5187 keyTemplate = nsslowkey_RSAPrivateKeyTemplate;
5188 paramTemplate = NULL;
5189 paramDest = NULL;
5190 lpk->keyType = NSSLOWKEYRSAKey;
5191 prepare_low_rsa_priv_key_for_asn1(lpk);
5192 break;
5193 case SEC_OID_ANSIX9_DSA_SIGNATURE:
5194 keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate;
5195 paramTemplate = nsslowkey_PQGParamsTemplate;
5196 paramDest = &(lpk->u.dsa.params);
5197 lpk->keyType = NSSLOWKEYDSAKey;
5198 prepare_low_dsa_priv_key_export_for_asn1(lpk);
5199 prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params);
5200 break;
5201 /* case NSSLOWKEYDHKey: */
5202 #ifndef NSS_DISABLE_ECC
5203 case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
5204 keyTemplate = nsslowkey_ECPrivateKeyTemplate;
5205 paramTemplate = NULL;
5206 paramDest = &(lpk->u.ec.ecParams.DEREncoding);
5207 lpk->keyType = NSSLOWKEYECKey;
5208 prepare_low_ec_priv_key_for_asn1(lpk);
5209 prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams);
5210 break;
5211 #endif /* NSS_DISABLE_ECC */
5212 default:
5213 keyTemplate = NULL;
5214 paramTemplate = NULL;
5215 paramDest = NULL;
5216 break;
5217 }
5219 if(!keyTemplate) {
5220 goto loser;
5221 }
5223 /* decode the private key and any algorithm parameters */
5224 rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
5226 #ifndef NSS_DISABLE_ECC
5227 if (lpk->keyType == NSSLOWKEYECKey) {
5228 /* convert length in bits to length in bytes */
5229 lpk->u.ec.publicValue.len >>= 3;
5230 rv = SECITEM_CopyItem(arena,
5231 &(lpk->u.ec.ecParams.DEREncoding),
5232 &(pki->algorithm.parameters));
5233 if(rv != SECSuccess) {
5234 goto loser;
5235 }
5236 }
5237 #endif /* NSS_DISABLE_ECC */
5239 if(rv != SECSuccess) {
5240 goto loser;
5241 }
5242 if(paramDest && paramTemplate) {
5243 rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate,
5244 &(pki->algorithm.parameters));
5245 if(rv != SECSuccess) {
5246 goto loser;
5247 }
5248 }
5250 rv = SECFailure;
5252 switch (lpk->keyType) {
5253 case NSSLOWKEYRSAKey:
5254 keyType = CKK_RSA;
5255 if(sftk_hasAttribute(key, CKA_NETSCAPE_DB)) {
5256 sftk_DeleteAttributeType(key, CKA_NETSCAPE_DB);
5257 }
5258 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
5259 sizeof(keyType));
5260 if(crv != CKR_OK) break;
5261 crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue,
5262 sizeof(CK_BBOOL));
5263 if(crv != CKR_OK) break;
5264 crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue,
5265 sizeof(CK_BBOOL));
5266 if(crv != CKR_OK) break;
5267 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
5268 sizeof(CK_BBOOL));
5269 if(crv != CKR_OK) break;
5270 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
5271 sizeof(CK_BBOOL));
5272 if(crv != CKR_OK) break;
5273 crv = sftk_AddAttributeType(key, CKA_MODULUS,
5274 sftk_item_expand(&lpk->u.rsa.modulus));
5275 if(crv != CKR_OK) break;
5276 crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT,
5277 sftk_item_expand(&lpk->u.rsa.publicExponent));
5278 if(crv != CKR_OK) break;
5279 crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT,
5280 sftk_item_expand(&lpk->u.rsa.privateExponent));
5281 if(crv != CKR_OK) break;
5282 crv = sftk_AddAttributeType(key, CKA_PRIME_1,
5283 sftk_item_expand(&lpk->u.rsa.prime1));
5284 if(crv != CKR_OK) break;
5285 crv = sftk_AddAttributeType(key, CKA_PRIME_2,
5286 sftk_item_expand(&lpk->u.rsa.prime2));
5287 if(crv != CKR_OK) break;
5288 crv = sftk_AddAttributeType(key, CKA_EXPONENT_1,
5289 sftk_item_expand(&lpk->u.rsa.exponent1));
5290 if(crv != CKR_OK) break;
5291 crv = sftk_AddAttributeType(key, CKA_EXPONENT_2,
5292 sftk_item_expand(&lpk->u.rsa.exponent2));
5293 if(crv != CKR_OK) break;
5294 crv = sftk_AddAttributeType(key, CKA_COEFFICIENT,
5295 sftk_item_expand(&lpk->u.rsa.coefficient));
5296 break;
5297 case NSSLOWKEYDSAKey:
5298 keyType = CKK_DSA;
5299 crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK :
5300 CKR_KEY_TYPE_INCONSISTENT;
5301 if(crv != CKR_OK) break;
5302 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
5303 sizeof(keyType));
5304 if(crv != CKR_OK) break;
5305 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
5306 sizeof(CK_BBOOL));
5307 if(crv != CKR_OK) break;
5308 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
5309 sizeof(CK_BBOOL));
5310 if(crv != CKR_OK) break;
5311 crv = sftk_AddAttributeType(key, CKA_PRIME,
5312 sftk_item_expand(&lpk->u.dsa.params.prime));
5313 if(crv != CKR_OK) break;
5314 crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
5315 sftk_item_expand(&lpk->u.dsa.params.subPrime));
5316 if(crv != CKR_OK) break;
5317 crv = sftk_AddAttributeType(key, CKA_BASE,
5318 sftk_item_expand(&lpk->u.dsa.params.base));
5319 if(crv != CKR_OK) break;
5320 crv = sftk_AddAttributeType(key, CKA_VALUE,
5321 sftk_item_expand(&lpk->u.dsa.privateValue));
5322 if(crv != CKR_OK) break;
5323 break;
5324 #ifdef notdef
5325 case NSSLOWKEYDHKey:
5326 template = dhTemplate;
5327 templateCount = sizeof(dhTemplate)/sizeof(CK_ATTRIBUTE);
5328 keyType = CKK_DH;
5329 break;
5330 #endif
5331 /* what about fortezza??? */
5332 #ifndef NSS_DISABLE_ECC
5333 case NSSLOWKEYECKey:
5334 keyType = CKK_EC;
5335 crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK :
5336 CKR_KEY_TYPE_INCONSISTENT;
5337 if(crv != CKR_OK) break;
5338 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
5339 sizeof(keyType));
5340 if(crv != CKR_OK) break;
5341 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
5342 sizeof(CK_BBOOL));
5343 if(crv != CKR_OK) break;
5344 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
5345 sizeof(CK_BBOOL));
5346 if(crv != CKR_OK) break;
5347 crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue,
5348 sizeof(CK_BBOOL));
5349 if(crv != CKR_OK) break;
5350 crv = sftk_AddAttributeType(key, CKA_EC_PARAMS,
5351 sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding));
5352 if(crv != CKR_OK) break;
5353 crv = sftk_AddAttributeType(key, CKA_VALUE,
5354 sftk_item_expand(&lpk->u.ec.privateValue));
5355 if(crv != CKR_OK) break;
5356 /* XXX Do we need to decode the EC Params here ?? */
5357 break;
5358 #endif /* NSS_DISABLE_ECC */
5359 default:
5360 crv = CKR_KEY_TYPE_INCONSISTENT;
5361 break;
5362 }
5364 loser:
5365 if(lpk) {
5366 nsslowkey_DestroyPrivateKey(lpk);
5367 }
5369 if(crv != CKR_OK) {
5370 return SECFailure;
5371 }
5373 return SECSuccess;
5374 }
5377 /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
5378 CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
5379 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
5380 CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
5381 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
5382 CK_OBJECT_HANDLE_PTR phKey)
5383 {
5384 SFTKObject *key = NULL;
5385 SFTKSession *session;
5386 CK_ULONG key_length = 0;
5387 unsigned char * buf = NULL;
5388 CK_RV crv = CKR_OK;
5389 int i;
5390 CK_ULONG bsize = ulWrappedKeyLen;
5391 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5392 SECItem bpki;
5393 CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
5395 CHECK_FORK();
5397 if (!slot) {
5398 return CKR_SESSION_HANDLE_INVALID;
5399 }
5400 /*
5401 * now lets create an object to hang the attributes off of
5402 */
5403 key = sftk_NewObject(slot); /* fill in the handle later */
5404 if (key == NULL) {
5405 return CKR_HOST_MEMORY;
5406 }
5408 /*
5409 * load the template values into the object
5410 */
5411 for (i=0; i < (int) ulAttributeCount; i++) {
5412 if (pTemplate[i].type == CKA_VALUE_LEN) {
5413 key_length = *(CK_ULONG *)pTemplate[i].pValue;
5414 continue;
5415 }
5416 if (pTemplate[i].type == CKA_CLASS) {
5417 target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
5418 }
5419 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i]));
5420 if (crv != CKR_OK) break;
5421 }
5422 if (crv != CKR_OK) {
5423 sftk_FreeObject(key);
5424 return crv;
5425 }
5427 crv = sftk_CryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP,
5428 CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE);
5429 if (crv != CKR_OK) {
5430 sftk_FreeObject(key);
5431 return sftk_mapWrap(crv);
5432 }
5434 /* allocate the buffer to decrypt into
5435 * this assumes the unwrapped key is never larger than the
5436 * wrapped key. For all the mechanisms we support this is true */
5437 buf = (unsigned char *)PORT_Alloc( ulWrappedKeyLen);
5438 bsize = ulWrappedKeyLen;
5440 crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
5441 if (crv != CKR_OK) {
5442 sftk_FreeObject(key);
5443 PORT_Free(buf);
5444 return sftk_mapWrap(crv);
5445 }
5447 switch(target_type) {
5448 case CKO_SECRET_KEY:
5449 if (!sftk_hasAttribute(key,CKA_KEY_TYPE)) {
5450 crv = CKR_TEMPLATE_INCOMPLETE;
5451 break;
5452 }
5454 if (key_length == 0 || key_length > bsize) {
5455 key_length = bsize;
5456 }
5457 if (key_length > MAX_KEY_LEN) {
5458 crv = CKR_TEMPLATE_INCONSISTENT;
5459 break;
5460 }
5462 /* add the value */
5463 crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length);
5464 break;
5465 case CKO_PRIVATE_KEY:
5466 bpki.data = (unsigned char *)buf;
5467 bpki.len = bsize;
5468 crv = CKR_OK;
5469 if(sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) {
5470 crv = CKR_TEMPLATE_INCOMPLETE;
5471 }
5472 break;
5473 default:
5474 crv = CKR_TEMPLATE_INCONSISTENT;
5475 break;
5476 }
5478 PORT_ZFree(buf, bsize);
5479 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
5481 /* get the session */
5482 session = sftk_SessionFromHandle(hSession);
5483 if (session == NULL) {
5484 sftk_FreeObject(key);
5485 return CKR_SESSION_HANDLE_INVALID;
5486 }
5488 /*
5489 * handle the base object stuff
5490 */
5491 crv = sftk_handleObject(key,session);
5492 *phKey = key->handle;
5493 sftk_FreeSession(session);
5494 sftk_FreeObject(key);
5496 return crv;
5498 }
5500 /*
5501 * The SSL key gen mechanism create's lots of keys. This function handles the
5502 * details of each of these key creation.
5503 */
5504 static CK_RV
5505 sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey,
5506 PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
5507 CK_OBJECT_HANDLE *keyHandle)
5508 {
5509 SFTKObject *key;
5510 SFTKSession *session;
5511 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
5512 CK_BBOOL cktrue = CK_TRUE;
5513 CK_BBOOL ckfalse = CK_FALSE;
5514 CK_RV crv = CKR_HOST_MEMORY;
5516 /*
5517 * now lets create an object to hang the attributes off of
5518 */
5519 *keyHandle = CK_INVALID_HANDLE;
5520 key = sftk_NewObject(baseKey->slot);
5521 if (key == NULL) return CKR_HOST_MEMORY;
5522 sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE;
5524 crv = sftk_CopyObject(key,baseKey);
5525 if (crv != CKR_OK) goto loser;
5526 if (isMacKey) {
5527 crv = sftk_forceAttribute(key,CKA_KEY_TYPE,&keyType,sizeof(keyType));
5528 if (crv != CKR_OK) goto loser;
5529 crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
5530 if (crv != CKR_OK) goto loser;
5531 crv = sftk_forceAttribute(key,CKA_ENCRYPT,&ckfalse,sizeof(CK_BBOOL));
5532 if (crv != CKR_OK) goto loser;
5533 crv = sftk_forceAttribute(key,CKA_DECRYPT,&ckfalse,sizeof(CK_BBOOL));
5534 if (crv != CKR_OK) goto loser;
5535 crv = sftk_forceAttribute(key,CKA_SIGN,&cktrue,sizeof(CK_BBOOL));
5536 if (crv != CKR_OK) goto loser;
5537 crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
5538 if (crv != CKR_OK) goto loser;
5539 crv = sftk_forceAttribute(key,CKA_WRAP,&ckfalse,sizeof(CK_BBOOL));
5540 if (crv != CKR_OK) goto loser;
5541 crv = sftk_forceAttribute(key,CKA_UNWRAP,&ckfalse,sizeof(CK_BBOOL));
5542 if (crv != CKR_OK) goto loser;
5543 }
5544 crv = sftk_forceAttribute(key,CKA_VALUE,keyBlock,keySize);
5545 if (crv != CKR_OK) goto loser;
5547 /* get the session */
5548 crv = CKR_HOST_MEMORY;
5549 session = sftk_SessionFromHandle(hSession);
5550 if (session == NULL) { goto loser; }
5552 crv = sftk_handleObject(key,session);
5553 sftk_FreeSession(session);
5554 *keyHandle = key->handle;
5555 loser:
5556 if (key) sftk_FreeObject(key);
5557 return crv;
5558 }
5560 /*
5561 * if there is an error, we need to free the keys we already created in SSL
5562 * This is the routine that will do it..
5563 */
5564 static void
5565 sftk_freeSSLKeys(CK_SESSION_HANDLE session,
5566 CK_SSL3_KEY_MAT_OUT *returnedMaterial )
5567 {
5568 if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) {
5569 NSC_DestroyObject(session,returnedMaterial->hClientMacSecret);
5570 }
5571 if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) {
5572 NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
5573 }
5574 if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) {
5575 NSC_DestroyObject(session, returnedMaterial->hClientKey);
5576 }
5577 if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) {
5578 NSC_DestroyObject(session, returnedMaterial->hServerKey);
5579 }
5580 }
5582 /*
5583 * when deriving from sensitive and extractable keys, we need to preserve some
5584 * of the semantics in the derived key. This helper routine maintains these
5585 * semantics.
5586 */
5587 static CK_RV
5588 sftk_DeriveSensitiveCheck(SFTKObject *baseKey,SFTKObject *destKey)
5589 {
5590 PRBool hasSensitive;
5591 PRBool sensitive = PR_FALSE;
5592 PRBool hasExtractable;
5593 PRBool extractable = PR_TRUE;
5594 CK_RV crv = CKR_OK;
5595 SFTKAttribute *att;
5597 hasSensitive = PR_FALSE;
5598 att = sftk_FindAttribute(destKey,CKA_SENSITIVE);
5599 if (att) {
5600 hasSensitive = PR_TRUE;
5601 sensitive = (PRBool) *(CK_BBOOL *)att->attrib.pValue;
5602 sftk_FreeAttribute(att);
5603 }
5605 hasExtractable = PR_FALSE;
5606 att = sftk_FindAttribute(destKey,CKA_EXTRACTABLE);
5607 if (att) {
5608 hasExtractable = PR_TRUE;
5609 extractable = (PRBool) *(CK_BBOOL *)att->attrib.pValue;
5610 sftk_FreeAttribute(att);
5611 }
5614 /* don't make a key more accessible */
5615 if (sftk_isTrue(baseKey,CKA_SENSITIVE) && hasSensitive &&
5616 (sensitive == PR_FALSE)) {
5617 return CKR_KEY_FUNCTION_NOT_PERMITTED;
5618 }
5619 if (!sftk_isTrue(baseKey,CKA_EXTRACTABLE) && hasExtractable &&
5620 (extractable == PR_TRUE)) {
5621 return CKR_KEY_FUNCTION_NOT_PERMITTED;
5622 }
5624 /* inherit parent's sensitivity */
5625 if (!hasSensitive) {
5626 att = sftk_FindAttribute(baseKey,CKA_SENSITIVE);
5627 if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT;
5628 crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib));
5629 sftk_FreeAttribute(att);
5630 if (crv != CKR_OK) return crv;
5631 }
5632 if (!hasExtractable) {
5633 att = sftk_FindAttribute(baseKey,CKA_EXTRACTABLE);
5634 if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT;
5635 crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib));
5636 sftk_FreeAttribute(att);
5637 if (crv != CKR_OK) return crv;
5638 }
5640 /* we should inherit the parent's always extractable/ never sensitive info,
5641 * but handleObject always forces this attributes, so we would need to do
5642 * something special. */
5643 return CKR_OK;
5644 }
5646 /*
5647 * make known fixed PKCS #11 key types to their sizes in bytes
5648 */
5649 unsigned long
5650 sftk_MapKeySize(CK_KEY_TYPE keyType)
5651 {
5652 switch (keyType) {
5653 case CKK_CDMF:
5654 return 8;
5655 case CKK_DES:
5656 return 8;
5657 case CKK_DES2:
5658 return 16;
5659 case CKK_DES3:
5660 return 24;
5661 /* IDEA and CAST need to be added */
5662 default:
5663 break;
5664 }
5665 return 0;
5666 }
5668 #ifndef NSS_DISABLE_ECC
5669 /* Inputs:
5670 * key_len: Length of derived key to be generated.
5671 * SharedSecret: a shared secret that is the output of a key agreement primitive.
5672 * SharedInfo: (Optional) some data shared by the entities computing the secret key.
5673 * SharedInfoLen: the length in octets of SharedInfo
5674 * Hash: The hash function to be used in the KDF
5675 * HashLen: the length in octets of the output of Hash
5676 * Output:
5677 * key: Pointer to a buffer containing derived key, if return value is SECSuccess.
5678 */
5679 static CK_RV sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret,
5680 CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
5681 SECStatus Hash(unsigned char *, const unsigned char *, PRUint32),
5682 CK_ULONG HashLen)
5683 {
5684 unsigned char *buffer = NULL, *output_buffer = NULL;
5685 PRUint32 buffer_len, max_counter, i;
5686 SECStatus rv;
5687 CK_RV crv;
5689 /* Check that key_len isn't too long. The maximum key length could be
5690 * greatly increased if the code below did not limit the 4-byte counter
5691 * to a maximum value of 255. */
5692 if (key_len > 254 * HashLen)
5693 return CKR_ARGUMENTS_BAD;
5695 if (SharedInfo == NULL)
5696 SharedInfoLen = 0;
5698 buffer_len = SharedSecret->len + 4 + SharedInfoLen;
5699 buffer = (CK_BYTE *)PORT_Alloc(buffer_len);
5700 if (buffer == NULL) {
5701 crv = CKR_HOST_MEMORY;
5702 goto loser;
5703 }
5705 max_counter = key_len/HashLen;
5706 if (key_len > max_counter * HashLen)
5707 max_counter++;
5709 output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen);
5710 if (output_buffer == NULL) {
5711 crv = CKR_HOST_MEMORY;
5712 goto loser;
5713 }
5715 /* Populate buffer with SharedSecret || Counter || [SharedInfo]
5716 * where Counter is 0x00000001 */
5717 PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len);
5718 buffer[SharedSecret->len] = 0;
5719 buffer[SharedSecret->len + 1] = 0;
5720 buffer[SharedSecret->len + 2] = 0;
5721 buffer[SharedSecret->len + 3] = 1;
5722 if (SharedInfo) {
5723 PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen);
5724 }
5726 for(i=0; i < max_counter; i++) {
5727 rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len);
5728 if (rv != SECSuccess) {
5729 /* 'Hash' should not fail. */
5730 crv = CKR_FUNCTION_FAILED;
5731 goto loser;
5732 }
5734 /* Increment counter (assumes max_counter < 255) */
5735 buffer[SharedSecret->len + 3]++;
5736 }
5738 PORT_ZFree(buffer, buffer_len);
5739 if (key_len < max_counter * HashLen) {
5740 PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len);
5741 }
5742 *key = output_buffer;
5744 return CKR_OK;
5746 loser:
5747 if (buffer) {
5748 PORT_ZFree(buffer, buffer_len);
5749 }
5750 if (output_buffer) {
5751 PORT_ZFree(output_buffer, max_counter * HashLen);
5752 }
5753 return crv;
5754 }
5756 static CK_RV sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len,
5757 SECItem *SharedSecret,
5758 CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
5759 CK_EC_KDF_TYPE kdf)
5760 {
5761 if (kdf == CKD_SHA1_KDF)
5762 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
5763 SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH);
5764 else if (kdf == CKD_SHA224_KDF)
5765 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
5766 SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH);
5767 else if (kdf == CKD_SHA256_KDF)
5768 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
5769 SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH);
5770 else if (kdf == CKD_SHA384_KDF)
5771 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
5772 SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH);
5773 else if (kdf == CKD_SHA512_KDF)
5774 return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
5775 SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH);
5776 else
5777 return CKR_MECHANISM_INVALID;
5778 }
5779 #endif /* NSS_DISABLE_ECC */
5781 /*
5782 * SSL Key generation given pre master secret
5783 */
5784 #define NUM_MIXERS 9
5785 static const char * const mixers[NUM_MIXERS] = {
5786 "A",
5787 "BB",
5788 "CCC",
5789 "DDDD",
5790 "EEEEE",
5791 "FFFFFF",
5792 "GGGGGGG",
5793 "HHHHHHHH",
5794 "IIIIIIIII" };
5795 #define SSL3_PMS_LENGTH 48
5796 #define SSL3_MASTER_SECRET_LENGTH 48
5797 #define SSL3_RANDOM_LENGTH 32
5800 /* NSC_DeriveKey derives a key from a base key, creating a new key object. */
5801 CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
5802 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
5803 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
5804 CK_OBJECT_HANDLE_PTR phKey)
5805 {
5806 SFTKSession * session;
5807 SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession);
5808 SFTKObject * key;
5809 SFTKObject * sourceKey;
5810 SFTKAttribute * att = NULL;
5811 SFTKAttribute * att2 = NULL;
5812 unsigned char * buf;
5813 SHA1Context * sha;
5814 MD5Context * md5;
5815 MD2Context * md2;
5816 CK_ULONG macSize;
5817 CK_ULONG tmpKeySize;
5818 CK_ULONG IVSize;
5819 CK_ULONG keySize = 0;
5820 CK_RV crv = CKR_OK;
5821 CK_BBOOL cktrue = CK_TRUE;
5822 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
5823 CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
5824 CK_KEY_DERIVATION_STRING_DATA *stringPtr;
5825 PRBool isTLS = PR_FALSE;
5826 PRBool isSHA256 = PR_FALSE;
5827 PRBool isDH = PR_FALSE;
5828 SECStatus rv;
5829 int i;
5830 unsigned int outLen;
5831 unsigned char sha_out[SHA1_LENGTH];
5832 unsigned char key_block[NUM_MIXERS * MD5_LENGTH];
5833 unsigned char key_block2[MD5_LENGTH];
5834 PRBool isFIPS;
5835 HASH_HashType hashType;
5836 PRBool extractValue = PR_TRUE;
5838 CHECK_FORK();
5840 if (!slot) {
5841 return CKR_SESSION_HANDLE_INVALID;
5842 }
5843 /*
5844 * now lets create an object to hang the attributes off of
5845 */
5846 if (phKey) *phKey = CK_INVALID_HANDLE;
5848 key = sftk_NewObject(slot); /* fill in the handle later */
5849 if (key == NULL) {
5850 return CKR_HOST_MEMORY;
5851 }
5852 isFIPS = (slot->slotID == FIPS_SLOT_ID);
5854 /*
5855 * load the template values into the object
5856 */
5857 for (i=0; i < (int) ulAttributeCount; i++) {
5858 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i]));
5859 if (crv != CKR_OK) break;
5861 if (pTemplate[i].type == CKA_KEY_TYPE) {
5862 keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
5863 }
5864 if (pTemplate[i].type == CKA_VALUE_LEN) {
5865 keySize = *(CK_ULONG *)pTemplate[i].pValue;
5866 }
5867 }
5868 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
5870 if (keySize == 0) {
5871 keySize = sftk_MapKeySize(keyType);
5872 }
5874 switch (pMechanism->mechanism) {
5875 case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */
5876 case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */
5877 case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */
5878 case CKM_NSS_JPAKE_ROUND2_SHA512:
5879 extractValue = PR_FALSE;
5880 classType = CKO_PRIVATE_KEY;
5881 break;
5882 case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */
5883 case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
5884 case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
5885 case CKM_NSS_JPAKE_FINAL_SHA512:
5886 extractValue = PR_FALSE;
5887 /* fall through */
5888 default:
5889 classType = CKO_SECRET_KEY;
5890 }
5892 crv = sftk_forceAttribute (key,CKA_CLASS,&classType,sizeof(classType));
5893 if (crv != CKR_OK) {
5894 sftk_FreeObject(key);
5895 return crv;
5896 }
5898 /* look up the base key we're deriving with */
5899 session = sftk_SessionFromHandle(hSession);
5900 if (session == NULL) {
5901 sftk_FreeObject(key);
5902 return CKR_SESSION_HANDLE_INVALID;
5903 }
5905 sourceKey = sftk_ObjectFromHandle(hBaseKey,session);
5906 sftk_FreeSession(session);
5907 if (sourceKey == NULL) {
5908 sftk_FreeObject(key);
5909 return CKR_KEY_HANDLE_INVALID;
5910 }
5912 if (extractValue) {
5913 /* get the value of the base key */
5914 att = sftk_FindAttribute(sourceKey,CKA_VALUE);
5915 if (att == NULL) {
5916 sftk_FreeObject(key);
5917 sftk_FreeObject(sourceKey);
5918 return CKR_KEY_HANDLE_INVALID;
5919 }
5920 }
5922 switch (pMechanism->mechanism) {
5923 /*
5924 * generate the master secret
5925 */
5926 case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256:
5927 case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256:
5928 isSHA256 = PR_TRUE;
5929 /* fall thru */
5930 case CKM_TLS_MASTER_KEY_DERIVE:
5931 case CKM_TLS_MASTER_KEY_DERIVE_DH:
5932 isTLS = PR_TRUE;
5933 /* fall thru */
5934 case CKM_SSL3_MASTER_KEY_DERIVE:
5935 case CKM_SSL3_MASTER_KEY_DERIVE_DH:
5936 {
5937 CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
5938 SSL3RSAPreMasterSecret * rsa_pms;
5939 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
5941 if ((pMechanism->mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) ||
5942 (pMechanism->mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) ||
5943 (pMechanism->mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256))
5944 isDH = PR_TRUE;
5946 /* first do the consistancy checks */
5947 if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
5948 crv = CKR_KEY_TYPE_INCONSISTENT;
5949 break;
5950 }
5951 att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE);
5952 if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
5953 CKK_GENERIC_SECRET)) {
5954 if (att2) sftk_FreeAttribute(att2);
5955 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5956 break;
5957 }
5958 sftk_FreeAttribute(att2);
5959 if (keyType != CKK_GENERIC_SECRET) {
5960 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5961 break;
5962 }
5963 if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
5964 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5965 break;
5966 }
5968 /* finally do the key gen */
5969 ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
5970 pMechanism->pParameter;
5972 PORT_Memcpy(crsrdata,
5973 ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
5974 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
5975 ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
5977 if (ssl3_master->pVersion) {
5978 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
5979 rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue;
5980 /* don't leak more key material then necessary for SSL to work */
5981 if ((sessKey == NULL) || sessKey->wasDerived) {
5982 ssl3_master->pVersion->major = 0xff;
5983 ssl3_master->pVersion->minor = 0xff;
5984 } else {
5985 ssl3_master->pVersion->major = rsa_pms->client_version[0];
5986 ssl3_master->pVersion->minor = rsa_pms->client_version[1];
5987 }
5988 }
5989 if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
5990 crv = CKR_MECHANISM_PARAM_INVALID;
5991 break;
5992 }
5993 if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
5994 crv = CKR_MECHANISM_PARAM_INVALID;
5995 break;
5996 }
5998 if (isTLS) {
5999 SECStatus status;
6000 SECItem crsr = { siBuffer, NULL, 0 };
6001 SECItem master = { siBuffer, NULL, 0 };
6002 SECItem pms = { siBuffer, NULL, 0 };
6004 crsr.data = crsrdata;
6005 crsr.len = sizeof crsrdata;
6006 master.data = key_block;
6007 master.len = SSL3_MASTER_SECRET_LENGTH;
6008 pms.data = (unsigned char*)att->attrib.pValue;
6009 pms.len = att->attrib.ulValueLen;
6011 if (isSHA256) {
6012 status = TLS_P_hash(HASH_AlgSHA256, &pms, "master secret",
6013 &crsr, &master, isFIPS);
6014 } else {
6015 status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS);
6016 }
6017 if (status != SECSuccess) {
6018 crv = CKR_FUNCTION_FAILED;
6019 break;
6020 }
6021 } else {
6022 /* now allocate the hash contexts */
6023 md5 = MD5_NewContext();
6024 if (md5 == NULL) {
6025 crv = CKR_HOST_MEMORY;
6026 break;
6027 }
6028 sha = SHA1_NewContext();
6029 if (sha == NULL) {
6030 PORT_Free(md5);
6031 crv = CKR_HOST_MEMORY;
6032 break;
6033 }
6034 for (i = 0; i < 3; i++) {
6035 SHA1_Begin(sha);
6036 SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));
6037 SHA1_Update(sha, (const unsigned char*)att->attrib.pValue,
6038 att->attrib.ulValueLen);
6039 SHA1_Update(sha, crsrdata, sizeof crsrdata);
6040 SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
6041 PORT_Assert(outLen == SHA1_LENGTH);
6043 MD5_Begin(md5);
6044 MD5_Update(md5, (const unsigned char*)att->attrib.pValue,
6045 att->attrib.ulValueLen);
6046 MD5_Update(md5, sha_out, outLen);
6047 MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);
6048 PORT_Assert(outLen == MD5_LENGTH);
6049 }
6050 PORT_Free(md5);
6051 PORT_Free(sha);
6052 }
6054 /* store the results */
6055 crv = sftk_forceAttribute
6056 (key,CKA_VALUE,key_block,SSL3_MASTER_SECRET_LENGTH);
6057 if (crv != CKR_OK) break;
6058 keyType = CKK_GENERIC_SECRET;
6059 crv = sftk_forceAttribute (key,CKA_KEY_TYPE,&keyType,sizeof(keyType));
6060 if (isTLS) {
6061 /* TLS's master secret is used to "sign" finished msgs with PRF. */
6062 /* XXX This seems like a hack. But SFTK_Derive only accepts
6063 * one "operation" argument. */
6064 crv = sftk_forceAttribute(key,CKA_SIGN, &cktrue,sizeof(CK_BBOOL));
6065 if (crv != CKR_OK) break;
6066 crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
6067 if (crv != CKR_OK) break;
6068 /* While we're here, we might as well force this, too. */
6069 crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
6070 if (crv != CKR_OK) break;
6071 }
6072 break;
6073 }
6075 case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256:
6076 isSHA256 = PR_TRUE;
6077 /* fall thru */
6078 case CKM_TLS_KEY_AND_MAC_DERIVE:
6079 isTLS = PR_TRUE;
6080 /* fall thru */
6081 case CKM_SSL3_KEY_AND_MAC_DERIVE:
6082 {
6083 CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
6084 CK_SSL3_KEY_MAT_OUT * ssl3_keys_out;
6085 CK_ULONG effKeySize;
6086 unsigned int block_needed;
6087 unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
6088 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
6090 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
6091 if (crv != CKR_OK) break;
6093 if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
6094 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
6095 break;
6096 }
6097 att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE);
6098 if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
6099 CKK_GENERIC_SECRET)) {
6100 if (att2) sftk_FreeAttribute(att2);
6101 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
6102 break;
6103 }
6104 sftk_FreeAttribute(att2);
6105 md5 = MD5_NewContext();
6106 if (md5 == NULL) {
6107 crv = CKR_HOST_MEMORY;
6108 break;
6109 }
6110 sha = SHA1_NewContext();
6111 if (sha == NULL) {
6112 PORT_Free(md5);
6113 crv = CKR_HOST_MEMORY;
6114 break;
6115 }
6116 ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter;
6118 PORT_Memcpy(srcrdata,
6119 ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
6120 PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
6121 ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
6123 PORT_Memcpy(crsrdata,
6124 ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
6125 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
6126 ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
6128 /*
6129 * clear out our returned keys so we can recover on failure
6130 */
6131 ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
6132 ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;
6133 ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;
6134 ssl3_keys_out->hClientKey = CK_INVALID_HANDLE;
6135 ssl3_keys_out->hServerKey = CK_INVALID_HANDLE;
6137 /*
6138 * How much key material do we need?
6139 */
6140 macSize = ssl3_keys->ulMacSizeInBits/8;
6141 effKeySize = ssl3_keys->ulKeySizeInBits/8;
6142 IVSize = ssl3_keys->ulIVSizeInBits/8;
6143 if (keySize == 0) {
6144 effKeySize = keySize;
6145 }
6146 block_needed = 2 * (macSize + effKeySize +
6147 ((!ssl3_keys->bIsExport) * IVSize));
6148 PORT_Assert(block_needed <= sizeof key_block);
6149 if (block_needed > sizeof key_block)
6150 block_needed = sizeof key_block;
6152 /*
6153 * generate the key material: This looks amazingly similar to the
6154 * PMS code, and is clearly crying out for a function to provide it.
6155 */
6156 if (isTLS) {
6157 SECStatus status;
6158 SECItem srcr = { siBuffer, NULL, 0 };
6159 SECItem keyblk = { siBuffer, NULL, 0 };
6160 SECItem master = { siBuffer, NULL, 0 };
6162 srcr.data = srcrdata;
6163 srcr.len = sizeof srcrdata;
6164 keyblk.data = key_block;
6165 keyblk.len = block_needed;
6166 master.data = (unsigned char*)att->attrib.pValue;
6167 master.len = att->attrib.ulValueLen;
6169 if (isSHA256) {
6170 status = TLS_P_hash(HASH_AlgSHA256, &master, "key expansion",
6171 &srcr, &keyblk, isFIPS);
6172 } else {
6173 status = TLS_PRF(&master, "key expansion", &srcr, &keyblk,
6174 isFIPS);
6175 }
6176 if (status != SECSuccess) {
6177 goto key_and_mac_derive_fail;
6178 }
6179 } else {
6180 unsigned int block_bytes = 0;
6181 /* key_block =
6182 * MD5(master_secret + SHA('A' + master_secret +
6183 * ServerHello.random + ClientHello.random)) +
6184 * MD5(master_secret + SHA('BB' + master_secret +
6185 * ServerHello.random + ClientHello.random)) +
6186 * MD5(master_secret + SHA('CCC' + master_secret +
6187 * ServerHello.random + ClientHello.random)) +
6188 * [...];
6189 */
6190 for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) {
6191 SHA1_Begin(sha);
6192 SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));
6193 SHA1_Update(sha, (const unsigned char*)att->attrib.pValue,
6194 att->attrib.ulValueLen);
6195 SHA1_Update(sha, srcrdata, sizeof srcrdata);
6196 SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
6197 PORT_Assert(outLen == SHA1_LENGTH);
6198 MD5_Begin(md5);
6199 MD5_Update(md5, (const unsigned char*)att->attrib.pValue,
6200 att->attrib.ulValueLen);
6201 MD5_Update(md5, sha_out, outLen);
6202 MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);
6203 PORT_Assert(outLen == MD5_LENGTH);
6204 block_bytes += outLen;
6205 }
6206 }
6208 /*
6209 * Put the key material where it goes.
6210 */
6211 i = 0; /* now shows how much consumed */
6213 /*
6214 * The key_block is partitioned as follows:
6215 * client_write_MAC_secret[CipherSpec.hash_size]
6216 */
6217 crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,
6218 &ssl3_keys_out->hClientMacSecret);
6219 if (crv != CKR_OK)
6220 goto key_and_mac_derive_fail;
6222 i += macSize;
6224 /*
6225 * server_write_MAC_secret[CipherSpec.hash_size]
6226 */
6227 crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,
6228 &ssl3_keys_out->hServerMacSecret);
6229 if (crv != CKR_OK) {
6230 goto key_and_mac_derive_fail;
6231 }
6232 i += macSize;
6234 if (keySize) {
6235 if (!ssl3_keys->bIsExport) {
6236 /*
6237 ** Generate Domestic write keys and IVs.
6238 ** client_write_key[CipherSpec.key_material]
6239 */
6240 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],
6241 keySize, &ssl3_keys_out->hClientKey);
6242 if (crv != CKR_OK) {
6243 goto key_and_mac_derive_fail;
6244 }
6245 i += keySize;
6247 /*
6248 ** server_write_key[CipherSpec.key_material]
6249 */
6250 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],
6251 keySize, &ssl3_keys_out->hServerKey);
6252 if (crv != CKR_OK) {
6253 goto key_and_mac_derive_fail;
6254 }
6255 i += keySize;
6257 /*
6258 ** client_write_IV[CipherSpec.IV_size]
6259 */
6260 if (IVSize > 0) {
6261 PORT_Memcpy(ssl3_keys_out->pIVClient,
6262 &key_block[i], IVSize);
6263 i += IVSize;
6264 }
6266 /*
6267 ** server_write_IV[CipherSpec.IV_size]
6268 */
6269 if (IVSize > 0) {
6270 PORT_Memcpy(ssl3_keys_out->pIVServer,
6271 &key_block[i], IVSize);
6272 i += IVSize;
6273 }
6274 PORT_Assert(i <= sizeof key_block);
6276 } else if (!isTLS) {
6278 /*
6279 ** Generate SSL3 Export write keys and IVs.
6280 ** client_write_key[CipherSpec.key_material]
6281 ** final_client_write_key = MD5(client_write_key +
6282 ** ClientHello.random + ServerHello.random);
6283 */
6284 MD5_Begin(md5);
6285 MD5_Update(md5, &key_block[i], effKeySize);
6286 MD5_Update(md5, crsrdata, sizeof crsrdata);
6287 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
6288 i += effKeySize;
6289 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2,
6290 keySize,&ssl3_keys_out->hClientKey);
6291 if (crv != CKR_OK) {
6292 goto key_and_mac_derive_fail;
6293 }
6295 /*
6296 ** server_write_key[CipherSpec.key_material]
6297 ** final_server_write_key = MD5(server_write_key +
6298 ** ServerHello.random + ClientHello.random);
6299 */
6300 MD5_Begin(md5);
6301 MD5_Update(md5, &key_block[i], effKeySize);
6302 MD5_Update(md5, srcrdata, sizeof srcrdata);
6303 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
6304 i += effKeySize;
6305 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2,
6306 keySize,&ssl3_keys_out->hServerKey);
6307 if (crv != CKR_OK) {
6308 goto key_and_mac_derive_fail;
6309 }
6311 /*
6312 ** client_write_IV =
6313 ** MD5(ClientHello.random + ServerHello.random);
6314 */
6315 MD5_Begin(md5);
6316 MD5_Update(md5, crsrdata, sizeof crsrdata);
6317 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
6318 PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize);
6320 /*
6321 ** server_write_IV =
6322 ** MD5(ServerHello.random + ClientHello.random);
6323 */
6324 MD5_Begin(md5);
6325 MD5_Update(md5, srcrdata, sizeof srcrdata);
6326 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
6327 PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize);
6329 } else {
6331 /*
6332 ** Generate TLS 1.0 Export write keys and IVs.
6333 */
6334 SECStatus status;
6335 SECItem secret = { siBuffer, NULL, 0 };
6336 SECItem crsr = { siBuffer, NULL, 0 };
6337 SECItem keyblk = { siBuffer, NULL, 0 };
6339 /*
6340 ** client_write_key[CipherSpec.key_material]
6341 ** final_client_write_key = PRF(client_write_key,
6342 ** "client write key",
6343 ** client_random + server_random);
6344 */
6345 secret.data = &key_block[i];
6346 secret.len = effKeySize;
6347 i += effKeySize;
6348 crsr.data = crsrdata;
6349 crsr.len = sizeof crsrdata;
6350 keyblk.data = key_block2;
6351 keyblk.len = sizeof key_block2;
6352 status = TLS_PRF(&secret, "client write key", &crsr, &keyblk,
6353 isFIPS);
6354 if (status != SECSuccess) {
6355 goto key_and_mac_derive_fail;
6356 }
6357 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2,
6358 keySize, &ssl3_keys_out->hClientKey);
6359 if (crv != CKR_OK) {
6360 goto key_and_mac_derive_fail;
6361 }
6363 /*
6364 ** server_write_key[CipherSpec.key_material]
6365 ** final_server_write_key = PRF(server_write_key,
6366 ** "server write key",
6367 ** client_random + server_random);
6368 */
6369 secret.data = &key_block[i];
6370 secret.len = effKeySize;
6371 i += effKeySize;
6372 keyblk.data = key_block2;
6373 keyblk.len = sizeof key_block2;
6374 status = TLS_PRF(&secret, "server write key", &crsr, &keyblk,
6375 isFIPS);
6376 if (status != SECSuccess) {
6377 goto key_and_mac_derive_fail;
6378 }
6379 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2,
6380 keySize, &ssl3_keys_out->hServerKey);
6381 if (crv != CKR_OK) {
6382 goto key_and_mac_derive_fail;
6383 }
6385 /*
6386 ** iv_block = PRF("", "IV block",
6387 ** client_random + server_random);
6388 ** client_write_IV[SecurityParameters.IV_size]
6389 ** server_write_IV[SecurityParameters.IV_size]
6390 */
6391 if (IVSize) {
6392 secret.data = NULL;
6393 secret.len = 0;
6394 keyblk.data = &key_block[i];
6395 keyblk.len = 2 * IVSize;
6396 status = TLS_PRF(&secret, "IV block", &crsr, &keyblk,
6397 isFIPS);
6398 if (status != SECSuccess) {
6399 goto key_and_mac_derive_fail;
6400 }
6401 PORT_Memcpy(ssl3_keys_out->pIVClient, keyblk.data, IVSize);
6402 PORT_Memcpy(ssl3_keys_out->pIVServer, keyblk.data + IVSize,
6403 IVSize);
6404 }
6405 }
6406 }
6408 crv = CKR_OK;
6410 if (0) {
6411 key_and_mac_derive_fail:
6412 if (crv == CKR_OK)
6413 crv = CKR_FUNCTION_FAILED;
6414 sftk_freeSSLKeys(hSession, ssl3_keys_out);
6415 }
6416 MD5_DestroyContext(md5, PR_TRUE);
6417 SHA1_DestroyContext(sha, PR_TRUE);
6418 sftk_FreeObject(key);
6419 key = NULL;
6420 break;
6421 }
6423 case CKM_CONCATENATE_BASE_AND_KEY:
6424 {
6425 SFTKObject *newKey;
6427 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
6428 if (crv != CKR_OK) break;
6430 session = sftk_SessionFromHandle(hSession);
6431 if (session == NULL) {
6432 crv = CKR_SESSION_HANDLE_INVALID;
6433 break;
6434 }
6436 newKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
6437 pMechanism->pParameter,session);
6438 sftk_FreeSession(session);
6439 if ( newKey == NULL) {
6440 crv = CKR_KEY_HANDLE_INVALID;
6441 break;
6442 }
6444 if (sftk_isTrue(newKey,CKA_SENSITIVE)) {
6445 crv = sftk_forceAttribute(newKey,CKA_SENSITIVE,&cktrue,
6446 sizeof(CK_BBOOL));
6447 if (crv != CKR_OK) {
6448 sftk_FreeObject(newKey);
6449 break;
6450 }
6451 }
6453 att2 = sftk_FindAttribute(newKey,CKA_VALUE);
6454 if (att2 == NULL) {
6455 sftk_FreeObject(newKey);
6456 crv = CKR_KEY_HANDLE_INVALID;
6457 break;
6458 }
6459 tmpKeySize = att->attrib.ulValueLen+att2->attrib.ulValueLen;
6460 if (keySize == 0) keySize = tmpKeySize;
6461 if (keySize > tmpKeySize) {
6462 sftk_FreeObject(newKey);
6463 sftk_FreeAttribute(att2);
6464 crv = CKR_TEMPLATE_INCONSISTENT;
6465 break;
6466 }
6467 buf = (unsigned char*)PORT_Alloc(tmpKeySize);
6468 if (buf == NULL) {
6469 sftk_FreeAttribute(att2);
6470 sftk_FreeObject(newKey);
6471 crv = CKR_HOST_MEMORY;
6472 break;
6473 }
6475 PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);
6476 PORT_Memcpy(buf+att->attrib.ulValueLen,
6477 att2->attrib.pValue,att2->attrib.ulValueLen);
6479 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
6480 PORT_ZFree(buf,tmpKeySize);
6481 sftk_FreeAttribute(att2);
6482 sftk_FreeObject(newKey);
6483 break;
6484 }
6486 case CKM_CONCATENATE_BASE_AND_DATA:
6487 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
6488 if (crv != CKR_OK) break;
6490 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;
6491 tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;
6492 if (keySize == 0) keySize = tmpKeySize;
6493 if (keySize > tmpKeySize) {
6494 crv = CKR_TEMPLATE_INCONSISTENT;
6495 break;
6496 }
6497 buf = (unsigned char*)PORT_Alloc(tmpKeySize);
6498 if (buf == NULL) {
6499 crv = CKR_HOST_MEMORY;
6500 break;
6501 }
6503 PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);
6504 PORT_Memcpy(buf+att->attrib.ulValueLen,stringPtr->pData,
6505 stringPtr->ulLen);
6507 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
6508 PORT_ZFree(buf,tmpKeySize);
6509 break;
6510 case CKM_CONCATENATE_DATA_AND_BASE:
6511 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
6512 if (crv != CKR_OK) break;
6514 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
6515 tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;
6516 if (keySize == 0) keySize = tmpKeySize;
6517 if (keySize > tmpKeySize) {
6518 crv = CKR_TEMPLATE_INCONSISTENT;
6519 break;
6520 }
6521 buf = (unsigned char*)PORT_Alloc(tmpKeySize);
6522 if (buf == NULL) {
6523 crv = CKR_HOST_MEMORY;
6524 break;
6525 }
6527 PORT_Memcpy(buf,stringPtr->pData,stringPtr->ulLen);
6528 PORT_Memcpy(buf+stringPtr->ulLen,att->attrib.pValue,
6529 att->attrib.ulValueLen);
6531 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
6532 PORT_ZFree(buf,tmpKeySize);
6533 break;
6534 case CKM_XOR_BASE_AND_DATA:
6535 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
6536 if (crv != CKR_OK) break;
6538 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
6539 tmpKeySize = PR_MIN(att->attrib.ulValueLen,stringPtr->ulLen);
6540 if (keySize == 0) keySize = tmpKeySize;
6541 if (keySize > tmpKeySize) {
6542 crv = CKR_TEMPLATE_INCONSISTENT;
6543 break;
6544 }
6545 buf = (unsigned char*)PORT_Alloc(keySize);
6546 if (buf == NULL) {
6547 crv = CKR_HOST_MEMORY;
6548 break;
6549 }
6552 PORT_Memcpy(buf,att->attrib.pValue,keySize);
6553 for (i=0; i < (int)keySize; i++) {
6554 buf[i] ^= stringPtr->pData[i];
6555 }
6557 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
6558 PORT_ZFree(buf,keySize);
6559 break;
6561 case CKM_EXTRACT_KEY_FROM_KEY:
6562 {
6563 /* the following assumes 8 bits per byte */
6564 CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
6565 CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
6566 CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
6568 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
6569 if (crv != CKR_OK) break;
6571 if (keySize == 0) {
6572 crv = CKR_TEMPLATE_INCOMPLETE;
6573 break;
6574 }
6575 /* make sure we have enough bits in the original key */
6576 if (att->attrib.ulValueLen <
6577 (offset + keySize + ((shift != 0)? 1 :0)) ) {
6578 crv = CKR_MECHANISM_PARAM_INVALID;
6579 break;
6580 }
6581 buf = (unsigned char*)PORT_Alloc(keySize);
6582 if (buf == NULL) {
6583 crv = CKR_HOST_MEMORY;
6584 break;
6585 }
6587 /* copy the bits we need into the new key */
6588 for (i=0; i < (int)keySize; i++) {
6589 unsigned char *value =
6590 ((unsigned char *)att->attrib.pValue)+offset+i;
6591 if (shift) {
6592 buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
6593 } else {
6594 buf[i] = value[0];
6595 }
6596 }
6598 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
6599 PORT_ZFree(buf,keySize);
6600 break;
6601 }
6602 case CKM_MD2_KEY_DERIVATION:
6603 if (keySize == 0) keySize = MD2_LENGTH;
6604 if (keySize > MD2_LENGTH) {
6605 crv = CKR_TEMPLATE_INCONSISTENT;
6606 break;
6607 }
6608 /* now allocate the hash contexts */
6609 md2 = MD2_NewContext();
6610 if (md2 == NULL) {
6611 crv = CKR_HOST_MEMORY;
6612 break;
6613 }
6614 MD2_Begin(md2);
6615 MD2_Update(md2,(const unsigned char*)att->attrib.pValue,
6616 att->attrib.ulValueLen);
6617 MD2_End(md2,key_block,&outLen,MD2_LENGTH);
6618 MD2_DestroyContext(md2, PR_TRUE);
6620 crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize);
6621 break;
6622 case CKM_MD5_KEY_DERIVATION:
6623 if (keySize == 0) keySize = MD5_LENGTH;
6624 if (keySize > MD5_LENGTH) {
6625 crv = CKR_TEMPLATE_INCONSISTENT;
6626 break;
6627 }
6628 MD5_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
6629 att->attrib.ulValueLen);
6631 crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize);
6632 break;
6633 case CKM_SHA1_KEY_DERIVATION:
6634 if (keySize == 0) keySize = SHA1_LENGTH;
6635 if (keySize > SHA1_LENGTH) {
6636 crv = CKR_TEMPLATE_INCONSISTENT;
6637 break;
6638 }
6639 SHA1_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
6640 att->attrib.ulValueLen);
6642 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
6643 break;
6645 case CKM_SHA224_KEY_DERIVATION:
6646 if (keySize == 0) keySize = SHA224_LENGTH;
6647 if (keySize > SHA224_LENGTH) {
6648 crv = CKR_TEMPLATE_INCONSISTENT;
6649 break;
6650 }
6651 SHA224_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
6652 att->attrib.ulValueLen);
6654 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
6655 break;
6657 case CKM_SHA256_KEY_DERIVATION:
6658 if (keySize == 0) keySize = SHA256_LENGTH;
6659 if (keySize > SHA256_LENGTH) {
6660 crv = CKR_TEMPLATE_INCONSISTENT;
6661 break;
6662 }
6663 SHA256_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
6664 att->attrib.ulValueLen);
6666 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
6667 break;
6669 case CKM_SHA384_KEY_DERIVATION:
6670 if (keySize == 0) keySize = SHA384_LENGTH;
6671 if (keySize > SHA384_LENGTH) {
6672 crv = CKR_TEMPLATE_INCONSISTENT;
6673 break;
6674 }
6675 SHA384_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
6676 att->attrib.ulValueLen);
6678 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
6679 break;
6681 case CKM_SHA512_KEY_DERIVATION:
6682 if (keySize == 0) keySize = SHA512_LENGTH;
6683 if (keySize > SHA512_LENGTH) {
6684 crv = CKR_TEMPLATE_INCONSISTENT;
6685 break;
6686 }
6687 SHA512_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
6688 att->attrib.ulValueLen);
6690 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
6691 break;
6693 case CKM_DH_PKCS_DERIVE:
6694 {
6695 SECItem derived, dhPublic;
6696 SECItem dhPrime, dhValue;
6697 /* sourceKey - values for the local existing low key */
6698 /* get prime and value attributes */
6699 crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
6700 if (crv != SECSuccess) break;
6701 crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
6702 if (crv != SECSuccess) {
6703 PORT_Free(dhPrime.data);
6704 break;
6705 }
6707 dhPublic.data = pMechanism->pParameter;
6708 dhPublic.len = pMechanism->ulParameterLen;
6710 /* calculate private value - oct */
6711 rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
6713 PORT_Free(dhPrime.data);
6714 PORT_Free(dhValue.data);
6716 if (rv == SECSuccess) {
6717 sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
6718 PORT_ZFree(derived.data, derived.len);
6719 } else
6720 crv = CKR_HOST_MEMORY;
6722 break;
6723 }
6725 #ifndef NSS_DISABLE_ECC
6726 case CKM_ECDH1_DERIVE:
6727 case CKM_ECDH1_COFACTOR_DERIVE:
6728 {
6729 SECItem ecScalar, ecPoint;
6730 SECItem tmp;
6731 PRBool withCofactor = PR_FALSE;
6732 unsigned char *secret;
6733 unsigned char *keyData = NULL;
6734 int secretlen, curveLen, pubKeyLen;
6735 CK_ECDH1_DERIVE_PARAMS *mechParams;
6736 NSSLOWKEYPrivateKey *privKey;
6737 PLArenaPool *arena = NULL;
6739 /* Check mechanism parameters */
6740 mechParams = (CK_ECDH1_DERIVE_PARAMS *) pMechanism->pParameter;
6741 if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) ||
6742 ((mechParams->kdf == CKD_NULL) &&
6743 ((mechParams->ulSharedDataLen != 0) ||
6744 (mechParams->pSharedData != NULL)))) {
6745 crv = CKR_MECHANISM_PARAM_INVALID;
6746 break;
6747 }
6749 privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv);
6750 if (privKey == NULL) {
6751 break;
6752 }
6754 /* Now we are working with a non-NULL private key */
6755 SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue);
6757 ecPoint.data = mechParams->pPublicData;
6758 ecPoint.len = mechParams->ulPublicDataLen;
6760 curveLen = (privKey->u.ec.ecParams.fieldID.size +7)/8;
6761 pubKeyLen = (2*curveLen) + 1;
6763 /* if the len is too small, can't be a valid point */
6764 if (ecPoint.len < pubKeyLen) {
6765 goto ec_loser;
6766 }
6767 /* if the len is too large, must be an encoded point (length is
6768 * equal case just falls through */
6769 if (ecPoint.len > pubKeyLen) {
6770 SECItem newPoint;
6772 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
6773 if (arena == NULL) {
6774 goto ec_loser;
6775 }
6777 rv = SEC_QuickDERDecodeItem(arena, &newPoint,
6778 SEC_ASN1_GET(SEC_OctetStringTemplate),
6779 &ecPoint);
6780 if (rv != SECSuccess) {
6781 goto ec_loser;
6782 }
6783 ecPoint = newPoint;
6784 }
6786 if (pMechanism->mechanism == CKM_ECDH1_COFACTOR_DERIVE) {
6787 withCofactor = PR_TRUE;
6788 } else {
6789 /* When not using cofactor derivation, one should
6790 * validate the public key to avoid small subgroup
6791 * attacks.
6792 */
6793 if (EC_ValidatePublicKey(&privKey->u.ec.ecParams, &ecPoint)
6794 != SECSuccess) {
6795 goto ec_loser;
6796 }
6797 }
6799 rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
6800 withCofactor, &tmp);
6801 PORT_Free(ecScalar.data);
6802 ecScalar.data = NULL;
6803 if (privKey != sourceKey->objectInfo) {
6804 nsslowkey_DestroyPrivateKey(privKey);
6805 privKey=NULL;
6806 }
6807 if (arena) {
6808 PORT_FreeArena(arena,PR_FALSE);
6809 arena=NULL;
6810 }
6812 if (rv != SECSuccess) {
6813 crv = sftk_MapCryptError(PORT_GetError());
6814 break;
6815 }
6818 /*
6819 * apply the kdf function.
6820 */
6821 if (mechParams->kdf == CKD_NULL) {
6822 /*
6823 * tmp is the raw data created by ECDH_Derive,
6824 * secret and secretlen are the values we will
6825 * eventually pass as our generated key.
6826 */
6827 secret = tmp.data;
6828 secretlen = tmp.len;
6829 } else {
6830 secretlen = keySize;
6831 crv = sftk_ANSI_X9_63_kdf(&secret, keySize,
6832 &tmp, mechParams->pSharedData,
6833 mechParams->ulSharedDataLen, mechParams->kdf);
6834 PORT_ZFree(tmp.data, tmp.len);
6835 if (crv != CKR_OK) {
6836 break;
6837 }
6838 tmp.data = secret;
6839 tmp.len = secretlen;
6840 }
6842 /*
6843 * if keySize is supplied, then we are generating a key of a specific
6844 * length. This is done by taking the least significant 'keySize'
6845 * bytes from the unsigned value calculated by ECDH. Note: this may
6846 * mean padding temp with extra leading zeros from what ECDH_Derive
6847 * already returned (which itself may contain leading zeros).
6848 */
6849 if (keySize) {
6850 if (secretlen < keySize) {
6851 keyData = PORT_ZAlloc(keySize);
6852 if (!keyData) {
6853 PORT_ZFree(tmp.data, tmp.len);
6854 crv = CKR_HOST_MEMORY;
6855 break;
6856 }
6857 PORT_Memcpy(&keyData[keySize-secretlen],secret,secretlen);
6858 secret = keyData;
6859 } else {
6860 secret += (secretlen - keySize);
6861 }
6862 secretlen = keySize;
6863 }
6865 sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
6866 PORT_ZFree(tmp.data, tmp.len);
6867 if (keyData) {
6868 PORT_ZFree(keyData, keySize);
6869 }
6870 break;
6872 ec_loser:
6873 crv = CKR_ARGUMENTS_BAD;
6874 PORT_Free(ecScalar.data);
6875 if (privKey != sourceKey->objectInfo)
6876 nsslowkey_DestroyPrivateKey(privKey);
6877 if (arena) {
6878 PORT_FreeArena(arena, PR_FALSE);
6879 }
6880 break;
6882 }
6883 #endif /* NSS_DISABLE_ECC */
6885 /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */
6886 case CKM_NSS_HKDF_SHA1: hashType = HASH_AlgSHA1; goto hkdf;
6887 case CKM_NSS_HKDF_SHA256: hashType = HASH_AlgSHA256; goto hkdf;
6888 case CKM_NSS_HKDF_SHA384: hashType = HASH_AlgSHA384; goto hkdf;
6889 case CKM_NSS_HKDF_SHA512: hashType = HASH_AlgSHA512; goto hkdf;
6890 hkdf: {
6891 const CK_NSS_HKDFParams * params =
6892 (const CK_NSS_HKDFParams *) pMechanism->pParameter;
6893 const SECHashObject * rawHash;
6894 unsigned hashLen;
6895 CK_BYTE buf[HASH_LENGTH_MAX];
6896 CK_BYTE * prk; /* psuedo-random key */
6897 CK_ULONG prkLen;
6898 CK_BYTE * okm; /* output keying material */
6900 rawHash = HASH_GetRawHashObject(hashType);
6901 if (rawHash == NULL || rawHash->length > sizeof buf) {
6902 crv = CKR_FUNCTION_FAILED;
6903 break;
6904 }
6905 hashLen = rawHash->length;
6907 if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams) ||
6908 !params || (!params->bExpand && !params->bExtract) ||
6909 (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
6910 (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
6911 crv = CKR_MECHANISM_PARAM_INVALID;
6912 break;
6913 }
6914 if (keySize == 0 || keySize > sizeof key_block ||
6915 (!params->bExpand && keySize > hashLen) ||
6916 (params->bExpand && keySize > 255 * hashLen)) {
6917 crv = CKR_TEMPLATE_INCONSISTENT;
6918 break;
6919 }
6920 crv = sftk_DeriveSensitiveCheck(sourceKey, key);
6921 if (crv != CKR_OK)
6922 break;
6924 /* HKDF-Extract(salt, base key value) */
6925 if (params->bExtract) {
6926 CK_BYTE * salt;
6927 CK_ULONG saltLen;
6928 HMACContext * hmac;
6929 unsigned int bufLen;
6931 salt = params->pSalt;
6932 saltLen = params->ulSaltLen;
6933 if (salt == NULL) {
6934 saltLen = hashLen;
6935 salt = buf;
6936 memset(salt, 0, saltLen);
6937 }
6938 hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
6939 if (!hmac) {
6940 crv = CKR_HOST_MEMORY;
6941 break;
6942 }
6943 HMAC_Begin(hmac);
6944 HMAC_Update(hmac, (const unsigned char*) att->attrib.pValue,
6945 att->attrib.ulValueLen);
6946 HMAC_Finish(hmac, buf, &bufLen, sizeof(buf));
6947 HMAC_Destroy(hmac, PR_TRUE);
6948 PORT_Assert(bufLen == rawHash->length);
6949 prk = buf;
6950 prkLen = bufLen;
6951 } else {
6952 /* PRK = base key value */
6953 prk = (CK_BYTE*) att->attrib.pValue;
6954 prkLen = att->attrib.ulValueLen;
6955 }
6957 /* HKDF-Expand */
6958 if (!params->bExpand) {
6959 okm = prk;
6960 } else {
6961 /* T(1) = HMAC-Hash(prk, "" | info | 0x01)
6962 * T(n) = HMAC-Hash(prk, T(n-1) | info | n
6963 * key material = T(1) | ... | T(n)
6964 */
6965 HMACContext * hmac;
6966 CK_BYTE i;
6967 unsigned iterations = PR_ROUNDUP(keySize, hashLen) / hashLen;
6968 hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
6969 if (hmac == NULL) {
6970 crv = CKR_HOST_MEMORY;
6971 break;
6972 }
6973 for (i = 1; i <= iterations; ++i) {
6974 unsigned len;
6975 HMAC_Begin(hmac);
6976 if (i > 1) {
6977 HMAC_Update(hmac, key_block + ((i-2) * hashLen), hashLen);
6978 }
6979 if (params->ulInfoLen != 0) {
6980 HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
6981 }
6982 HMAC_Update(hmac, &i, 1);
6983 HMAC_Finish(hmac, key_block + ((i-1) * hashLen), &len,
6984 hashLen);
6985 PORT_Assert(len == hashLen);
6986 }
6987 HMAC_Destroy(hmac, PR_TRUE);
6988 okm = key_block;
6989 }
6990 /* key material = prk */
6991 crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
6992 break;
6993 } /* end of CKM_NSS_HKDF_* */
6995 case CKM_NSS_JPAKE_ROUND2_SHA1: hashType = HASH_AlgSHA1; goto jpake2;
6996 case CKM_NSS_JPAKE_ROUND2_SHA256: hashType = HASH_AlgSHA256; goto jpake2;
6997 case CKM_NSS_JPAKE_ROUND2_SHA384: hashType = HASH_AlgSHA384; goto jpake2;
6998 case CKM_NSS_JPAKE_ROUND2_SHA512: hashType = HASH_AlgSHA512; goto jpake2;
6999 jpake2:
7000 if (pMechanism->pParameter == NULL ||
7001 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params))
7002 crv = CKR_MECHANISM_PARAM_INVALID;
7003 if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN))
7004 crv = CKR_TEMPLATE_INCONSISTENT;
7005 if (crv == CKR_OK)
7006 crv = sftk_DeriveSensitiveCheck(sourceKey, key);
7007 if (crv == CKR_OK)
7008 crv = jpake_Round2(hashType,
7009 (CK_NSS_JPAKERound2Params *) pMechanism->pParameter,
7010 sourceKey, key);
7011 break;
7013 case CKM_NSS_JPAKE_FINAL_SHA1: hashType = HASH_AlgSHA1; goto jpakeFinal;
7014 case CKM_NSS_JPAKE_FINAL_SHA256: hashType = HASH_AlgSHA256; goto jpakeFinal;
7015 case CKM_NSS_JPAKE_FINAL_SHA384: hashType = HASH_AlgSHA384; goto jpakeFinal;
7016 case CKM_NSS_JPAKE_FINAL_SHA512: hashType = HASH_AlgSHA512; goto jpakeFinal;
7017 jpakeFinal:
7018 if (pMechanism->pParameter == NULL ||
7019 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams))
7020 crv = CKR_MECHANISM_PARAM_INVALID;
7021 /* We purposely do not do the derive sensitivity check; we want to be
7022 able to derive non-sensitive keys while allowing the ROUND1 and
7023 ROUND2 keys to be sensitive (which they always are, since they are
7024 in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE
7025 in the template in order for the resultant keyblock key to be
7026 sensitive.
7027 */
7028 if (crv == CKR_OK)
7029 crv = jpake_Final(hashType,
7030 (CK_NSS_JPAKEFinalParams *) pMechanism->pParameter,
7031 sourceKey, key);
7032 break;
7034 default:
7035 crv = CKR_MECHANISM_INVALID;
7036 }
7037 if (att) {
7038 sftk_FreeAttribute(att);
7039 }
7040 sftk_FreeObject(sourceKey);
7041 if (crv != CKR_OK) {
7042 if (key) sftk_FreeObject(key);
7043 return crv;
7044 }
7046 /* link the key object into the list */
7047 if (key) {
7048 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
7049 PORT_Assert(sessKey);
7050 /* get the session */
7051 sessKey->wasDerived = PR_TRUE;
7052 session = sftk_SessionFromHandle(hSession);
7053 if (session == NULL) {
7054 sftk_FreeObject(key);
7055 return CKR_HOST_MEMORY;
7056 }
7058 crv = sftk_handleObject(key,session);
7059 sftk_FreeSession(session);
7060 *phKey = key->handle;
7061 sftk_FreeObject(key);
7062 }
7063 return crv;
7064 }
7067 /* NSC_GetFunctionStatus obtains an updated status of a function running
7068 * in parallel with an application. */
7069 CK_RV NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
7070 {
7071 CHECK_FORK();
7073 return CKR_FUNCTION_NOT_PARALLEL;
7074 }
7076 /* NSC_CancelFunction cancels a function running in parallel */
7077 CK_RV NSC_CancelFunction(CK_SESSION_HANDLE hSession)
7078 {
7079 CHECK_FORK();
7081 return CKR_FUNCTION_NOT_PARALLEL;
7082 }
7084 /* NSC_GetOperationState saves the state of the cryptographic
7085 *operation in a session.
7086 * NOTE: This code only works for digest functions for now. eventually need
7087 * to add full flatten/resurect to our state stuff so that all types of state
7088 * can be saved */
7089 CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession,
7090 CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
7091 {
7092 SFTKSessionContext *context;
7093 SFTKSession *session;
7094 CK_RV crv;
7095 CK_ULONG pOSLen = *pulOperationStateLen;
7097 CHECK_FORK();
7099 /* make sure we're legal */
7100 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
7101 if (crv != CKR_OK) return crv;
7103 *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE)
7104 + sizeof(SFTKContextType);
7105 if (pOperationState == NULL) {
7106 sftk_FreeSession(session);
7107 return CKR_OK;
7108 } else {
7109 if (pOSLen < *pulOperationStateLen) {
7110 return CKR_BUFFER_TOO_SMALL;
7111 }
7112 }
7113 PORT_Memcpy(pOperationState,&context->type,sizeof(SFTKContextType));
7114 pOperationState += sizeof(SFTKContextType);
7115 PORT_Memcpy(pOperationState,&context->currentMech,
7116 sizeof(CK_MECHANISM_TYPE));
7117 pOperationState += sizeof(CK_MECHANISM_TYPE);
7118 PORT_Memcpy(pOperationState,context->cipherInfo,context->cipherInfoLen);
7119 sftk_FreeSession(session);
7120 return CKR_OK;
7121 }
7124 #define sftk_Decrement(stateSize,len) \
7125 stateSize = ((stateSize) > (CK_ULONG)(len)) ? \
7126 ((stateSize) - (CK_ULONG)(len)) : 0;
7128 /* NSC_SetOperationState restores the state of the cryptographic
7129 * operation in a session. This is coded like it can restore lots of
7130 * states, but it only works for truly flat cipher structures. */
7131 CK_RV NSC_SetOperationState(CK_SESSION_HANDLE hSession,
7132 CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
7133 CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
7134 {
7135 SFTKSessionContext *context;
7136 SFTKSession *session;
7137 SFTKContextType type;
7138 CK_MECHANISM mech;
7139 CK_RV crv = CKR_OK;
7141 CHECK_FORK();
7143 while (ulOperationStateLen != 0) {
7144 /* get what type of state we're dealing with... */
7145 PORT_Memcpy(&type,pOperationState, sizeof(SFTKContextType));
7147 /* fix up session contexts based on type */
7148 session = sftk_SessionFromHandle(hSession);
7149 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7150 context = sftk_ReturnContextByType(session, type);
7151 sftk_SetContextByType(session, type, NULL);
7152 if (context) {
7153 sftk_FreeContext(context);
7154 }
7155 pOperationState += sizeof(SFTKContextType);
7156 sftk_Decrement(ulOperationStateLen,sizeof(SFTKContextType));
7159 /* get the mechanism structure */
7160 PORT_Memcpy(&mech.mechanism,pOperationState,sizeof(CK_MECHANISM_TYPE));
7161 pOperationState += sizeof(CK_MECHANISM_TYPE);
7162 sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
7163 /* should be filled in... but not necessary for hash */
7164 mech.pParameter = NULL;
7165 mech.ulParameterLen = 0;
7166 switch (type) {
7167 case SFTK_HASH:
7168 crv = NSC_DigestInit(hSession,&mech);
7169 if (crv != CKR_OK) break;
7170 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE,
7171 NULL);
7172 if (crv != CKR_OK) break;
7173 PORT_Memcpy(context->cipherInfo,pOperationState,
7174 context->cipherInfoLen);
7175 pOperationState += context->cipherInfoLen;
7176 sftk_Decrement(ulOperationStateLen,context->cipherInfoLen);
7177 break;
7178 default:
7179 /* do sign/encrypt/decrypt later */
7180 crv = CKR_SAVED_STATE_INVALID;
7181 }
7182 sftk_FreeSession(session);
7183 if (crv != CKR_OK) break;
7184 }
7185 return crv;
7186 }
7188 /* Dual-function cryptographic operations */
7190 /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
7191 * operation. */
7192 CK_RV NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
7193 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
7194 CK_ULONG_PTR pulEncryptedPartLen)
7195 {
7196 CK_RV crv;
7198 CHECK_FORK();
7200 crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart,
7201 pulEncryptedPartLen);
7202 if (crv != CKR_OK) return crv;
7203 crv = NSC_DigestUpdate(hSession,pPart,ulPartLen);
7205 return crv;
7206 }
7209 /* NSC_DecryptDigestUpdate continues a multiple-part decryption and
7210 * digesting operation. */
7211 CK_RV NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
7212 CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
7213 CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
7214 {
7215 CK_RV crv;
7217 CHECK_FORK();
7219 crv = NSC_DecryptUpdate(hSession,pEncryptedPart, ulEncryptedPartLen,
7220 pPart, pulPartLen);
7221 if (crv != CKR_OK) return crv;
7222 crv = NSC_DigestUpdate(hSession,pPart,*pulPartLen);
7224 return crv;
7225 }
7228 /* NSC_SignEncryptUpdate continues a multiple-part signing and
7229 * encryption operation. */
7230 CK_RV NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
7231 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
7232 CK_ULONG_PTR pulEncryptedPartLen)
7233 {
7234 CK_RV crv;
7236 CHECK_FORK();
7238 crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart,
7239 pulEncryptedPartLen);
7240 if (crv != CKR_OK) return crv;
7241 crv = NSC_SignUpdate(hSession,pPart,ulPartLen);
7243 return crv;
7244 }
7247 /* NSC_DecryptVerifyUpdate continues a multiple-part decryption
7248 * and verify operation. */
7249 CK_RV NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
7250 CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
7251 CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
7252 {
7253 CK_RV crv;
7255 CHECK_FORK();
7257 crv = NSC_DecryptUpdate(hSession,pEncryptedData, ulEncryptedDataLen,
7258 pData, pulDataLen);
7259 if (crv != CKR_OK) return crv;
7260 crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
7262 return crv;
7263 }
7265 /* NSC_DigestKey continues a multi-part message-digesting operation,
7266 * by digesting the value of a secret key as part of the data already digested.
7267 */
7268 CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
7269 {
7270 SFTKSession *session = NULL;
7271 SFTKObject *key = NULL;
7272 SFTKAttribute *att;
7273 CK_RV crv;
7275 CHECK_FORK();
7277 session = sftk_SessionFromHandle(hSession);
7278 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7280 key = sftk_ObjectFromHandle(hKey,session);
7281 sftk_FreeSession(session);
7282 if (key == NULL) return CKR_KEY_HANDLE_INVALID;
7284 /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
7286 /* make sure it's a valid key for this operation */
7287 if (key->objclass != CKO_SECRET_KEY) {
7288 sftk_FreeObject(key);
7289 return CKR_KEY_TYPE_INCONSISTENT;
7290 }
7291 /* get the key value */
7292 att = sftk_FindAttribute(key,CKA_VALUE);
7293 sftk_FreeObject(key);
7294 if (!att) {
7295 return CKR_KEY_HANDLE_INVALID;
7296 }
7297 crv = NSC_DigestUpdate(hSession,(CK_BYTE_PTR)att->attrib.pValue,
7298 att->attrib.ulValueLen);
7299 sftk_FreeAttribute(att);
7300 return crv;
7301 }