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

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

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

Powered by Google App Engine
This is Rietveld 408576698