comparison nss/lib/softoken/pkcs11c.c @ 0:1e5118fa0cb1

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