Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: nss/lib/softoken/pkcs11c.c

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

Powered by Google App Engine
This is Rietveld 408576698