Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / security / nss / lib / softoken / pkcs11c.c
blob76d648f95d6b3bc1c2951ec2aa7c5e5c645dc31b
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Dr Stephen Henson <stephen.henson@gemplus.com>
23 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 * This file implements PKCS 11 on top of our existing security modules
41 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
42 * This implementation has two slots:
43 * slot 1 is our generic crypto support. It does not require login.
44 * It supports Public Key ops, and all they bulk ciphers and hashes.
45 * It can also support Private Key ops for imported Private keys. It does
46 * not have any token storage.
47 * slot 2 is our private key support. It requires a login before use. It
48 * can store Private Keys and Certs as token objects. Currently only private
49 * keys and their associated Certificates are saved on the token.
51 * In this implementation, session objects are only visible to the session
52 * that created or generated them.
54 #include "seccomon.h"
55 #include "secitem.h"
56 #include "secport.h"
57 #include "blapi.h"
58 #include "pkcs11.h"
59 #include "pkcs11i.h"
60 #include "lowkeyi.h"
61 #include "sechash.h"
62 #include "secder.h"
63 #include "secdig.h"
64 #include "lowpbe.h" /* We do PBE below */
65 #include "pkcs11t.h"
66 #include "secoid.h"
67 #include "alghmac.h"
68 #include "softoken.h"
69 #include "secasn1.h"
70 #include "secerr.h"
72 #include "prprf.h"
74 #define __PASTE(x,y) x##y
77 * we renamed all our internal functions, get the correct
78 * definitions for them...
79 */
80 #undef CK_PKCS11_FUNCTION_INFO
81 #undef CK_NEED_ARG_LIST
83 #define CK_EXTERN extern
84 #define CK_PKCS11_FUNCTION_INFO(func) \
85 CK_RV __PASTE(NS,func)
86 #define CK_NEED_ARG_LIST 1
88 #include "pkcs11f.h"
90 typedef struct {
91 uint8 client_version[2];
92 uint8 random[46];
93 } SSL3RSAPreMasterSecret;
95 static void sftk_Null(void *data, PRBool freeit)
97 return;
100 #ifdef NSS_ENABLE_ECC
101 #ifdef EC_DEBUG
102 #define SEC_PRINT(str1, str2, num, sitem) \
103 printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
104 str1, str2, num, sitem->len); \
105 for (i = 0; i < sitem->len; i++) { \
106 printf("%02x:", sitem->data[i]); \
108 printf("\n")
109 #else
110 #define SEC_PRINT(a, b, c, d)
111 #endif
112 #endif /* NSS_ENABLE_ECC */
115 * free routines.... Free local type allocated data, and convert
116 * other free routines to the destroy signature.
118 static void
119 sftk_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit)
121 nsslowkey_DestroyPrivateKey(key);
124 static void
125 sftk_Space(void *data, PRBool freeit)
127 PORT_Free(data);
132 * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
133 * Deprecating a full des key to 40 bit key strenth.
135 static CK_RV
136 sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
138 unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
139 unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
140 unsigned char enc_src[8];
141 unsigned char enc_dest[8];
142 unsigned int leng,i;
143 DESContext *descx;
144 SECStatus rv;
147 /* zero the parity bits */
148 for (i=0; i < 8; i++) {
149 enc_src[i] = cdmfkey[i] & 0xfe;
152 /* encrypt with key 1 */
153 descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);
154 if (descx == NULL) return CKR_HOST_MEMORY;
155 rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);
156 DES_DestroyContext(descx,PR_TRUE);
157 if (rv != SECSuccess) return CKR_DEVICE_ERROR;
159 /* xor source with des, zero the parity bits and deprecate the key*/
160 for (i=0; i < 8; i++) {
161 if (i & 1) {
162 enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;
163 } else {
164 enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;
168 /* encrypt with key 2 */
169 descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);
170 if (descx == NULL) return CKR_HOST_MEMORY;
171 rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);
172 DES_DestroyContext(descx,PR_TRUE);
173 if (rv != SECSuccess) return CKR_DEVICE_ERROR;
175 /* set the corret parity on our new des key */
176 sftk_FormatDESKey(deskey, 8);
177 return CKR_OK;
181 /* NSC_DestroyObject destroys an object. */
182 CK_RV
183 NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
185 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
186 SFTKSession *session;
187 SFTKObject *object;
188 SFTKFreeStatus status;
190 CHECK_FORK();
192 if (slot == NULL) {
193 return CKR_SESSION_HANDLE_INVALID;
196 * This whole block just makes sure we really can destroy the
197 * requested object.
199 session = sftk_SessionFromHandle(hSession);
200 if (session == NULL) {
201 return CKR_SESSION_HANDLE_INVALID;
204 object = sftk_ObjectFromHandle(hObject,session);
205 if (object == NULL) {
206 sftk_FreeSession(session);
207 return CKR_OBJECT_HANDLE_INVALID;
210 /* don't destroy a private object if we aren't logged in */
211 if ((!slot->isLoggedIn) && (slot->needLogin) &&
212 (sftk_isTrue(object,CKA_PRIVATE))) {
213 sftk_FreeSession(session);
214 sftk_FreeObject(object);
215 return CKR_USER_NOT_LOGGED_IN;
218 /* don't destroy a token object if we aren't in a rw session */
220 if (((session->info.flags & CKF_RW_SESSION) == 0) &&
221 (sftk_isTrue(object,CKA_TOKEN))) {
222 sftk_FreeSession(session);
223 sftk_FreeObject(object);
224 return CKR_SESSION_READ_ONLY;
227 sftk_DeleteObject(session,object);
229 sftk_FreeSession(session);
232 * get some indication if the object is destroyed. Note: this is not
233 * 100%. Someone may have an object reference outstanding (though that
234 * should not be the case by here. Also note that the object is "half"
235 * destroyed. Our internal representation is destroyed, but it may still
236 * be in the data base.
238 status = sftk_FreeObject(object);
240 return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
245 ************** Crypto Functions: Utilities ************************
250 * map SEC_ERROR_xxx to CKR_xxx.
252 static CK_RV
253 sftk_MapCryptError(int error)
255 switch (error) {
256 case SEC_ERROR_INVALID_ARGS:
257 return CKR_ARGUMENTS_BAD;
258 case SEC_ERROR_INPUT_LEN:
259 return CKR_DATA_LEN_RANGE;
260 case SEC_ERROR_OUTPUT_LEN:
261 return CKR_BUFFER_TOO_SMALL;
263 return CKR_DEVICE_ERROR;
267 * return a context based on the SFTKContext type.
269 SFTKSessionContext *
270 sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
272 switch (type) {
273 case SFTK_ENCRYPT:
274 case SFTK_DECRYPT:
275 return session->enc_context;
276 case SFTK_HASH:
277 return session->hash_context;
278 case SFTK_SIGN:
279 case SFTK_SIGN_RECOVER:
280 case SFTK_VERIFY:
281 case SFTK_VERIFY_RECOVER:
282 return session->hash_context;
284 return NULL;
288 * change a context based on the SFTKContext type.
290 void
291 sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
292 SFTKSessionContext *context)
294 switch (type) {
295 case SFTK_ENCRYPT:
296 case SFTK_DECRYPT:
297 session->enc_context = context;
298 break;
299 case SFTK_HASH:
300 session->hash_context = context;
301 break;
302 case SFTK_SIGN:
303 case SFTK_SIGN_RECOVER:
304 case SFTK_VERIFY:
305 case SFTK_VERIFY_RECOVER:
306 session->hash_context = context;
307 break;
309 return;
313 * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
314 * and C_XXX function. The function takes a session handle, the context type,
315 * and wether or not the session needs to be multipart. It returns the context,
316 * and optionally returns the session pointer (if sessionPtr != NULL) if session
317 * pointer is returned, the caller is responsible for freeing it.
319 static CK_RV
320 sftk_GetContext(CK_SESSION_HANDLE handle,SFTKSessionContext **contextPtr,
321 SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr)
323 SFTKSession *session;
324 SFTKSessionContext *context;
326 session = sftk_SessionFromHandle(handle);
327 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
328 context = sftk_ReturnContextByType(session,type);
329 /* make sure the context is valid */
330 if((context==NULL)||(context->type!=type)||(needMulti&&!(context->multi))){
331 sftk_FreeSession(session);
332 return CKR_OPERATION_NOT_INITIALIZED;
334 *contextPtr = context;
335 if (sessionPtr != NULL) {
336 *sessionPtr = session;
337 } else {
338 sftk_FreeSession(session);
340 return CKR_OK;
344 ************** Crypto Functions: Encrypt ************************
348 * All the NSC_InitXXX functions have a set of common checks and processing they
349 * all need to do at the beginning. This is done here.
351 static CK_RV
352 sftk_InitGeneric(SFTKSession *session,SFTKSessionContext **contextPtr,
353 SFTKContextType ctype,SFTKObject **keyPtr,
354 CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
355 CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation)
357 SFTKObject *key = NULL;
358 SFTKAttribute *att;
359 SFTKSessionContext *context;
361 /* We can only init if there is not current context active */
362 if (sftk_ReturnContextByType(session,ctype) != NULL) {
363 return CKR_OPERATION_ACTIVE;
366 /* find the key */
367 if (keyPtr) {
368 key = sftk_ObjectFromHandle(hKey,session);
369 if (key == NULL) {
370 return CKR_KEY_HANDLE_INVALID;
373 /* make sure it's a valid key for this operation */
374 if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType))
375 || !sftk_isTrue(key,operation)) {
376 sftk_FreeObject(key);
377 return CKR_KEY_TYPE_INCONSISTENT;
379 /* get the key type */
380 att = sftk_FindAttribute(key,CKA_KEY_TYPE);
381 if (att == NULL) {
382 sftk_FreeObject(key);
383 return CKR_KEY_TYPE_INCONSISTENT;
385 PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE));
386 if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) {
387 sftk_FreeAttribute(att);
388 sftk_FreeObject(key);
389 return CKR_ATTRIBUTE_VALUE_INVALID;
391 PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE));
392 sftk_FreeAttribute(att);
393 *keyPtr = key;
396 /* allocate the context structure */
397 context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext));
398 if (context == NULL) {
399 if (key) sftk_FreeObject(key);
400 return CKR_HOST_MEMORY;
402 context->type = ctype;
403 context->multi = PR_TRUE;
404 context->cipherInfo = NULL;
405 context->hashInfo = NULL;
406 context->doPad = PR_FALSE;
407 context->padDataLength = 0;
408 context->key = key;
409 context->blockSize = 0;
411 *contextPtr = context;
412 return CKR_OK;
415 /* NSC_CryptInit initializes an encryption/Decryption operation. */
416 /* This function is used by NSC_EncryptInit, NSC_DecryptInit,
417 * NSC_WrapKey, NSC_UnwrapKey,
418 * NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac),
419 * The only difference in their uses is the value of etype.
421 static CK_RV
422 sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
423 CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype,
424 SFTKContextType contextType, PRBool isEncrypt)
426 SFTKSession *session;
427 SFTKObject *key;
428 SFTKSessionContext *context;
429 SFTKAttribute *att;
430 CK_RC2_CBC_PARAMS *rc2_param;
431 #if NSS_SOFTOKEN_DOES_RC5
432 CK_RC5_CBC_PARAMS *rc5_param;
433 SECItem rc5Key;
434 #endif
435 CK_KEY_TYPE key_type;
436 CK_RV crv = CKR_OK;
437 unsigned effectiveKeyLength;
438 unsigned char newdeskey[24];
439 PRBool useNewKey=PR_FALSE;
440 int t;
442 crv = sftk_MechAllowsOperation(pMechanism->mechanism, etype);
443 if (crv != CKR_OK)
444 return crv;
446 session = sftk_SessionFromHandle(hSession);
447 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
449 crv = sftk_InitGeneric(session,&context,contextType,&key,hKey,&key_type,
450 isEncrypt ?CKO_PUBLIC_KEY:CKO_PRIVATE_KEY, etype);
452 if (crv != CKR_OK) {
453 sftk_FreeSession(session);
454 return crv;
457 context->doPad = PR_FALSE;
458 switch(pMechanism->mechanism) {
459 case CKM_RSA_PKCS:
460 case CKM_RSA_X_509:
461 if (key_type != CKK_RSA) {
462 crv = CKR_KEY_TYPE_INCONSISTENT;
463 break;
465 context->multi = PR_FALSE;
466 if (isEncrypt) {
467 NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key,CKK_RSA,&crv);
468 if (pubKey == NULL) {
469 break;
471 context->maxLen = nsslowkey_PublicModulusLen(pubKey);
472 context->cipherInfo = (void *)pubKey;
473 context->update = (SFTKCipher)
474 (pMechanism->mechanism == CKM_RSA_X_509
475 ? RSA_EncryptRaw : RSA_EncryptBlock);
476 } else {
477 NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key,CKK_RSA,&crv);
478 if (privKey == NULL) {
479 break;
481 context->maxLen = nsslowkey_PrivateModulusLen(privKey);
482 context->cipherInfo = (void *)privKey;
483 context->update = (SFTKCipher)
484 (pMechanism->mechanism == CKM_RSA_X_509
485 ? RSA_DecryptRaw : RSA_DecryptBlock);
487 context->destroy = sftk_Null;
488 break;
489 case CKM_RC2_CBC_PAD:
490 context->doPad = PR_TRUE;
491 /* fall thru */
492 case CKM_RC2_ECB:
493 case CKM_RC2_CBC:
494 context->blockSize = 8;
495 if (key_type != CKK_RC2) {
496 crv = CKR_KEY_TYPE_INCONSISTENT;
497 break;
499 att = sftk_FindAttribute(key,CKA_VALUE);
500 if (att == NULL) {
501 crv = CKR_KEY_HANDLE_INVALID;
502 break;
504 rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
505 effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8;
506 context->cipherInfo =
507 RC2_CreateContext((unsigned char*)att->attrib.pValue,
508 att->attrib.ulValueLen, rc2_param->iv,
509 pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 :
510 NSS_RC2_CBC,effectiveKeyLength);
511 sftk_FreeAttribute(att);
512 if (context->cipherInfo == NULL) {
513 crv = CKR_HOST_MEMORY;
514 break;
516 context->update = (SFTKCipher) (isEncrypt ? RC2_Encrypt : RC2_Decrypt);
517 context->destroy = (SFTKDestroy) RC2_DestroyContext;
518 break;
519 #if NSS_SOFTOKEN_DOES_RC5
520 case CKM_RC5_CBC_PAD:
521 context->doPad = PR_TRUE;
522 /* fall thru */
523 case CKM_RC5_ECB:
524 case CKM_RC5_CBC:
525 if (key_type != CKK_RC5) {
526 crv = CKR_KEY_TYPE_INCONSISTENT;
527 break;
529 att = sftk_FindAttribute(key,CKA_VALUE);
530 if (att == NULL) {
531 crv = CKR_KEY_HANDLE_INVALID;
532 break;
534 rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
535 context->blockSize = rc5_param->ulWordsize*2;
536 rc5Key.data = (unsigned char*)att->attrib.pValue;
537 rc5Key.len = att->attrib.ulValueLen;
538 context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds,
539 rc5_param->ulWordsize,rc5_param->pIv,
540 pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
541 sftk_FreeAttribute(att);
542 if (context->cipherInfo == NULL) {
543 crv = CKR_HOST_MEMORY;
544 break;
546 context->update = (SFTKCipher) (isEncrypt ? RC5_Encrypt : RC5_Decrypt);
547 context->destroy = (SFTKDestroy) RC5_DestroyContext;
548 break;
549 #endif
550 case CKM_RC4:
551 if (key_type != CKK_RC4) {
552 crv = CKR_KEY_TYPE_INCONSISTENT;
553 break;
555 att = sftk_FindAttribute(key,CKA_VALUE);
556 if (att == NULL) {
557 crv = CKR_KEY_HANDLE_INVALID;
558 break;
560 context->cipherInfo =
561 RC4_CreateContext((unsigned char*)att->attrib.pValue,
562 att->attrib.ulValueLen);
563 sftk_FreeAttribute(att);
564 if (context->cipherInfo == NULL) {
565 crv = CKR_HOST_MEMORY; /* WRONG !!! */
566 break;
568 context->update = (SFTKCipher) (isEncrypt ? RC4_Encrypt : RC4_Decrypt);
569 context->destroy = (SFTKDestroy) RC4_DestroyContext;
570 break;
571 case CKM_CDMF_CBC_PAD:
572 context->doPad = PR_TRUE;
573 /* fall thru */
574 case CKM_CDMF_ECB:
575 case CKM_CDMF_CBC:
576 if (key_type != CKK_CDMF) {
577 crv = CKR_KEY_TYPE_INCONSISTENT;
578 break;
580 t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
581 if (crv != CKR_OK) break;
582 goto finish_des;
583 case CKM_DES_ECB:
584 if (key_type != CKK_DES) {
585 crv = CKR_KEY_TYPE_INCONSISTENT;
586 break;
588 t = NSS_DES;
589 goto finish_des;
590 case CKM_DES_CBC_PAD:
591 context->doPad = PR_TRUE;
592 /* fall thru */
593 case CKM_DES_CBC:
594 if (key_type != CKK_DES) {
595 crv = CKR_KEY_TYPE_INCONSISTENT;
596 break;
598 t = NSS_DES_CBC;
599 goto finish_des;
600 case CKM_DES3_ECB:
601 if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
602 crv = CKR_KEY_TYPE_INCONSISTENT;
603 break;
605 t = NSS_DES_EDE3;
606 goto finish_des;
607 case CKM_DES3_CBC_PAD:
608 context->doPad = PR_TRUE;
609 /* fall thru */
610 case CKM_DES3_CBC:
611 if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
612 crv = CKR_KEY_TYPE_INCONSISTENT;
613 break;
615 t = NSS_DES_EDE3_CBC;
616 finish_des:
617 context->blockSize = 8;
618 att = sftk_FindAttribute(key,CKA_VALUE);
619 if (att == NULL) {
620 crv = CKR_KEY_HANDLE_INVALID;
621 break;
623 if (key_type == CKK_DES2 &&
624 (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) {
625 /* extend DES2 key to DES3 key. */
626 memcpy(newdeskey, att->attrib.pValue, 16);
627 memcpy(newdeskey + 16, newdeskey, 8);
628 useNewKey=PR_TRUE;
629 } else if (key_type == CKK_CDMF) {
630 crv = sftk_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey);
631 if (crv != CKR_OK) {
632 sftk_FreeAttribute(att);
633 break;
635 useNewKey=PR_TRUE;
637 context->cipherInfo = DES_CreateContext(
638 useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue,
639 (unsigned char*)pMechanism->pParameter,t, isEncrypt);
640 if (useNewKey)
641 memset(newdeskey, 0, sizeof newdeskey);
642 sftk_FreeAttribute(att);
643 if (context->cipherInfo == NULL) {
644 crv = CKR_HOST_MEMORY;
645 break;
647 context->update = (SFTKCipher) (isEncrypt ? DES_Encrypt : DES_Decrypt);
648 context->destroy = (SFTKDestroy) DES_DestroyContext;
649 break;
651 case CKM_CAMELLIA_CBC_PAD:
652 context->doPad = PR_TRUE;
653 /* fall thru */
654 case CKM_CAMELLIA_CBC:
655 if (!pMechanism->pParameter ||
656 pMechanism->ulParameterLen != 16) {
657 crv = CKR_MECHANISM_PARAM_INVALID;
658 break;
660 /* fall thru */
661 case CKM_CAMELLIA_ECB:
662 context->blockSize = 16;
663 if (key_type != CKK_CAMELLIA) {
664 crv = CKR_KEY_TYPE_INCONSISTENT;
665 break;
667 att = sftk_FindAttribute(key,CKA_VALUE);
668 if (att == NULL) {
669 crv = CKR_KEY_HANDLE_INVALID;
670 break;
672 context->cipherInfo = Camellia_CreateContext(
673 (unsigned char*)att->attrib.pValue,
674 (unsigned char*)pMechanism->pParameter,
675 pMechanism->mechanism ==
676 CKM_CAMELLIA_ECB ? NSS_CAMELLIA : NSS_CAMELLIA_CBC,
677 isEncrypt, att->attrib.ulValueLen);
678 sftk_FreeAttribute(att);
679 if (context->cipherInfo == NULL) {
680 crv = CKR_HOST_MEMORY;
681 break;
683 context->update = (SFTKCipher) (isEncrypt ?
684 Camellia_Encrypt : Camellia_Decrypt);
685 context->destroy = (SFTKDestroy) Camellia_DestroyContext;
686 break;
688 case CKM_AES_CBC_PAD:
689 context->doPad = PR_TRUE;
690 /* fall thru */
691 case CKM_AES_ECB:
692 case CKM_AES_CBC:
693 context->blockSize = 16;
694 if (key_type != CKK_AES) {
695 crv = CKR_KEY_TYPE_INCONSISTENT;
696 break;
698 att = sftk_FindAttribute(key,CKA_VALUE);
699 if (att == NULL) {
700 crv = CKR_KEY_HANDLE_INVALID;
701 break;
703 context->cipherInfo = AES_CreateContext(
704 (unsigned char*)att->attrib.pValue,
705 (unsigned char*)pMechanism->pParameter,
706 pMechanism->mechanism == CKM_AES_ECB ? NSS_AES : NSS_AES_CBC,
707 isEncrypt, att->attrib.ulValueLen, 16);
708 sftk_FreeAttribute(att);
709 if (context->cipherInfo == NULL) {
710 crv = CKR_HOST_MEMORY;
711 break;
713 context->update = (SFTKCipher) (isEncrypt ? AES_Encrypt : AES_Decrypt);
714 context->destroy = (SFTKDestroy) AES_DestroyContext;
715 break;
717 case CKM_NETSCAPE_AES_KEY_WRAP_PAD:
718 context->doPad = PR_TRUE;
719 /* fall thru */
720 case CKM_NETSCAPE_AES_KEY_WRAP:
721 context->multi = PR_FALSE;
722 context->blockSize = 8;
723 if (key_type != CKK_AES) {
724 crv = CKR_KEY_TYPE_INCONSISTENT;
725 break;
727 att = sftk_FindAttribute(key,CKA_VALUE);
728 if (att == NULL) {
729 crv = CKR_KEY_HANDLE_INVALID;
730 break;
732 context->cipherInfo = AESKeyWrap_CreateContext(
733 (unsigned char*)att->attrib.pValue,
734 (unsigned char*)pMechanism->pParameter,
735 isEncrypt, att->attrib.ulValueLen);
736 sftk_FreeAttribute(att);
737 if (context->cipherInfo == NULL) {
738 crv = CKR_HOST_MEMORY;
739 break;
741 context->update = (SFTKCipher) (isEncrypt ? AESKeyWrap_Encrypt
742 : AESKeyWrap_Decrypt);
743 context->destroy = (SFTKDestroy) AESKeyWrap_DestroyContext;
744 break;
746 default:
747 crv = CKR_MECHANISM_INVALID;
748 break;
751 if (crv != CKR_OK) {
752 sftk_FreeContext(context);
753 sftk_FreeSession(session);
754 return crv;
756 sftk_SetContextByType(session, contextType, context);
757 sftk_FreeSession(session);
758 return CKR_OK;
761 /* NSC_EncryptInit initializes an encryption operation. */
762 CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession,
763 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
765 CHECK_FORK();
766 return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT,
767 SFTK_ENCRYPT, PR_TRUE);
770 /* NSC_EncryptUpdate continues a multiple-part encryption operation. */
771 CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
772 CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
773 CK_ULONG_PTR pulEncryptedPartLen)
775 SFTKSessionContext *context;
776 unsigned int outlen,i;
777 unsigned int padoutlen = 0;
778 unsigned int maxout = *pulEncryptedPartLen;
779 CK_RV crv;
780 SECStatus rv;
782 CHECK_FORK();
784 /* make sure we're legal */
785 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,NULL);
786 if (crv != CKR_OK) return crv;
788 if (!pEncryptedPart) {
789 if (context->doPad) {
790 CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength;
791 CK_ULONG blocksToSend = totalDataAvailable/context->blockSize;
793 *pulEncryptedPartLen = blocksToSend * context->blockSize;
794 return CKR_OK;
796 *pulEncryptedPartLen = ulPartLen;
797 return CKR_OK;
800 /* do padding */
801 if (context->doPad) {
802 /* deal with previous buffered data */
803 if (context->padDataLength != 0) {
804 /* fill in the padded to a full block size */
805 for (i=context->padDataLength;
806 (ulPartLen != 0) && i < context->blockSize; i++) {
807 context->padBuf[i] = *pPart++;
808 ulPartLen--;
809 context->padDataLength++;
812 /* not enough data to encrypt yet? then return */
813 if (context->padDataLength != context->blockSize) {
814 *pulEncryptedPartLen = 0;
815 return CKR_OK;
817 /* encrypt the current padded data */
818 rv = (*context->update)(context->cipherInfo, pEncryptedPart,
819 &padoutlen, context->blockSize, context->padBuf,
820 context->blockSize);
821 if (rv != SECSuccess) {
822 return sftk_MapCryptError(PORT_GetError());
824 pEncryptedPart += padoutlen;
825 maxout -= padoutlen;
827 /* save the residual */
828 context->padDataLength = ulPartLen % context->blockSize;
829 if (context->padDataLength) {
830 PORT_Memcpy(context->padBuf,
831 &pPart[ulPartLen-context->padDataLength],
832 context->padDataLength);
833 ulPartLen -= context->padDataLength;
835 /* if we've exhausted our new buffer, we're done */
836 if (ulPartLen == 0) {
837 *pulEncryptedPartLen = padoutlen;
838 return CKR_OK;
843 /* do it: NOTE: this assumes buf size in is >= buf size out! */
844 rv = (*context->update)(context->cipherInfo,pEncryptedPart,
845 &outlen, maxout, pPart, ulPartLen);
846 *pulEncryptedPartLen = (CK_ULONG) (outlen + padoutlen);
847 if (rv != SECSuccess) {
848 return sftk_MapCryptError(PORT_GetError());
850 return CKR_OK;
854 /* NSC_EncryptFinal finishes a multiple-part encryption operation. */
855 CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
856 CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
858 SFTKSession *session;
859 SFTKSessionContext *context;
860 unsigned int outlen,i;
861 unsigned int maxout = *pulLastEncryptedPartLen;
862 CK_RV crv;
863 SECStatus rv = SECSuccess;
864 PRBool contextFinished = PR_TRUE;
866 CHECK_FORK();
868 /* make sure we're legal */
869 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,&session);
870 if (crv != CKR_OK) return crv;
872 *pulLastEncryptedPartLen = 0;
873 if (!pLastEncryptedPart) {
874 /* caller is checking the amount of remaining data */
875 if (context->blockSize > 0 && context->doPad) {
876 *pulLastEncryptedPartLen = context->blockSize;
877 contextFinished = PR_FALSE; /* still have padding to go */
879 goto finish;
882 /* do padding */
883 if (context->doPad) {
884 unsigned char padbyte = (unsigned char)
885 (context->blockSize - context->padDataLength);
886 /* fill out rest of pad buffer with pad magic*/
887 for (i=context->padDataLength; i < context->blockSize; i++) {
888 context->padBuf[i] = padbyte;
890 rv = (*context->update)(context->cipherInfo,pLastEncryptedPart,
891 &outlen, maxout, context->padBuf, context->blockSize);
892 if (rv == SECSuccess) *pulLastEncryptedPartLen = (CK_ULONG) outlen;
895 finish:
896 if (contextFinished) {
897 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
898 sftk_FreeContext(context);
900 sftk_FreeSession(session);
901 return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
904 /* NSC_Encrypt encrypts single-part data. */
905 CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
906 CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
907 CK_ULONG_PTR pulEncryptedDataLen)
909 SFTKSession *session;
910 SFTKSessionContext *context;
911 unsigned int outlen;
912 unsigned int maxoutlen = *pulEncryptedDataLen;
913 CK_RV crv;
914 CK_RV crv2;
915 SECStatus rv = SECSuccess;
916 SECItem pText;
918 pText.type = siBuffer;
919 pText.data = pData;
920 pText.len = ulDataLen;
922 CHECK_FORK();
924 /* make sure we're legal */
925 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,&session);
926 if (crv != CKR_OK) return crv;
928 if (!pEncryptedData) {
929 *pulEncryptedDataLen = context->multi ?
930 ulDataLen + 2 * context->blockSize : context->maxLen;
931 goto finish;
934 if (context->doPad) {
935 if (context->multi) {
936 CK_ULONG finalLen;
937 /* padding is fairly complicated, have the update and final
938 * code deal with it */
939 sftk_FreeSession(session);
940 crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData,
941 pulEncryptedDataLen);
942 if (crv != CKR_OK)
943 *pulEncryptedDataLen = 0;
944 maxoutlen -= *pulEncryptedDataLen;
945 pEncryptedData += *pulEncryptedDataLen;
946 finalLen = maxoutlen;
947 crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
948 if (crv2 == CKR_OK)
949 *pulEncryptedDataLen += finalLen;
950 return crv == CKR_OK ? crv2 : crv;
952 /* doPad without multi means that padding must be done on the first
953 ** and only update. There will be no final.
955 PORT_Assert(context->blockSize > 1);
956 if (context->blockSize > 1) {
957 CK_ULONG remainder = ulDataLen % context->blockSize;
958 CK_ULONG padding = context->blockSize - remainder;
959 pText.len += padding;
960 pText.data = PORT_ZAlloc(pText.len);
961 if (pText.data) {
962 memcpy(pText.data, pData, ulDataLen);
963 memset(pText.data + ulDataLen, padding, padding);
964 } else {
965 crv = CKR_HOST_MEMORY;
966 goto fail;
971 /* do it: NOTE: this assumes buf size is big enough. */
972 rv = (*context->update)(context->cipherInfo, pEncryptedData,
973 &outlen, maxoutlen, pText.data, pText.len);
974 crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
975 *pulEncryptedDataLen = (CK_ULONG) outlen;
976 if (pText.data != pData)
977 PORT_ZFree(pText.data, pText.len);
978 fail:
979 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
980 sftk_FreeContext(context);
981 finish:
982 sftk_FreeSession(session);
984 return crv;
989 ************** Crypto Functions: Decrypt ************************
992 /* NSC_DecryptInit initializes a decryption operation. */
993 CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession,
994 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
996 CHECK_FORK();
998 return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT,
999 SFTK_DECRYPT, PR_FALSE);
1002 /* NSC_DecryptUpdate continues a multiple-part decryption operation. */
1003 CK_RV NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
1004 CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
1005 CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
1007 SFTKSessionContext *context;
1008 unsigned int padoutlen = 0;
1009 unsigned int outlen;
1010 unsigned int maxout = *pulPartLen;
1011 CK_RV crv;
1012 SECStatus rv;
1014 CHECK_FORK();
1016 /* make sure we're legal */
1017 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,NULL);
1018 if (crv != CKR_OK) return crv;
1020 /* this can only happen on an NSS programming error */
1021 PORT_Assert((context->padDataLength == 0)
1022 || context->padDataLength == context->blockSize);
1025 if (!pPart) {
1026 if (context->doPad) {
1027 /* we can check the data length here because if we are padding,
1028 * then we must be using a block cipher. In the non-padding case
1029 * the error will be returned by the underlying decryption
1030 * function when do do the actual decrypt. We need to do the
1031 * check here to avoid returning a negative length to the caller.
1033 if ((ulEncryptedPartLen == 0) ||
1034 (ulEncryptedPartLen % context->blockSize) != 0) {
1035 return CKR_ENCRYPTED_DATA_LEN_RANGE;
1037 *pulPartLen =
1038 ulEncryptedPartLen + context->padDataLength - context->blockSize;
1039 return CKR_OK;
1041 /* for stream ciphers there is are no constraints on ulEncryptedPartLen.
1042 * for block ciphers, it must be a multiple of blockSize. The error is
1043 * detected when this function is called again do decrypt the output.
1045 *pulPartLen = ulEncryptedPartLen;
1046 return CKR_OK;
1049 if (context->doPad) {
1050 /* first decrypt our saved buffer */
1051 if (context->padDataLength != 0) {
1052 rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
1053 maxout, context->padBuf, context->blockSize);
1054 if (rv != SECSuccess) return CKR_DEVICE_ERROR;
1055 pPart += padoutlen;
1056 maxout -= padoutlen;
1058 /* now save the final block for the next decrypt or the final */
1059 PORT_Memcpy(context->padBuf,&pEncryptedPart[ulEncryptedPartLen -
1060 context->blockSize], context->blockSize);
1061 context->padDataLength = context->blockSize;
1062 ulEncryptedPartLen -= context->padDataLength;
1065 /* do it: NOTE: this assumes buf size in is >= buf size out! */
1066 rv = (*context->update)(context->cipherInfo,pPart, &outlen,
1067 maxout, pEncryptedPart, ulEncryptedPartLen);
1068 *pulPartLen = (CK_ULONG) (outlen + padoutlen);
1069 return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
1073 /* NSC_DecryptFinal finishes a multiple-part decryption operation. */
1074 CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
1075 CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
1077 SFTKSession *session;
1078 SFTKSessionContext *context;
1079 unsigned int outlen;
1080 unsigned int maxout = *pulLastPartLen;
1081 CK_RV crv;
1082 SECStatus rv = SECSuccess;
1084 CHECK_FORK();
1086 /* make sure we're legal */
1087 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,&session);
1088 if (crv != CKR_OK) return crv;
1090 *pulLastPartLen = 0;
1091 if (!pLastPart) {
1092 /* caller is checking the amount of remaining data */
1093 if (context->padDataLength > 0) {
1094 *pulLastPartLen = context->padDataLength;
1096 rv = SECSuccess;
1097 goto finish;
1100 if (context->doPad) {
1101 /* decrypt our saved buffer */
1102 if (context->padDataLength != 0) {
1103 /* this assumes that pLastPart is big enough to hold the *whole*
1104 * buffer!!! */
1105 rv = (*context->update)(context->cipherInfo, pLastPart, &outlen,
1106 maxout, context->padBuf, context->blockSize);
1107 if (rv == SECSuccess) {
1108 unsigned int padSize =
1109 (unsigned int) pLastPart[context->blockSize-1];
1110 if ((padSize > context->blockSize) || (padSize == 0)) {
1111 rv = SECFailure;
1112 } else {
1113 *pulLastPartLen = outlen - padSize;
1119 sftk_SetContextByType(session, SFTK_DECRYPT, NULL);
1120 sftk_FreeContext(context);
1121 finish:
1122 sftk_FreeSession(session);
1123 return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
1126 /* NSC_Decrypt decrypts encrypted data in a single part. */
1127 CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession,
1128 CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,
1129 CK_ULONG_PTR pulDataLen)
1131 SFTKSession *session;
1132 SFTKSessionContext *context;
1133 unsigned int outlen;
1134 unsigned int maxoutlen = *pulDataLen;
1135 CK_RV crv;
1136 CK_RV crv2;
1137 SECStatus rv = SECSuccess;
1139 CHECK_FORK();
1141 /* make sure we're legal */
1142 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_FALSE,&session);
1143 if (crv != CKR_OK) return crv;
1145 if (!pData) {
1146 *pulDataLen = ulEncryptedDataLen + context->blockSize;
1147 goto finish;
1150 if (context->doPad && context->multi) {
1151 CK_ULONG finalLen;
1152 /* padding is fairly complicated, have the update and final
1153 * code deal with it */
1154 sftk_FreeSession(session);
1155 crv = NSC_DecryptUpdate(hSession,pEncryptedData,ulEncryptedDataLen,
1156 pData, pulDataLen);
1157 if (crv != CKR_OK)
1158 *pulDataLen = 0;
1159 maxoutlen -= *pulDataLen;
1160 pData += *pulDataLen;
1161 finalLen = maxoutlen;
1162 crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
1163 if (crv2 == CKR_OK)
1164 *pulDataLen += finalLen;
1165 return crv == CKR_OK ? crv2 : crv;
1168 rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
1169 pEncryptedData, ulEncryptedDataLen);
1170 /* XXX need to do MUCH better error mapping than this. */
1171 crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
1172 if (rv == SECSuccess && context->doPad) {
1173 CK_ULONG padding = pData[outlen - 1];
1174 if (padding > context->blockSize || !padding) {
1175 crv = CKR_ENCRYPTED_DATA_INVALID;
1176 } else
1177 outlen -= padding;
1179 *pulDataLen = (CK_ULONG) outlen;
1180 sftk_SetContextByType(session, SFTK_DECRYPT, NULL);
1181 sftk_FreeContext(context);
1182 finish:
1183 sftk_FreeSession(session);
1184 return crv;
1190 ************** Crypto Functions: Digest (HASH) ************************
1193 /* NSC_DigestInit initializes a message-digesting operation. */
1194 CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession,
1195 CK_MECHANISM_PTR pMechanism)
1197 SFTKSession *session;
1198 SFTKSessionContext *context;
1199 CK_RV crv = CKR_OK;
1201 CHECK_FORK();
1203 session = sftk_SessionFromHandle(hSession);
1204 if (session == NULL)
1205 return CKR_SESSION_HANDLE_INVALID;
1206 crv = sftk_InitGeneric(session,&context,SFTK_HASH,NULL,0,NULL, 0, 0);
1207 if (crv != CKR_OK) {
1208 sftk_FreeSession(session);
1209 return crv;
1213 #define INIT_MECH(mech,mmm) \
1214 case mech: { \
1215 mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \
1216 context->cipherInfo = (void *)mmm ## _ctx; \
1217 context->cipherInfoLen = mmm ## _FlattenSize(mmm ## _ctx); \
1218 context->currentMech = mech; \
1219 context->hashUpdate = (SFTKHash) mmm ## _Update; \
1220 context->end = (SFTKEnd) mmm ## _End; \
1221 context->destroy = (SFTKDestroy) mmm ## _DestroyContext; \
1222 context->maxLen = mmm ## _LENGTH; \
1223 if (mmm ## _ctx) \
1224 mmm ## _Begin(mmm ## _ctx); \
1225 else \
1226 crv = CKR_HOST_MEMORY; \
1227 break; \
1230 switch(pMechanism->mechanism) {
1231 INIT_MECH(CKM_MD2, MD2)
1232 INIT_MECH(CKM_MD5, MD5)
1233 INIT_MECH(CKM_SHA_1, SHA1)
1234 INIT_MECH(CKM_SHA256, SHA256)
1235 INIT_MECH(CKM_SHA384, SHA384)
1236 INIT_MECH(CKM_SHA512, SHA512)
1238 default:
1239 crv = CKR_MECHANISM_INVALID;
1240 break;
1243 if (crv != CKR_OK) {
1244 sftk_FreeContext(context);
1245 sftk_FreeSession(session);
1246 return crv;
1248 sftk_SetContextByType(session, SFTK_HASH, context);
1249 sftk_FreeSession(session);
1250 return CKR_OK;
1254 /* NSC_Digest digests data in a single part. */
1255 CK_RV NSC_Digest(CK_SESSION_HANDLE hSession,
1256 CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
1257 CK_ULONG_PTR pulDigestLen)
1259 SFTKSession *session;
1260 SFTKSessionContext *context;
1261 unsigned int digestLen;
1262 unsigned int maxout = *pulDigestLen;
1263 CK_RV crv;
1265 CHECK_FORK();
1267 /* make sure we're legal */
1268 crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_FALSE,&session);
1269 if (crv != CKR_OK) return crv;
1271 if (pDigest == NULL) {
1272 *pulDigestLen = context->maxLen;
1273 goto finish;
1276 /* do it: */
1277 (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
1278 /* NOTE: this assumes buf size is bigenough for the algorithm */
1279 (*context->end)(context->cipherInfo, pDigest, &digestLen,maxout);
1280 *pulDigestLen = digestLen;
1282 sftk_SetContextByType(session, SFTK_HASH, NULL);
1283 sftk_FreeContext(context);
1284 finish:
1285 sftk_FreeSession(session);
1286 return CKR_OK;
1290 /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
1291 CK_RV NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
1292 CK_ULONG ulPartLen)
1294 SFTKSessionContext *context;
1295 CK_RV crv;
1297 CHECK_FORK();
1299 /* make sure we're legal */
1300 crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_TRUE,NULL);
1301 if (crv != CKR_OK) return crv;
1302 /* do it: */
1303 (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);
1304 return CKR_OK;
1308 /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
1309 CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,
1310 CK_ULONG_PTR pulDigestLen)
1312 SFTKSession *session;
1313 SFTKSessionContext *context;
1314 unsigned int maxout = *pulDigestLen;
1315 unsigned int digestLen;
1316 CK_RV crv;
1318 CHECK_FORK();
1320 /* make sure we're legal */
1321 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
1322 if (crv != CKR_OK) return crv;
1324 if (pDigest != NULL) {
1325 (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
1326 *pulDigestLen = digestLen;
1327 sftk_SetContextByType(session, SFTK_HASH, NULL);
1328 sftk_FreeContext(context);
1329 } else {
1330 *pulDigestLen = context->maxLen;
1333 sftk_FreeSession(session);
1334 return CKR_OK;
1338 * these helper functions are used by Generic Macing and Signing functions
1339 * that use hashes as part of their operations.
1341 #define DOSUB(mmm) \
1342 static CK_RV \
1343 sftk_doSub ## mmm(SFTKSessionContext *context) { \
1344 mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \
1345 context->hashInfo = (void *) mmm ## _ctx; \
1346 context->hashUpdate = (SFTKHash) mmm ## _Update; \
1347 context->end = (SFTKEnd) mmm ## _End; \
1348 context->hashdestroy = (SFTKDestroy) mmm ## _DestroyContext; \
1349 if (!context->hashInfo) { \
1350 return CKR_HOST_MEMORY; \
1352 mmm ## _Begin( mmm ## _ctx ); \
1353 return CKR_OK; \
1356 DOSUB(MD2)
1357 DOSUB(MD5)
1358 DOSUB(SHA1)
1359 DOSUB(SHA256)
1360 DOSUB(SHA384)
1361 DOSUB(SHA512)
1364 * HMAC General copies only a portion of the result. This update routine likes
1365 * the final HMAC output with the signature.
1367 static SECStatus
1368 sftk_HMACCopy(CK_ULONG *copyLen,unsigned char *sig,unsigned int *sigLen,
1369 unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
1371 if (maxLen < *copyLen) return SECFailure;
1372 PORT_Memcpy(sig,hash,*copyLen);
1373 *sigLen = *copyLen;
1374 return SECSuccess;
1377 /* Verify is just a compare for HMAC */
1378 static SECStatus
1379 sftk_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen,
1380 unsigned char *hash, unsigned int hashLen)
1382 return (PORT_Memcmp(sig,hash,*copyLen) == 0) ? SECSuccess : SECFailure ;
1386 * common HMAC initalization routine
1388 static CK_RV
1389 sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash,
1390 SFTKObject *key, CK_ULONG mac_size)
1392 SFTKAttribute *keyval;
1393 HMACContext *HMACcontext;
1394 CK_ULONG *intpointer;
1395 const SECHashObject *hashObj = HASH_GetRawHashObject(hash);
1396 PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID);
1398 /* required by FIPS 198 Section 4 */
1399 if (isFIPS && (mac_size < 4 || mac_size < hashObj->length/2)) {
1400 return CKR_BUFFER_TOO_SMALL;
1403 keyval = sftk_FindAttribute(key,CKA_VALUE);
1404 if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
1406 HMACcontext = HMAC_Create(hashObj,
1407 (const unsigned char*)keyval->attrib.pValue,
1408 keyval->attrib.ulValueLen, isFIPS);
1409 context->hashInfo = HMACcontext;
1410 context->multi = PR_TRUE;
1411 sftk_FreeAttribute(keyval);
1412 if (context->hashInfo == NULL) {
1413 if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) {
1414 return CKR_KEY_SIZE_RANGE;
1416 return CKR_HOST_MEMORY;
1418 context->hashUpdate = (SFTKHash) HMAC_Update;
1419 context->end = (SFTKEnd) HMAC_Finish;
1421 context->hashdestroy = (SFTKDestroy) HMAC_Destroy;
1422 intpointer = (CK_ULONG *) PORT_Alloc(sizeof(CK_ULONG));
1423 if (intpointer == NULL) {
1424 return CKR_HOST_MEMORY;
1426 *intpointer = mac_size;
1427 context->cipherInfo = (void *) intpointer;
1428 context->destroy = (SFTKDestroy) sftk_Space;
1429 context->update = (SFTKCipher) sftk_HMACCopy;
1430 context->verify = (SFTKVerify) sftk_HMACCmp;
1431 context->maxLen = hashObj->length;
1432 HMAC_Begin(HMACcontext);
1433 return CKR_OK;
1437 * SSL Macing support. SSL Macs are inited, then update with the base
1438 * hashing algorithm, then finalized in sign and verify
1442 * FROM SSL:
1443 * 60 bytes is 3 times the maximum length MAC size that is supported.
1444 * We probably should have one copy of this table. We still need this table
1445 * in ssl to 'sign' the handshake hashes.
1447 static unsigned char ssl_pad_1 [60] = {
1448 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1449 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1450 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1451 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1452 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1453 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1454 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1455 0x36, 0x36, 0x36, 0x36
1457 static unsigned char ssl_pad_2 [60] = {
1458 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1459 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1460 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1461 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1462 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1463 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1464 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1465 0x5c, 0x5c, 0x5c, 0x5c
1468 static SECStatus
1469 sftk_SSLMACSign(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int *sigLen,
1470 unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
1472 unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
1473 unsigned int out;
1475 info->begin(info->hashContext);
1476 info->update(info->hashContext,info->key,info->keySize);
1477 info->update(info->hashContext,ssl_pad_2,info->padSize);
1478 info->update(info->hashContext,hash,hashLen);
1479 info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH);
1480 PORT_Memcpy(sig,tmpBuf,info->macSize);
1481 *sigLen = info->macSize;
1482 return SECSuccess;
1485 static SECStatus
1486 sftk_SSLMACVerify(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int sigLen,
1487 unsigned char *hash, unsigned int hashLen)
1489 unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
1490 unsigned int out;
1492 info->begin(info->hashContext);
1493 info->update(info->hashContext,info->key,info->keySize);
1494 info->update(info->hashContext,ssl_pad_2,info->padSize);
1495 info->update(info->hashContext,hash,hashLen);
1496 info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH);
1497 return (PORT_Memcmp(sig,tmpBuf,info->macSize) == 0) ?
1498 SECSuccess : SECFailure;
1502 * common HMAC initalization routine
1504 static CK_RV
1505 sftk_doSSLMACInit(SFTKSessionContext *context,SECOidTag oid,
1506 SFTKObject *key, CK_ULONG mac_size)
1508 SFTKAttribute *keyval;
1509 SFTKBegin begin;
1510 int padSize;
1511 SFTKSSLMACInfo *sslmacinfo;
1512 CK_RV crv = CKR_MECHANISM_INVALID;
1514 if (oid == SEC_OID_SHA1) {
1515 crv = sftk_doSubSHA1(context);
1516 if (crv != CKR_OK) return crv;
1517 begin = (SFTKBegin) SHA1_Begin;
1518 padSize = 40;
1519 } else {
1520 crv = sftk_doSubMD5(context);
1521 if (crv != CKR_OK) return crv;
1522 begin = (SFTKBegin) MD5_Begin;
1523 padSize = 48;
1525 context->multi = PR_TRUE;
1527 keyval = sftk_FindAttribute(key,CKA_VALUE);
1528 if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
1530 context->hashUpdate(context->hashInfo,keyval->attrib.pValue,
1531 keyval->attrib.ulValueLen);
1532 context->hashUpdate(context->hashInfo,ssl_pad_1,padSize);
1533 sslmacinfo = (SFTKSSLMACInfo *) PORT_Alloc(sizeof(SFTKSSLMACInfo));
1534 if (sslmacinfo == NULL) {
1535 sftk_FreeAttribute(keyval);
1536 return CKR_HOST_MEMORY;
1538 sslmacinfo->macSize = mac_size;
1539 sslmacinfo->hashContext = context->hashInfo;
1540 PORT_Memcpy(sslmacinfo->key,keyval->attrib.pValue,
1541 keyval->attrib.ulValueLen);
1542 sslmacinfo->keySize = keyval->attrib.ulValueLen;
1543 sslmacinfo->begin = begin;
1544 sslmacinfo->end = context->end;
1545 sslmacinfo->update = context->hashUpdate;
1546 sslmacinfo->padSize = padSize;
1547 sftk_FreeAttribute(keyval);
1548 context->cipherInfo = (void *) sslmacinfo;
1549 context->destroy = (SFTKDestroy) sftk_Space;
1550 context->update = (SFTKCipher) sftk_SSLMACSign;
1551 context->verify = (SFTKVerify) sftk_SSLMACVerify;
1552 context->maxLen = mac_size;
1553 return CKR_OK;
1557 ************** Crypto Functions: Sign ************************
1561 * Check if We're using CBCMacing and initialize the session context if we are.
1563 static CK_RV
1564 sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
1565 CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,
1566 SFTKContextType contextType)
1569 CK_MECHANISM cbc_mechanism;
1570 CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
1571 CK_RC2_CBC_PARAMS rc2_params;
1572 #if NSS_SOFTOKEN_DOES_RC5
1573 CK_RC5_CBC_PARAMS rc5_params;
1574 CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
1575 #endif
1576 unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
1577 SFTKSessionContext *context;
1578 CK_RV crv;
1579 int blockSize;
1581 switch (pMechanism->mechanism) {
1582 case CKM_RC2_MAC_GENERAL:
1583 mac_bytes =
1584 ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
1585 /* fall through */
1586 case CKM_RC2_MAC:
1587 /* this works because ulEffectiveBits is in the same place in both the
1588 * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */
1589 rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *)
1590 pMechanism->pParameter)->ulEffectiveBits;
1591 PORT_Memset(rc2_params.iv,0,sizeof(rc2_params.iv));
1592 cbc_mechanism.mechanism = CKM_RC2_CBC;
1593 cbc_mechanism.pParameter = &rc2_params;
1594 cbc_mechanism.ulParameterLen = sizeof(rc2_params);
1595 blockSize = 8;
1596 break;
1597 #if NSS_SOFTOKEN_DOES_RC5
1598 case CKM_RC5_MAC_GENERAL:
1599 mac_bytes =
1600 ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
1601 /* fall through */
1602 case CKM_RC5_MAC:
1603 /* this works because ulEffectiveBits is in the same place in both the
1604 * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
1605 rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
1606 rc5_params.ulWordsize = rc5_mac->ulWordsize;
1607 rc5_params.ulRounds = rc5_mac->ulRounds;
1608 rc5_params.pIv = ivBlock;
1609 blockSize = rc5_mac->ulWordsize*2;
1610 rc5_params.ulIvLen = blockSize;
1611 PORT_Memset(ivBlock,0,blockSize);
1612 cbc_mechanism.mechanism = CKM_RC5_CBC;
1613 cbc_mechanism.pParameter = &rc5_params;
1614 cbc_mechanism.ulParameterLen = sizeof(rc5_params);
1615 break;
1616 #endif
1617 /* add cast and idea later */
1618 case CKM_DES_MAC_GENERAL:
1619 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1620 /* fall through */
1621 case CKM_DES_MAC:
1622 blockSize = 8;
1623 PORT_Memset(ivBlock,0,blockSize);
1624 cbc_mechanism.mechanism = CKM_DES_CBC;
1625 cbc_mechanism.pParameter = &ivBlock;
1626 cbc_mechanism.ulParameterLen = blockSize;
1627 break;
1628 case CKM_DES3_MAC_GENERAL:
1629 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1630 /* fall through */
1631 case CKM_DES3_MAC:
1632 blockSize = 8;
1633 PORT_Memset(ivBlock,0,blockSize);
1634 cbc_mechanism.mechanism = CKM_DES3_CBC;
1635 cbc_mechanism.pParameter = &ivBlock;
1636 cbc_mechanism.ulParameterLen = blockSize;
1637 break;
1638 case CKM_CDMF_MAC_GENERAL:
1639 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1640 /* fall through */
1641 case CKM_CDMF_MAC:
1642 blockSize = 8;
1643 PORT_Memset(ivBlock,0,blockSize);
1644 cbc_mechanism.mechanism = CKM_CDMF_CBC;
1645 cbc_mechanism.pParameter = &ivBlock;
1646 cbc_mechanism.ulParameterLen = blockSize;
1647 break;
1648 case CKM_CAMELLIA_MAC_GENERAL:
1649 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1650 /* fall through */
1651 case CKM_CAMELLIA_MAC:
1652 blockSize = 16;
1653 PORT_Memset(ivBlock,0,blockSize);
1654 cbc_mechanism.mechanism = CKM_CAMELLIA_CBC;
1655 cbc_mechanism.pParameter = &ivBlock;
1656 cbc_mechanism.ulParameterLen = blockSize;
1657 break;
1658 case CKM_AES_MAC_GENERAL:
1659 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1660 /* fall through */
1661 case CKM_AES_MAC:
1662 blockSize = 16;
1663 PORT_Memset(ivBlock,0,blockSize);
1664 cbc_mechanism.mechanism = CKM_AES_CBC;
1665 cbc_mechanism.pParameter = &ivBlock;
1666 cbc_mechanism.ulParameterLen = blockSize;
1667 break;
1668 default:
1669 return CKR_FUNCTION_NOT_SUPPORTED;
1672 crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey, keyUsage,
1673 contextType, PR_TRUE);
1674 if (crv != CKR_OK) return crv;
1675 crv = sftk_GetContext(hSession,&context,contextType,PR_TRUE,NULL);
1677 /* this shouldn't happen! */
1678 PORT_Assert(crv == CKR_OK);
1679 if (crv != CKR_OK) return crv;
1680 context->blockSize = blockSize;
1681 if (mac_bytes == SFTK_INVALID_MAC_SIZE) mac_bytes = blockSize/2;
1682 context->macSize = mac_bytes;
1683 return CKR_OK;
1687 * encode RSA PKCS #1 Signature data before signing...
1689 static SECStatus
1690 sftk_HashSign(SFTKHashSignInfo *info,unsigned char *sig,unsigned int *sigLen,
1691 unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
1693 return RSA_HashSign(info->hashOid,info->key,sig,sigLen,maxLen,
1694 hash,hashLen);
1697 /* XXX Old template; want to expunge it eventually. */
1698 static DERTemplate SECAlgorithmIDTemplate[] = {
1699 { DER_SEQUENCE,
1700 0, NULL, sizeof(SECAlgorithmID) },
1701 { DER_OBJECT_ID,
1702 offsetof(SECAlgorithmID,algorithm), },
1703 { DER_OPTIONAL | DER_ANY,
1704 offsetof(SECAlgorithmID,parameters), },
1705 { 0, }
1709 * XXX OLD Template. Once all uses have been switched over to new one,
1710 * remove this.
1712 static DERTemplate SGNDigestInfoTemplate[] = {
1713 { DER_SEQUENCE,
1714 0, NULL, sizeof(SGNDigestInfo) },
1715 { DER_INLINE,
1716 offsetof(SGNDigestInfo,digestAlgorithm),
1717 SECAlgorithmIDTemplate, },
1718 { DER_OCTET_STRING,
1719 offsetof(SGNDigestInfo,digest), },
1720 { 0, }
1723 SECStatus
1724 RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
1725 unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
1726 unsigned char *hash, unsigned int hashLen)
1729 SECStatus rv = SECFailure;
1730 SECItem digder;
1731 PLArenaPool *arena = NULL;
1732 SGNDigestInfo *di = NULL;
1734 digder.data = NULL;
1736 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1737 if ( !arena ) { goto loser; }
1739 /* Construct digest info */
1740 di = SGN_CreateDigestInfo(hashOid, hash, hashLen);
1741 if (!di) { goto loser; }
1743 /* Der encode the digest as a DigestInfo */
1744 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
1745 if (rv != SECSuccess) {
1746 goto loser;
1750 ** Encrypt signature after constructing appropriate PKCS#1 signature
1751 ** block
1753 rv = RSA_Sign(key,sig,sigLen,maxLen,digder.data,digder.len);
1755 loser:
1756 SGN_DestroyDigestInfo(di);
1757 if (arena != NULL) {
1758 PORT_FreeArena(arena, PR_FALSE);
1760 return rv;
1763 static SECStatus
1764 nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen,
1765 void *dataBuf, unsigned int dataLen)
1767 SECItem signature, digest;
1768 NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
1770 signature.data = (unsigned char *)sigBuf;
1771 signature.len = sigLen;
1772 digest.data = (unsigned char *)dataBuf;
1773 digest.len = dataLen;
1774 return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest);
1777 static SECStatus
1778 nsc_DSA_Sign_Stub(void *ctx, void *sigBuf,
1779 unsigned int *sigLen, unsigned int maxSigLen,
1780 void *dataBuf, unsigned int dataLen)
1782 SECItem signature, digest;
1783 SECStatus rv;
1784 NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
1786 signature.data = (unsigned char *)sigBuf;
1787 signature.len = maxSigLen;
1788 digest.data = (unsigned char *)dataBuf;
1789 digest.len = dataLen;
1790 rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest);
1791 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
1792 sftk_fatalError = PR_TRUE;
1794 *sigLen = signature.len;
1795 return rv;
1798 #ifdef NSS_ENABLE_ECC
1799 static SECStatus
1800 nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen,
1801 void *dataBuf, unsigned int dataLen)
1803 SECItem signature, digest;
1804 NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
1806 signature.data = (unsigned char *)sigBuf;
1807 signature.len = sigLen;
1808 digest.data = (unsigned char *)dataBuf;
1809 digest.len = dataLen;
1810 return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest);
1813 static SECStatus
1814 nsc_ECDSASignStub(void *ctx, void *sigBuf,
1815 unsigned int *sigLen, unsigned int maxSigLen,
1816 void *dataBuf, unsigned int dataLen)
1818 SECItem signature, digest;
1819 SECStatus rv;
1820 NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
1822 signature.data = (unsigned char *)sigBuf;
1823 signature.len = maxSigLen;
1824 digest.data = (unsigned char *)dataBuf;
1825 digest.len = dataLen;
1826 rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest);
1827 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
1828 sftk_fatalError = PR_TRUE;
1830 *sigLen = signature.len;
1831 return rv;
1833 #endif /* NSS_ENABLE_ECC */
1835 /* NSC_SignInit setups up the signing operations. There are three basic
1836 * types of signing:
1837 * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
1838 * to data in a single Sign operation (which often looks a lot like an
1839 * encrypt, with data coming in and data going out).
1840 * (2) Hash based signing, where we continually hash the data, then apply
1841 * some sort of signature to the end.
1842 * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key,
1843 * and only the final block is part of the mac.
1845 * For case number 3, we initialize a context much like the Encryption Context
1846 * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and
1847 * C_Final by the following method... if it's not multi-part, and it's doesn't
1848 * have a hash context, it must be a block Encryption CBC MAC.
1850 * For case number 2, we initialize a hash structure, as well as make it
1851 * multi-part. Updates are simple calls to the hash update function. Final
1852 * calls the hashend, then passes the result to the 'update' function (which
1853 * operates as a final signature function). In some hash based MAC'ing (as
1854 * opposed to hash base signatures), the update function is can be simply a
1855 * copy (as is the case with HMAC).
1857 CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession,
1858 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1860 SFTKSession *session;
1861 SFTKObject *key;
1862 SFTKSessionContext *context;
1863 CK_KEY_TYPE key_type;
1864 CK_RV crv = CKR_OK;
1865 NSSLOWKEYPrivateKey *privKey;
1866 SFTKHashSignInfo *info = NULL;
1868 CHECK_FORK();
1870 /* Block Cipher MACing Algorithms use a different Context init method..*/
1871 crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN);
1872 if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv;
1874 /* we're not using a block cipher mac */
1875 session = sftk_SessionFromHandle(hSession);
1876 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1877 crv = sftk_InitGeneric(session,&context,SFTK_SIGN,&key,hKey,&key_type,
1878 CKO_PRIVATE_KEY,CKA_SIGN);
1879 if (crv != CKR_OK) {
1880 sftk_FreeSession(session);
1881 return crv;
1884 context->multi = PR_FALSE;
1886 #define INIT_RSA_SIGN_MECH(mmm) \
1887 case CKM_ ## mmm ## _RSA_PKCS: \
1888 context->multi = PR_TRUE; \
1889 crv = sftk_doSub ## mmm (context); \
1890 if (crv != CKR_OK) break; \
1891 context->update = (SFTKCipher) sftk_HashSign; \
1892 info = PORT_New(SFTKHashSignInfo); \
1893 if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \
1894 info->hashOid = SEC_OID_ ## mmm ; \
1895 goto finish_rsa;
1897 switch(pMechanism->mechanism) {
1898 INIT_RSA_SIGN_MECH(MD5)
1899 INIT_RSA_SIGN_MECH(MD2)
1900 INIT_RSA_SIGN_MECH(SHA1)
1901 INIT_RSA_SIGN_MECH(SHA256)
1902 INIT_RSA_SIGN_MECH(SHA384)
1903 INIT_RSA_SIGN_MECH(SHA512)
1905 case CKM_RSA_PKCS:
1906 context->update = (SFTKCipher) RSA_Sign;
1907 goto finish_rsa;
1908 case CKM_RSA_X_509:
1909 context->update = (SFTKCipher) RSA_SignRaw;
1910 finish_rsa:
1911 if (key_type != CKK_RSA) {
1912 if (info) PORT_Free(info);
1913 crv = CKR_KEY_TYPE_INCONSISTENT;
1914 break;
1916 privKey = sftk_GetPrivKey(key,CKK_RSA,&crv);
1917 if (privKey == NULL) {
1918 if (info) PORT_Free(info);
1919 break;
1921 /* OK, info is allocated only if we're doing hash and sign mechanism.
1922 * It's necessary to be able to set the correct OID in the final
1923 * signature.
1925 if (info) {
1926 info->key = privKey;
1927 context->cipherInfo = info;
1928 context->destroy = (SFTKDestroy)sftk_Space;
1929 } else {
1930 context->cipherInfo = privKey;
1931 context->destroy = (SFTKDestroy)sftk_Null;
1933 context->maxLen = nsslowkey_PrivateModulusLen(privKey);
1934 break;
1936 case CKM_DSA_SHA1:
1937 context->multi = PR_TRUE;
1938 crv = sftk_doSubSHA1(context);
1939 if (crv != CKR_OK) break;
1940 /* fall through */
1941 case CKM_DSA:
1942 if (key_type != CKK_DSA) {
1943 crv = CKR_KEY_TYPE_INCONSISTENT;
1944 break;
1946 privKey = sftk_GetPrivKey(key,CKK_DSA,&crv);
1947 if (privKey == NULL) {
1948 break;
1950 context->cipherInfo = privKey;
1951 context->update = (SFTKCipher) nsc_DSA_Sign_Stub;
1952 context->destroy = (privKey == key->objectInfo) ?
1953 (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey;
1954 context->maxLen = DSA_SIGNATURE_LEN;
1956 break;
1958 #ifdef NSS_ENABLE_ECC
1959 case CKM_ECDSA_SHA1:
1960 context->multi = PR_TRUE;
1961 crv = sftk_doSubSHA1(context);
1962 if (crv != CKR_OK) break;
1963 /* fall through */
1964 case CKM_ECDSA:
1965 if (key_type != CKK_EC) {
1966 crv = CKR_KEY_TYPE_INCONSISTENT;
1967 break;
1969 privKey = sftk_GetPrivKey(key,CKK_EC,&crv);
1970 if (privKey == NULL) {
1971 crv = CKR_HOST_MEMORY;
1972 break;
1974 context->cipherInfo = privKey;
1975 context->update = (SFTKCipher) nsc_ECDSASignStub;
1976 context->destroy = (privKey == key->objectInfo) ?
1977 (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey;
1978 context->maxLen = MAX_ECKEY_LEN * 2;
1980 break;
1981 #endif /* NSS_ENABLE_ECC */
1983 #define INIT_HMAC_MECH(mmm) \
1984 case CKM_ ## mmm ## _HMAC_GENERAL: \
1985 crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, \
1986 *(CK_ULONG *)pMechanism->pParameter); \
1987 break; \
1988 case CKM_ ## mmm ## _HMAC: \
1989 crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, mmm ## _LENGTH); \
1990 break;
1992 INIT_HMAC_MECH(MD2)
1993 INIT_HMAC_MECH(MD5)
1994 INIT_HMAC_MECH(SHA256)
1995 INIT_HMAC_MECH(SHA384)
1996 INIT_HMAC_MECH(SHA512)
1998 case CKM_SHA_1_HMAC_GENERAL:
1999 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,
2000 *(CK_ULONG *)pMechanism->pParameter);
2001 break;
2002 case CKM_SHA_1_HMAC:
2003 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH);
2004 break;
2006 case CKM_SSL3_MD5_MAC:
2007 crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key,
2008 *(CK_ULONG *)pMechanism->pParameter);
2009 break;
2010 case CKM_SSL3_SHA1_MAC:
2011 crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key,
2012 *(CK_ULONG *)pMechanism->pParameter);
2013 break;
2014 case CKM_TLS_PRF_GENERAL:
2015 crv = sftk_TLSPRFInit(context, key, key_type);
2016 break;
2017 default:
2018 crv = CKR_MECHANISM_INVALID;
2019 break;
2022 if (crv != CKR_OK) {
2023 sftk_FreeContext(context);
2024 sftk_FreeSession(session);
2025 return crv;
2027 sftk_SetContextByType(session, SFTK_SIGN, context);
2028 sftk_FreeSession(session);
2029 return CKR_OK;
2033 /* MACUpdate is the common implementation for SignUpdate and VerifyUpdate.
2034 * (sign and verify only very in their setup and final operations) */
2035 static CK_RV
2036 sftk_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
2037 CK_ULONG ulPartLen,SFTKContextType type)
2039 unsigned int outlen;
2040 SFTKSessionContext *context;
2041 CK_RV crv;
2042 SECStatus rv;
2044 /* make sure we're legal */
2045 crv = sftk_GetContext(hSession,&context,type,PR_TRUE,NULL);
2046 if (crv != CKR_OK) return crv;
2048 if (context->hashInfo) {
2049 (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen);
2050 return CKR_OK;
2053 /* must be block cipher macing */
2055 /* deal with previous buffered data */
2056 if (context->padDataLength != 0) {
2057 int i;
2058 /* fill in the padded to a full block size */
2059 for (i=context->padDataLength; (ulPartLen != 0) &&
2060 i < (int)context->blockSize; i++) {
2061 context->padBuf[i] = *pPart++;
2062 ulPartLen--;
2063 context->padDataLength++;
2066 /* not enough data to encrypt yet? then return */
2067 if (context->padDataLength != context->blockSize) return CKR_OK;
2068 /* encrypt the current padded data */
2069 rv = (*context->update)(context->cipherInfo,context->macBuf,&outlen,
2070 SFTK_MAX_BLOCK_SIZE,context->padBuf,context->blockSize);
2071 if (rv != SECSuccess) return CKR_DEVICE_ERROR;
2074 /* save the residual */
2075 context->padDataLength = ulPartLen % context->blockSize;
2076 if (context->padDataLength) {
2077 PORT_Memcpy(context->padBuf,
2078 &pPart[ulPartLen-context->padDataLength],
2079 context->padDataLength);
2080 ulPartLen -= context->padDataLength;
2083 /* if we've exhausted our new buffer, we're done */
2084 if (ulPartLen == 0) { return CKR_OK; }
2086 /* run the data through out encrypter */
2087 while (ulPartLen) {
2088 rv = (*context->update)(context->cipherInfo, context->padBuf, &outlen,
2089 SFTK_MAX_BLOCK_SIZE, pPart, context->blockSize);
2090 if (rv != SECSuccess) return CKR_DEVICE_ERROR;
2091 /* paranoia.. make sure we exit the loop */
2092 PORT_Assert(ulPartLen >= context->blockSize);
2093 if (ulPartLen < context->blockSize) break;
2094 ulPartLen -= context->blockSize;
2097 return CKR_OK;
2101 /* NSC_SignUpdate continues a multiple-part signature operation,
2102 * where the signature is (will be) an appendix to the data,
2103 * and plaintext cannot be recovered from the signature */
2104 CK_RV NSC_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
2105 CK_ULONG ulPartLen)
2107 CHECK_FORK();
2109 return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN);
2113 /* NSC_SignFinal finishes a multiple-part signature operation,
2114 * returning the signature. */
2115 CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,
2116 CK_ULONG_PTR pulSignatureLen)
2118 SFTKSession *session;
2119 SFTKSessionContext *context;
2120 unsigned int outlen;
2121 unsigned int digestLen;
2122 unsigned int maxoutlen = *pulSignatureLen;
2123 unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
2124 CK_RV crv;
2125 SECStatus rv = SECSuccess;
2127 CHECK_FORK();
2129 /* make sure we're legal */
2130 *pulSignatureLen = 0;
2131 crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_TRUE,&session);
2132 if (crv != CKR_OK) return crv;
2134 if (!pSignature) {
2135 *pulSignatureLen = context->maxLen;
2136 goto finish;
2137 } else if (context->hashInfo) {
2138 (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
2139 rv = (*context->update)(context->cipherInfo, pSignature,
2140 &outlen, maxoutlen, tmpbuf, digestLen);
2141 *pulSignatureLen = (CK_ULONG) outlen;
2142 } else {
2143 /* deal with the last block if any residual */
2144 if (context->padDataLength) {
2145 /* fill out rest of pad buffer with pad magic*/
2146 int i;
2147 for (i=context->padDataLength; i < (int)context->blockSize; i++) {
2148 context->padBuf[i] = 0;
2150 rv = (*context->update)(context->cipherInfo,context->macBuf,
2151 &outlen,SFTK_MAX_BLOCK_SIZE,context->padBuf,context->blockSize);
2153 if (rv == SECSuccess) {
2154 PORT_Memcpy(pSignature,context->macBuf,context->macSize);
2155 *pulSignatureLen = context->macSize;
2159 sftk_FreeContext(context);
2160 sftk_SetContextByType(session, SFTK_SIGN, NULL);
2162 finish:
2163 sftk_FreeSession(session);
2165 return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
2168 /* NSC_Sign signs (encrypts with private key) data in a single part,
2169 * where the signature is (will be) an appendix to the data,
2170 * and plaintext cannot be recovered from the signature */
2171 CK_RV NSC_Sign(CK_SESSION_HANDLE hSession,
2172 CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,
2173 CK_ULONG_PTR pulSignatureLen)
2175 SFTKSession *session;
2176 SFTKSessionContext *context;
2177 unsigned int outlen;
2178 unsigned int maxoutlen = *pulSignatureLen;
2179 CK_RV crv,crv2;
2180 SECStatus rv = SECSuccess;
2182 CHECK_FORK();
2184 /* make sure we're legal */
2185 crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_FALSE,&session);
2186 if (crv != CKR_OK) return crv;
2188 if (!pSignature) {
2189 *pulSignatureLen = context->maxLen;
2190 goto finish;
2193 /* multi part Signing are completely implemented by SignUpdate and
2194 * sign Final */
2195 if (context->multi) {
2196 sftk_FreeSession(session);
2197 crv = NSC_SignUpdate(hSession,pData,ulDataLen);
2198 if (crv != CKR_OK) *pulSignatureLen = 0;
2199 crv2 = NSC_SignFinal(hSession, pSignature, pulSignatureLen);
2200 return crv == CKR_OK ? crv2 :crv;
2203 rv = (*context->update)(context->cipherInfo, pSignature,
2204 &outlen, maxoutlen, pData, ulDataLen);
2205 *pulSignatureLen = (CK_ULONG) outlen;
2206 sftk_FreeContext(context);
2207 sftk_SetContextByType(session, SFTK_SIGN, NULL);
2209 finish:
2210 sftk_FreeSession(session);
2212 return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
2217 ************** Crypto Functions: Sign Recover ************************
2219 /* NSC_SignRecoverInit initializes a signature operation,
2220 * where the (digest) data can be recovered from the signature.
2221 * E.g. encryption with the user's private key */
2222 CK_RV NSC_SignRecoverInit(CK_SESSION_HANDLE hSession,
2223 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
2225 CHECK_FORK();
2227 switch (pMechanism->mechanism) {
2228 case CKM_RSA_PKCS:
2229 case CKM_RSA_X_509:
2230 return NSC_SignInit(hSession,pMechanism,hKey);
2231 default:
2232 break;
2234 return CKR_MECHANISM_INVALID;
2238 /* NSC_SignRecover signs data in a single operation
2239 * where the (digest) data can be recovered from the signature.
2240 * E.g. encryption with the user's private key */
2241 CK_RV NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
2242 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
2244 CHECK_FORK();
2246 return NSC_Sign(hSession,pData,ulDataLen,pSignature,pulSignatureLen);
2250 ************** Crypto Functions: verify ************************
2253 /* Handle RSA Signature formatting */
2254 static SECStatus
2255 sftk_hashCheckSign(SFTKHashVerifyInfo *info, unsigned char *sig,
2256 unsigned int sigLen, unsigned char *digest, unsigned int digestLen)
2258 return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen,
2259 digest, digestLen);
2262 SECStatus
2263 RSA_HashCheckSign(SECOidTag hashOid, NSSLOWKEYPublicKey *key,
2264 unsigned char *sig, unsigned int sigLen,
2265 unsigned char *digest, unsigned int digestLen)
2268 SECItem it;
2269 SGNDigestInfo *di = NULL;
2270 SECStatus rv = SECSuccess;
2272 it.data = NULL;
2274 if (key == NULL) goto loser;
2276 it.len = nsslowkey_PublicModulusLen(key);
2277 if (!it.len) goto loser;
2279 it.data = (unsigned char *) PORT_Alloc(it.len);
2280 if (it.data == NULL) goto loser;
2282 /* decrypt the block */
2283 rv = RSA_CheckSignRecover(key, it.data, &it.len, it.len, sig, sigLen);
2284 if (rv != SECSuccess) goto loser;
2286 di = SGN_DecodeDigestInfo(&it);
2287 if (di == NULL) goto loser;
2288 if (di->digest.len != digestLen) goto loser;
2290 /* make sure the tag is OK */
2291 if (SECOID_GetAlgorithmTag(&di->digestAlgorithm) != hashOid) {
2292 goto loser;
2294 /* make sure the "parameters" are not too bogus. */
2295 if (di->digestAlgorithm.parameters.len > 2) {
2296 goto loser;
2298 /* Now check the signature */
2299 if (PORT_Memcmp(digest, di->digest.data, di->digest.len) == 0) {
2300 goto done;
2303 loser:
2304 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
2305 rv = SECFailure;
2307 done:
2308 if (it.data != NULL) PORT_Free(it.data);
2309 if (di != NULL) SGN_DestroyDigestInfo(di);
2311 return rv;
2314 /* NSC_VerifyInit initializes a verification operation,
2315 * where the signature is an appendix to the data,
2316 * and plaintext cannot be recovered from the signature (e.g. DSA) */
2317 CK_RV NSC_VerifyInit(CK_SESSION_HANDLE hSession,
2318 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
2320 SFTKSession *session;
2321 SFTKObject *key;
2322 SFTKSessionContext *context;
2323 CK_KEY_TYPE key_type;
2324 CK_RV crv = CKR_OK;
2325 NSSLOWKEYPublicKey *pubKey;
2326 SFTKHashVerifyInfo *info = NULL;
2328 CHECK_FORK();
2330 /* Block Cipher MACing Algorithms use a different Context init method..*/
2331 crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY);
2332 if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv;
2334 session = sftk_SessionFromHandle(hSession);
2335 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2336 crv = sftk_InitGeneric(session,&context,SFTK_VERIFY,&key,hKey,&key_type,
2337 CKO_PUBLIC_KEY,CKA_VERIFY);
2338 if (crv != CKR_OK) {
2339 sftk_FreeSession(session);
2340 return crv;
2343 context->multi = PR_FALSE;
2345 #define INIT_RSA_VFY_MECH(mmm) \
2346 case CKM_ ## mmm ## _RSA_PKCS: \
2347 context->multi = PR_TRUE; \
2348 crv = sftk_doSub ## mmm (context); \
2349 if (crv != CKR_OK) break; \
2350 context->verify = (SFTKVerify) sftk_hashCheckSign; \
2351 info = PORT_New(SFTKHashVerifyInfo); \
2352 if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \
2353 info->hashOid = SEC_OID_ ## mmm ; \
2354 goto finish_rsa;
2356 switch(pMechanism->mechanism) {
2357 INIT_RSA_VFY_MECH(MD5)
2358 INIT_RSA_VFY_MECH(MD2)
2359 INIT_RSA_VFY_MECH(SHA1)
2360 INIT_RSA_VFY_MECH(SHA256)
2361 INIT_RSA_VFY_MECH(SHA384)
2362 INIT_RSA_VFY_MECH(SHA512)
2364 case CKM_RSA_PKCS:
2365 context->verify = (SFTKVerify) RSA_CheckSign;
2366 goto finish_rsa;
2367 case CKM_RSA_X_509:
2368 context->verify = (SFTKVerify) RSA_CheckSignRaw;
2369 finish_rsa:
2370 if (key_type != CKK_RSA) {
2371 crv = CKR_KEY_TYPE_INCONSISTENT;
2372 break;
2374 pubKey = sftk_GetPubKey(key,CKK_RSA,&crv);
2375 if (pubKey == NULL) {
2376 break;
2378 if (info) {
2379 info->key = pubKey;
2380 context->cipherInfo = info;
2381 context->destroy = sftk_Space;
2382 } else {
2383 context->cipherInfo = pubKey;
2384 context->destroy = sftk_Null;
2386 break;
2387 case CKM_DSA_SHA1:
2388 context->multi = PR_TRUE;
2389 crv = sftk_doSubSHA1(context);
2390 if (crv != CKR_OK) break;
2391 /* fall through */
2392 case CKM_DSA:
2393 if (key_type != CKK_DSA) {
2394 crv = CKR_KEY_TYPE_INCONSISTENT;
2395 break;
2397 pubKey = sftk_GetPubKey(key,CKK_DSA,&crv);
2398 if (pubKey == NULL) {
2399 break;
2401 context->cipherInfo = pubKey;
2402 context->verify = (SFTKVerify) nsc_DSA_Verify_Stub;
2403 context->destroy = sftk_Null;
2404 break;
2405 #ifdef NSS_ENABLE_ECC
2406 case CKM_ECDSA_SHA1:
2407 context->multi = PR_TRUE;
2408 crv = sftk_doSubSHA1(context);
2409 if (crv != CKR_OK) break;
2410 /* fall through */
2411 case CKM_ECDSA:
2412 if (key_type != CKK_EC) {
2413 crv = CKR_KEY_TYPE_INCONSISTENT;
2414 break;
2416 pubKey = sftk_GetPubKey(key,CKK_EC,&crv);
2417 if (pubKey == NULL) {
2418 crv = CKR_HOST_MEMORY;
2419 break;
2421 context->cipherInfo = pubKey;
2422 context->verify = (SFTKVerify) nsc_ECDSAVerifyStub;
2423 context->destroy = sftk_Null;
2424 break;
2425 #endif /* NSS_ENABLE_ECC */
2427 INIT_HMAC_MECH(MD2)
2428 INIT_HMAC_MECH(MD5)
2429 INIT_HMAC_MECH(SHA256)
2430 INIT_HMAC_MECH(SHA384)
2431 INIT_HMAC_MECH(SHA512)
2433 case CKM_SHA_1_HMAC_GENERAL:
2434 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,
2435 *(CK_ULONG *)pMechanism->pParameter);
2436 break;
2437 case CKM_SHA_1_HMAC:
2438 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH);
2439 break;
2441 case CKM_SSL3_MD5_MAC:
2442 crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key,
2443 *(CK_ULONG *)pMechanism->pParameter);
2444 break;
2445 case CKM_SSL3_SHA1_MAC:
2446 crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key,
2447 *(CK_ULONG *)pMechanism->pParameter);
2448 break;
2449 case CKM_TLS_PRF_GENERAL:
2450 crv = sftk_TLSPRFInit(context, key, key_type);
2451 break;
2453 default:
2454 crv = CKR_MECHANISM_INVALID;
2455 break;
2458 if (crv != CKR_OK) {
2459 if (info) PORT_Free(info);
2460 PORT_Free(context);
2461 sftk_FreeSession(session);
2462 return crv;
2464 sftk_SetContextByType(session, SFTK_VERIFY, context);
2465 sftk_FreeSession(session);
2466 return CKR_OK;
2469 /* NSC_Verify verifies a signature in a single-part operation,
2470 * where the signature is an appendix to the data,
2471 * and plaintext cannot be recovered from the signature */
2472 CK_RV NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
2473 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
2475 SFTKSession *session;
2476 SFTKSessionContext *context;
2477 CK_RV crv, crv2;
2478 SECStatus rv;
2480 CHECK_FORK();
2482 /* make sure we're legal */
2483 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_FALSE,&session);
2484 if (crv != CKR_OK) return crv;
2486 /* multi part Verifying are completely implemented by VerifyUpdate and
2487 * VerifyFinal */
2488 if (context->multi) {
2489 sftk_FreeSession(session);
2490 crv = NSC_VerifyUpdate(hSession, pData, ulDataLen);
2491 crv2 = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen);
2492 return crv == CKR_OK ? crv2 :crv;
2495 rv = (*context->verify)(context->cipherInfo,pSignature, ulSignatureLen,
2496 pData, ulDataLen);
2497 sftk_FreeContext(context);
2498 sftk_SetContextByType(session, SFTK_VERIFY, NULL);
2499 sftk_FreeSession(session);
2501 return (rv == SECSuccess) ? CKR_OK : CKR_SIGNATURE_INVALID;
2506 /* NSC_VerifyUpdate continues a multiple-part verification operation,
2507 * where the signature is an appendix to the data,
2508 * and plaintext cannot be recovered from the signature */
2509 CK_RV NSC_VerifyUpdate( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
2510 CK_ULONG ulPartLen)
2512 CHECK_FORK();
2514 return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY);
2518 /* NSC_VerifyFinal finishes a multiple-part verification operation,
2519 * checking the signature. */
2520 CK_RV NSC_VerifyFinal(CK_SESSION_HANDLE hSession,
2521 CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)
2523 SFTKSession *session;
2524 SFTKSessionContext *context;
2525 unsigned int outlen;
2526 unsigned int digestLen;
2527 unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
2528 CK_RV crv;
2529 SECStatus rv = SECSuccess;
2531 CHECK_FORK();
2533 /* make sure we're legal */
2534 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_TRUE,&session);
2535 if (crv != CKR_OK) return crv;
2537 if (context->hashInfo) {
2538 (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
2539 rv = (*context->verify)(context->cipherInfo, pSignature,
2540 ulSignatureLen, tmpbuf, digestLen);
2541 } else {
2542 if (context->padDataLength) {
2543 /* fill out rest of pad buffer with pad magic*/
2544 int i;
2545 for (i=context->padDataLength; i < (int)context->blockSize; i++) {
2546 context->padBuf[i] = 0;
2548 rv = (*context->update)(context->cipherInfo,context->macBuf,
2549 &outlen,SFTK_MAX_BLOCK_SIZE,context->padBuf,context->blockSize);
2551 if (rv == SECSuccess) {
2552 rv =(PORT_Memcmp(pSignature,context->macBuf,context->macSize) == 0)
2553 ? SECSuccess : SECFailure;
2557 sftk_FreeContext(context);
2558 sftk_SetContextByType(session, SFTK_VERIFY, NULL);
2559 sftk_FreeSession(session);
2560 return (rv == SECSuccess) ? CKR_OK : CKR_SIGNATURE_INVALID;
2565 ************** Crypto Functions: Verify Recover ************************
2568 /* NSC_VerifyRecoverInit initializes a signature verification operation,
2569 * where the data is recovered from the signature.
2570 * E.g. Decryption with the user's public key */
2571 CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
2572 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
2574 SFTKSession *session;
2575 SFTKObject *key;
2576 SFTKSessionContext *context;
2577 CK_KEY_TYPE key_type;
2578 CK_RV crv = CKR_OK;
2579 NSSLOWKEYPublicKey *pubKey;
2581 CHECK_FORK();
2583 session = sftk_SessionFromHandle(hSession);
2584 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2585 crv = sftk_InitGeneric(session,&context,SFTK_VERIFY_RECOVER,
2586 &key,hKey,&key_type,CKO_PUBLIC_KEY,CKA_VERIFY_RECOVER);
2587 if (crv != CKR_OK) {
2588 sftk_FreeSession(session);
2589 return crv;
2592 context->multi = PR_TRUE;
2594 switch(pMechanism->mechanism) {
2595 case CKM_RSA_PKCS:
2596 case CKM_RSA_X_509:
2597 if (key_type != CKK_RSA) {
2598 crv = CKR_KEY_TYPE_INCONSISTENT;
2599 break;
2601 context->multi = PR_FALSE;
2602 pubKey = sftk_GetPubKey(key,CKK_RSA,&crv);
2603 if (pubKey == NULL) {
2604 break;
2606 context->cipherInfo = pubKey;
2607 context->update = (SFTKCipher) (pMechanism->mechanism == CKM_RSA_X_509
2608 ? RSA_CheckSignRecoverRaw : RSA_CheckSignRecover);
2609 context->destroy = sftk_Null;
2610 break;
2611 default:
2612 crv = CKR_MECHANISM_INVALID;
2613 break;
2616 if (crv != CKR_OK) {
2617 PORT_Free(context);
2618 sftk_FreeSession(session);
2619 return crv;
2621 sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context);
2622 sftk_FreeSession(session);
2623 return CKR_OK;
2627 /* NSC_VerifyRecover verifies a signature in a single-part operation,
2628 * where the data is recovered from the signature.
2629 * E.g. Decryption with the user's public key */
2630 CK_RV NSC_VerifyRecover(CK_SESSION_HANDLE hSession,
2631 CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,
2632 CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)
2634 SFTKSession *session;
2635 SFTKSessionContext *context;
2636 unsigned int outlen;
2637 unsigned int maxoutlen = *pulDataLen;
2638 CK_RV crv;
2639 SECStatus rv;
2641 CHECK_FORK();
2643 /* make sure we're legal */
2644 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY_RECOVER,
2645 PR_FALSE,&session);
2646 if (crv != CKR_OK) return crv;
2647 if (pData == NULL) {
2648 /* to return the actual size, we need to do the decrypt, just return
2649 * the max size, which is the size of the input signature. */
2650 *pulDataLen = ulSignatureLen;
2651 rv = SECSuccess;
2652 goto finish;
2655 rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
2656 pSignature, ulSignatureLen);
2657 *pulDataLen = (CK_ULONG) outlen;
2659 sftk_FreeContext(context);
2660 sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, NULL);
2661 finish:
2662 sftk_FreeSession(session);
2663 return (rv == SECSuccess) ? CKR_OK : CKR_SIGNATURE_INVALID;
2667 **************************** Random Functions: ************************
2670 /* NSC_SeedRandom mixes additional seed material into the token's random number
2671 * generator. */
2672 CK_RV NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
2673 CK_ULONG ulSeedLen)
2675 SECStatus rv;
2677 CHECK_FORK();
2679 rv = RNG_RandomUpdate(pSeed, ulSeedLen);
2680 return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
2683 /* NSC_GenerateRandom generates random data. */
2684 CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
2685 CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
2687 SECStatus rv;
2689 CHECK_FORK();
2691 rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen);
2692 return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
2696 **************************** Key Functions: ************************
2701 * generate a password based encryption key. This code uses
2702 * PKCS5 to do the work.
2704 static CK_RV
2705 nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
2706 void *buf, CK_ULONG *key_length, PRBool faulty3DES)
2708 SECItem *pbe_key = NULL, iv, pwitem;
2709 CK_PBE_PARAMS *pbe_params = NULL;
2710 CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
2712 *key_length = 0;
2713 iv.data = NULL; iv.len = 0;
2715 if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
2716 pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
2717 pwitem.data = (unsigned char *)pbkd2_params->pPassword;
2718 /* was this a typo in the PKCS #11 spec? */
2719 pwitem.len = *pbkd2_params->ulPasswordLen;
2720 } else {
2721 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
2722 pwitem.data = (unsigned char *)pbe_params->pPassword;
2723 pwitem.len = pbe_params->ulPasswordLen;
2725 pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES);
2726 if (pbe_key == NULL) {
2727 return CKR_HOST_MEMORY;
2730 PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
2731 *key_length = pbe_key->len;
2732 SECITEM_ZfreeItem(pbe_key, PR_TRUE);
2733 pbe_key = NULL;
2735 if (iv.data) {
2736 if (pbe_params && pbe_params->pInitVector != NULL) {
2737 PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len);
2739 PORT_Free(iv.data);
2742 return CKR_OK;
2744 static CK_RV
2745 nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
2747 SFTKAttribute *attribute;
2748 CK_ULONG counter;
2749 unsigned int seedBits = 0;
2750 unsigned int primeBits;
2751 unsigned int j;
2752 CK_RV crv = CKR_OK;
2753 PQGParams *params = NULL;
2754 PQGVerify *vfy = NULL;
2755 SECStatus rv;
2757 attribute = sftk_FindAttribute(key, CKA_PRIME_BITS);
2758 if (attribute == NULL) {
2759 return CKR_TEMPLATE_INCOMPLETE;
2761 primeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
2762 sftk_FreeAttribute(attribute);
2763 j = PQG_PBITS_TO_INDEX(primeBits);
2764 if (j == (unsigned int)-1) {
2765 return CKR_ATTRIBUTE_VALUE_INVALID;
2768 attribute = sftk_FindAttribute(key, CKA_NETSCAPE_PQG_SEED_BITS);
2769 if (attribute != NULL) {
2770 seedBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
2771 sftk_FreeAttribute(attribute);
2774 sftk_DeleteAttributeType(key,CKA_PRIME_BITS);
2775 sftk_DeleteAttributeType(key,CKA_NETSCAPE_PQG_SEED_BITS);
2777 if (seedBits == 0) {
2778 rv = PQG_ParamGen(j, &params, &vfy);
2779 } else {
2780 rv = PQG_ParamGenSeedLen(j,seedBits/8, &params, &vfy);
2783 if (rv != SECSuccess) {
2784 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2785 sftk_fatalError = PR_TRUE;
2787 return CKR_DEVICE_ERROR;
2789 crv = sftk_AddAttributeType(key,CKA_PRIME,
2790 params->prime.data, params->prime.len);
2791 if (crv != CKR_OK) goto loser;
2792 crv = sftk_AddAttributeType(key,CKA_SUBPRIME,
2793 params->subPrime.data, params->subPrime.len);
2794 if (crv != CKR_OK) goto loser;
2795 crv = sftk_AddAttributeType(key,CKA_BASE,
2796 params->base.data, params->base.len);
2797 if (crv != CKR_OK) goto loser;
2798 counter = vfy->counter;
2799 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_COUNTER,
2800 &counter, sizeof(counter));
2801 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_SEED,
2802 vfy->seed.data, vfy->seed.len);
2803 if (crv != CKR_OK) goto loser;
2804 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_H,
2805 vfy->h.data, vfy->h.len);
2806 if (crv != CKR_OK) goto loser;
2808 loser:
2809 if (params) {
2810 PQG_DestroyParams(params);
2812 if (vfy) {
2813 PQG_DestroyVerify(vfy);
2815 return crv;
2819 static CK_RV
2820 nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
2821 CK_ULONG *key_length)
2823 CK_RV crv = CKR_OK;
2825 switch (mechanism) {
2826 case CKM_RC2_KEY_GEN:
2827 *key_type = CKK_RC2;
2828 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
2829 break;
2830 #if NSS_SOFTOKEN_DOES_RC5
2831 case CKM_RC5_KEY_GEN:
2832 *key_type = CKK_RC5;
2833 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
2834 break;
2835 #endif
2836 case CKM_RC4_KEY_GEN:
2837 *key_type = CKK_RC4;
2838 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
2839 break;
2840 case CKM_GENERIC_SECRET_KEY_GEN:
2841 *key_type = CKK_GENERIC_SECRET;
2842 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
2843 break;
2844 case CKM_CDMF_KEY_GEN:
2845 *key_type = CKK_CDMF;
2846 *key_length = 8;
2847 break;
2848 case CKM_DES_KEY_GEN:
2849 *key_type = CKK_DES;
2850 *key_length = 8;
2851 break;
2852 case CKM_DES2_KEY_GEN:
2853 *key_type = CKK_DES2;
2854 *key_length = 16;
2855 break;
2856 case CKM_DES3_KEY_GEN:
2857 *key_type = CKK_DES3;
2858 *key_length = 24;
2859 break;
2860 case CKM_CAMELLIA_KEY_GEN:
2861 *key_type = CKK_CAMELLIA;
2862 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
2863 break;
2864 case CKM_AES_KEY_GEN:
2865 *key_type = CKK_AES;
2866 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
2867 break;
2868 default:
2869 PORT_Assert(0);
2870 crv = CKR_MECHANISM_INVALID;
2871 break;
2874 return crv;
2877 CK_RV
2878 nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
2880 SECItem salt;
2881 CK_PBE_PARAMS *pbe_params = NULL;
2882 NSSPKCS5PBEParameter *params;
2883 PRArenaPool *arena = NULL;
2884 SECStatus rv;
2886 *pbe = NULL;
2888 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2889 if (arena == NULL) {
2890 return CKR_HOST_MEMORY;
2893 params = (NSSPKCS5PBEParameter *) PORT_ArenaZAlloc(arena,
2894 sizeof(NSSPKCS5PBEParameter));
2895 if (params == NULL) {
2896 PORT_FreeArena(arena,PR_TRUE);
2897 return CKR_HOST_MEMORY;
2900 params->poolp = arena;
2901 params->ivLen = 0;
2902 params->pbeType = NSSPKCS5_PKCS12_V2;
2903 params->hashType = HASH_AlgSHA1;
2904 params->encAlg = SEC_OID_SHA1; /* any invalid value */
2905 params->is2KeyDES = PR_FALSE;
2906 params->keyID = pbeBitGenIntegrityKey;
2907 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
2908 params->iter = pbe_params->ulIteration;
2910 salt.data = (unsigned char *)pbe_params->pSalt;
2911 salt.len = (unsigned int)pbe_params->ulSaltLen;
2912 rv = SECITEM_CopyItem(arena,&params->salt,&salt);
2913 if (rv != SECSuccess) {
2914 PORT_FreeArena(arena,PR_TRUE);
2915 return CKR_HOST_MEMORY;
2917 switch (pMechanism->mechanism) {
2918 case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
2919 case CKM_PBA_SHA1_WITH_SHA1_HMAC:
2920 params->hashType = HASH_AlgSHA1;
2921 params->keyLen = 20;
2922 break;
2923 case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
2924 params->hashType = HASH_AlgMD5;
2925 params->keyLen = 16;
2926 break;
2927 case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
2928 params->hashType = HASH_AlgMD2;
2929 params->keyLen = 16;
2930 break;
2931 default:
2932 PORT_FreeArena(arena,PR_TRUE);
2933 return CKR_MECHANISM_INVALID;
2935 *pbe = params;
2936 return CKR_OK;
2939 /* maybe this should be table driven? */
2940 static CK_RV
2941 nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
2942 CK_KEY_TYPE *key_type, CK_ULONG *key_length)
2944 CK_RV crv = CKR_OK;
2945 SECOidData *oid;
2946 CK_PBE_PARAMS *pbe_params = NULL;
2947 NSSPKCS5PBEParameter *params = NULL;
2948 CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
2949 SECItem salt;
2950 CK_ULONG iteration = 0;
2952 *pbe = NULL;
2954 oid = SECOID_FindOIDByMechanism(pMechanism->mechanism);
2955 if (oid == NULL) {
2956 return CKR_MECHANISM_INVALID;
2959 if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
2960 pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
2961 if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) {
2962 return CKR_MECHANISM_PARAM_INVALID;
2964 salt.data = (unsigned char *)pbkd2_params->pSaltSourceData;
2965 salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen;
2966 iteration = pbkd2_params->iterations;
2967 } else {
2968 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
2969 salt.data = (unsigned char *)pbe_params->pSalt;
2970 salt.len = (unsigned int)pbe_params->ulSaltLen;
2971 iteration = pbe_params->ulIteration;
2973 params=nsspkcs5_NewParam(oid->offset, &salt, iteration);
2974 if (params == NULL) {
2975 return CKR_MECHANISM_INVALID;
2978 switch (params->encAlg) {
2979 case SEC_OID_DES_CBC:
2980 *key_type = CKK_DES;
2981 *key_length = params->keyLen;
2982 break;
2983 case SEC_OID_DES_EDE3_CBC:
2984 *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3;
2985 *key_length = params->keyLen;
2986 break;
2987 case SEC_OID_RC2_CBC:
2988 *key_type = CKK_RC2;
2989 *key_length = params->keyLen;
2990 break;
2991 case SEC_OID_RC4:
2992 *key_type = CKK_RC4;
2993 *key_length = params->keyLen;
2994 break;
2995 case SEC_OID_PKCS5_PBKDF2:
2996 /* sigh, PKCS #11 currently only defines SHA1 for the KDF hash type.
2997 * we do the check here because this where we would handle multiple
2998 * hash types in the future */
2999 if (pbkd2_params == NULL ||
3000 pbkd2_params->prf != CKP_PKCS5_PBKD2_HMAC_SHA1) {
3001 crv = CKR_MECHANISM_PARAM_INVALID;
3002 break;
3004 /* key type must already be set */
3005 if (*key_type == CKK_INVALID_KEY_TYPE) {
3006 crv = CKR_TEMPLATE_INCOMPLETE;
3007 break;
3009 /* PBKDF2 needs to calculate the key length from the other parameters
3011 if (*key_length == 0) {
3012 *key_length = sftk_MapKeySize(*key_type);
3014 if (*key_length == 0) {
3015 crv = CKR_TEMPLATE_INCOMPLETE;
3016 break;
3018 params->keyLen = *key_length;
3019 break;
3020 default:
3021 crv = CKR_MECHANISM_INVALID;
3022 nsspkcs5_DestroyPBEParameter(params);
3023 break;
3025 if (crv == CKR_OK) {
3026 *pbe = params;
3028 return crv;
3031 /* NSC_GenerateKey generates a secret key, creating a new key object. */
3032 CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
3033 CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,
3034 CK_OBJECT_HANDLE_PTR phKey)
3036 SFTKObject *key;
3037 SFTKSession *session;
3038 PRBool checkWeak = PR_FALSE;
3039 CK_ULONG key_length = 0;
3040 CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE;
3041 CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
3042 CK_RV crv = CKR_OK;
3043 CK_BBOOL cktrue = CK_TRUE;
3044 int i;
3045 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
3046 unsigned char buf[MAX_KEY_LEN];
3047 enum {nsc_pbe, nsc_ssl, nsc_bulk, nsc_param} key_gen_type;
3048 NSSPKCS5PBEParameter *pbe_param;
3049 SSL3RSAPreMasterSecret *rsa_pms;
3050 CK_VERSION *version;
3051 /* in very old versions of NSS, there were implementation errors with key
3052 * generation methods. We want to beable to read these, but not
3053 * produce them any more. The affected algorithm was 3DES.
3055 PRBool faultyPBE3DES = PR_FALSE;
3057 CHECK_FORK();
3059 if (!slot) {
3060 return CKR_SESSION_HANDLE_INVALID;
3063 * now lets create an object to hang the attributes off of
3065 key = sftk_NewObject(slot); /* fill in the handle later */
3066 if (key == NULL) {
3067 return CKR_HOST_MEMORY;
3071 * load the template values into the object
3073 for (i=0; i < (int) ulCount; i++) {
3074 if (pTemplate[i].type == CKA_VALUE_LEN) {
3075 key_length = *(CK_ULONG *)pTemplate[i].pValue;
3076 continue;
3078 /* some algorithms need keytype specified */
3079 if (pTemplate[i].type == CKA_KEY_TYPE) {
3080 key_type = *(CK_ULONG *)pTemplate[i].pValue;
3081 continue;
3084 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i]));
3085 if (crv != CKR_OK) break;
3087 if (crv != CKR_OK) {
3088 sftk_FreeObject(key);
3089 return crv;
3092 /* make sure we don't have any class, key_type, or value fields */
3093 sftk_DeleteAttributeType(key,CKA_CLASS);
3094 sftk_DeleteAttributeType(key,CKA_KEY_TYPE);
3095 sftk_DeleteAttributeType(key,CKA_VALUE);
3097 /* Now Set up the parameters to generate the key (based on mechanism) */
3098 key_gen_type = nsc_bulk; /* bulk key by default */
3099 switch (pMechanism->mechanism) {
3100 case CKM_CDMF_KEY_GEN:
3101 case CKM_DES_KEY_GEN:
3102 case CKM_DES2_KEY_GEN:
3103 case CKM_DES3_KEY_GEN:
3104 checkWeak = PR_TRUE;
3105 case CKM_RC2_KEY_GEN:
3106 case CKM_RC4_KEY_GEN:
3107 case CKM_GENERIC_SECRET_KEY_GEN:
3108 case CKM_CAMELLIA_KEY_GEN:
3109 case CKM_AES_KEY_GEN:
3110 #if NSS_SOFTOKEN_DOES_RC5
3111 case CKM_RC5_KEY_GEN:
3112 #endif
3113 crv = nsc_SetupBulkKeyGen(pMechanism->mechanism,&key_type,&key_length);
3114 break;
3115 case CKM_SSL3_PRE_MASTER_KEY_GEN:
3116 key_type = CKK_GENERIC_SECRET;
3117 key_length = 48;
3118 key_gen_type = nsc_ssl;
3119 break;
3120 case CKM_PBA_SHA1_WITH_SHA1_HMAC:
3121 case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
3122 case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
3123 case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
3124 key_gen_type = nsc_pbe;
3125 key_type = CKK_GENERIC_SECRET;
3126 crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param);
3127 break;
3128 case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
3129 faultyPBE3DES = PR_TRUE;
3130 case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:
3131 case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
3132 case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
3133 case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC:
3134 case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4:
3135 case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4:
3136 case CKM_PBE_SHA1_DES3_EDE_CBC:
3137 case CKM_PBE_SHA1_DES2_EDE_CBC:
3138 case CKM_PBE_SHA1_RC2_128_CBC:
3139 case CKM_PBE_SHA1_RC2_40_CBC:
3140 case CKM_PBE_SHA1_RC4_128:
3141 case CKM_PBE_SHA1_RC4_40:
3142 case CKM_PBE_MD5_DES_CBC:
3143 case CKM_PBE_MD2_DES_CBC:
3144 case CKM_PKCS5_PBKD2:
3145 key_gen_type = nsc_pbe;
3146 crv = nsc_SetupPBEKeyGen(pMechanism,&pbe_param, &key_type, &key_length);
3147 break;
3148 case CKM_DSA_PARAMETER_GEN:
3149 key_gen_type = nsc_param;
3150 key_type = CKK_DSA;
3151 objclass = CKO_KG_PARAMETERS;
3152 crv = CKR_OK;
3153 break;
3154 default:
3155 crv = CKR_MECHANISM_INVALID;
3156 break;
3159 /* make sure we aren't going to overflow the buffer */
3160 if (sizeof(buf) < key_length) {
3161 /* someone is getting pretty optimistic about how big their key can
3162 * be... */
3163 crv = CKR_TEMPLATE_INCONSISTENT;
3166 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3168 /* if there was no error,
3169 * key_type *MUST* be set in the switch statement above */
3170 PORT_Assert( key_type != CKK_INVALID_KEY_TYPE );
3173 * now to the actual key gen.
3175 switch (key_gen_type) {
3176 case nsc_pbe:
3177 crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length,
3178 faultyPBE3DES);
3179 nsspkcs5_DestroyPBEParameter(pbe_param);
3180 break;
3181 case nsc_ssl:
3182 rsa_pms = (SSL3RSAPreMasterSecret *)buf;
3183 version = (CK_VERSION *)pMechanism->pParameter;
3184 rsa_pms->client_version[0] = version->major;
3185 rsa_pms->client_version[1] = version->minor;
3186 crv =
3187 NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random));
3188 break;
3189 case nsc_bulk:
3190 /* get the key, check for weak keys and repeat if found */
3191 do {
3192 crv = NSC_GenerateRandom(0, buf, key_length);
3193 } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf,key_type));
3194 break;
3195 case nsc_param:
3196 /* generate parameters */
3197 *buf = 0;
3198 crv = nsc_parameter_gen(key_type,key);
3199 break;
3202 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3204 /* Add the class, key_type, and value */
3205 crv = sftk_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS));
3206 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3207 crv = sftk_AddAttributeType(key,CKA_KEY_TYPE,&key_type,sizeof(CK_KEY_TYPE));
3208 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3209 if (key_length != 0) {
3210 crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length);
3211 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3214 /* get the session */
3215 session = sftk_SessionFromHandle(hSession);
3216 if (session == NULL) {
3217 sftk_FreeObject(key);
3218 return CKR_SESSION_HANDLE_INVALID;
3222 * handle the base object stuff
3224 crv = sftk_handleObject(key,session);
3225 sftk_FreeSession(session);
3226 if (sftk_isTrue(key,CKA_SENSITIVE)) {
3227 sftk_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL));
3229 if (!sftk_isTrue(key,CKA_EXTRACTABLE)) {
3230 sftk_forceAttribute(key,CKA_NEVER_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL));
3233 *phKey = key->handle;
3234 sftk_FreeObject(key);
3235 return crv;
3238 #define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */
3239 #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */
3242 * FIPS 140-2 pairwise consistency check utilized to validate key pair.
3244 * This function returns
3245 * CKR_OK if pairwise consistency check passed
3246 * CKR_GENERAL_ERROR if pairwise consistency check failed
3247 * other error codes if paiswise consistency check could not be
3248 * performed, for example, CKR_HOST_MEMORY.
3250 static CK_RV
3251 sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
3252 SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType)
3255 * Key type Mechanism type
3256 * --------------------------------
3257 * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS
3258 * others => CKM_INVALID_MECHANISM
3260 * For sign/verify: CKK_RSA => CKM_RSA_PKCS
3261 * CKK_DSA => CKM_DSA
3262 * CKK_EC => CKM_ECDSA
3263 * others => CKM_INVALID_MECHANISM
3265 * None of these mechanisms has a parameter.
3267 CK_MECHANISM mech = {0, NULL, 0};
3269 CK_ULONG modulusLen;
3270 PRBool isEncryptable = PR_FALSE;
3271 PRBool canSignVerify = PR_FALSE;
3272 PRBool isDerivable = PR_FALSE;
3273 CK_RV crv;
3275 /* Variables used for Encrypt/Decrypt functions. */
3276 unsigned char *known_message = (unsigned char *)"Known Crypto Message";
3277 unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH];
3278 CK_ULONG bytes_decrypted;
3279 unsigned char *ciphertext;
3280 unsigned char *text_compared;
3281 CK_ULONG bytes_encrypted;
3282 CK_ULONG bytes_compared;
3284 /* Variables used for Signature/Verification functions. */
3285 /* always uses SHA-1 digest */
3286 unsigned char *known_digest = (unsigned char *)"Mozilla Rules World!";
3287 unsigned char *signature;
3288 CK_ULONG signature_length;
3290 if (keyType == CKK_RSA) {
3291 SFTKAttribute *attribute;
3293 /* Get modulus length of private key. */
3294 attribute = sftk_FindAttribute(privateKey, CKA_MODULUS);
3295 if (attribute == NULL) {
3296 return CKR_DEVICE_ERROR;
3298 modulusLen = attribute->attrib.ulValueLen;
3299 if (*(unsigned char *)attribute->attrib.pValue == 0) {
3300 modulusLen--;
3302 sftk_FreeAttribute(attribute);
3305 /**************************************************/
3306 /* Pairwise Consistency Check of Encrypt/Decrypt. */
3307 /**************************************************/
3309 isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT);
3312 * If the decryption attribute is set, attempt to encrypt
3313 * with the public key and decrypt with the private key.
3315 if (isEncryptable) {
3316 if (keyType != CKK_RSA) {
3317 return CKR_DEVICE_ERROR;
3319 bytes_encrypted = modulusLen;
3320 mech.mechanism = CKM_RSA_PKCS;
3322 /* Allocate space for ciphertext. */
3323 ciphertext = (unsigned char *) PORT_ZAlloc(bytes_encrypted);
3324 if (ciphertext == NULL) {
3325 return CKR_HOST_MEMORY;
3328 /* Prepare for encryption using the public key. */
3329 crv = NSC_EncryptInit(hSession, &mech, publicKey->handle);
3330 if (crv != CKR_OK) {
3331 PORT_Free(ciphertext);
3332 return crv;
3335 /* Encrypt using the public key. */
3336 crv = NSC_Encrypt(hSession,
3337 known_message,
3338 PAIRWISE_MESSAGE_LENGTH,
3339 ciphertext,
3340 &bytes_encrypted);
3341 if (crv != CKR_OK) {
3342 PORT_Free(ciphertext);
3343 return crv;
3346 /* Always use the smaller of these two values . . . */
3347 bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH);
3350 * If there was a failure, the plaintext
3351 * goes at the end, therefore . . .
3353 text_compared = ciphertext + bytes_encrypted - bytes_compared;
3356 * Check to ensure that ciphertext does
3357 * NOT EQUAL known input message text
3358 * per FIPS PUB 140-2 directive.
3360 if (PORT_Memcmp(text_compared, known_message,
3361 bytes_compared) == 0) {
3362 /* Set error to Invalid PRIVATE Key. */
3363 PORT_SetError(SEC_ERROR_INVALID_KEY);
3364 PORT_Free(ciphertext);
3365 return CKR_GENERAL_ERROR;
3368 /* Prepare for decryption using the private key. */
3369 crv = NSC_DecryptInit(hSession, &mech, privateKey->handle);
3370 if (crv != CKR_OK) {
3371 PORT_Free(ciphertext);
3372 return crv;
3375 memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH);
3378 * Initialize bytes decrypted to be the
3379 * expected PAIRWISE_MESSAGE_LENGTH.
3381 bytes_decrypted = PAIRWISE_MESSAGE_LENGTH;
3384 * Decrypt using the private key.
3385 * NOTE: No need to reset the
3386 * value of bytes_encrypted.
3388 crv = NSC_Decrypt(hSession,
3389 ciphertext,
3390 bytes_encrypted,
3391 plaintext,
3392 &bytes_decrypted);
3394 /* Finished with ciphertext; free it. */
3395 PORT_Free(ciphertext);
3397 if (crv != CKR_OK) {
3398 return crv;
3402 * Check to ensure that the output plaintext
3403 * does EQUAL known input message text.
3405 if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) ||
3406 (PORT_Memcmp(plaintext, known_message,
3407 PAIRWISE_MESSAGE_LENGTH) != 0)) {
3408 /* Set error to Bad PUBLIC Key. */
3409 PORT_SetError(SEC_ERROR_BAD_KEY);
3410 return CKR_GENERAL_ERROR;
3414 /**********************************************/
3415 /* Pairwise Consistency Check of Sign/Verify. */
3416 /**********************************************/
3418 canSignVerify = sftk_isTrue(privateKey, CKA_SIGN);
3420 if (canSignVerify) {
3421 /* Determine length of signature. */
3422 switch (keyType) {
3423 case CKK_RSA:
3424 signature_length = modulusLen;
3425 mech.mechanism = CKM_RSA_PKCS;
3426 break;
3427 case CKK_DSA:
3428 signature_length = DSA_SIGNATURE_LEN;
3429 mech.mechanism = CKM_DSA;
3430 break;
3431 #ifdef NSS_ENABLE_ECC
3432 case CKK_EC:
3433 signature_length = MAX_ECKEY_LEN * 2;
3434 mech.mechanism = CKM_ECDSA;
3435 break;
3436 #endif
3437 default:
3438 return CKR_DEVICE_ERROR;
3441 /* Allocate space for signature data. */
3442 signature = (unsigned char *) PORT_ZAlloc(signature_length);
3443 if (signature == NULL) {
3444 return CKR_HOST_MEMORY;
3447 /* Sign the known hash using the private key. */
3448 crv = NSC_SignInit(hSession, &mech, privateKey->handle);
3449 if (crv != CKR_OK) {
3450 PORT_Free(signature);
3451 return crv;
3454 crv = NSC_Sign(hSession,
3455 known_digest,
3456 PAIRWISE_DIGEST_LENGTH,
3457 signature,
3458 &signature_length);
3459 if (crv != CKR_OK) {
3460 PORT_Free(signature);
3461 return crv;
3464 /* Verify the known hash using the public key. */
3465 crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
3466 if (crv != CKR_OK) {
3467 PORT_Free(signature);
3468 return crv;
3471 crv = NSC_Verify(hSession,
3472 known_digest,
3473 PAIRWISE_DIGEST_LENGTH,
3474 signature,
3475 signature_length);
3477 /* Free signature data. */
3478 PORT_Free(signature);
3480 if ((crv == CKR_SIGNATURE_LEN_RANGE) ||
3481 (crv == CKR_SIGNATURE_INVALID)) {
3482 return CKR_GENERAL_ERROR;
3484 if (crv != CKR_OK) {
3485 return crv;
3489 /**********************************************/
3490 /* Pairwise Consistency Check for Derivation */
3491 /**********************************************/
3493 isDerivable = sftk_isTrue(privateKey, CKA_DERIVE);
3495 if (isDerivable) {
3497 * We are not doing consistency check for Diffie-Hellman Key -
3498 * otherwise it would be here
3499 * This is also true for Elliptic Curve Diffie-Hellman keys
3500 * NOTE: EC keys are currently subjected to pairwise
3501 * consistency check for signing/verification.
3504 * FIPS 140-2 had the following pairwise consistency test for
3505 * public and private keys used for key agreement:
3506 * If the keys are used to perform key agreement, then the
3507 * cryptographic module shall create a second, compatible
3508 * key pair. The cryptographic module shall perform both
3509 * sides of the key agreement algorithm and shall compare
3510 * the resulting shared values. If the shared values are
3511 * not equal, the test shall fail.
3512 * This test was removed in Change Notice 3.
3517 return CKR_OK;
3520 /* NSC_GenerateKeyPair generates a public-key/private-key pair,
3521 * creating new key objects. */
3522 CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession,
3523 CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
3524 CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
3525 CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
3526 CK_OBJECT_HANDLE_PTR phPrivateKey)
3528 SFTKObject * publicKey,*privateKey;
3529 SFTKSession * session;
3530 CK_KEY_TYPE key_type;
3531 CK_RV crv = CKR_OK;
3532 CK_BBOOL cktrue = CK_TRUE;
3533 SECStatus rv;
3534 CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
3535 CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
3536 int i;
3537 SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession);
3538 unsigned int bitSize;
3540 /* RSA */
3541 int public_modulus_bits = 0;
3542 SECItem pubExp;
3543 RSAPrivateKey * rsaPriv;
3545 /* DSA */
3546 PQGParams pqgParam;
3547 DHParams dhParam;
3548 DSAPrivateKey * dsaPriv;
3550 /* Diffie Hellman */
3551 int private_value_bits = 0;
3552 DHPrivateKey * dhPriv;
3554 #ifdef NSS_ENABLE_ECC
3555 /* Elliptic Curve Cryptography */
3556 SECItem ecEncodedParams; /* DER Encoded parameters */
3557 ECPrivateKey * ecPriv;
3558 ECParams * ecParams;
3559 #endif /* NSS_ENABLE_ECC */
3561 CHECK_FORK();
3563 if (!slot) {
3564 return CKR_SESSION_HANDLE_INVALID;
3567 * now lets create an object to hang the attributes off of
3569 publicKey = sftk_NewObject(slot); /* fill in the handle later */
3570 if (publicKey == NULL) {
3571 return CKR_HOST_MEMORY;
3575 * load the template values into the publicKey
3577 for (i=0; i < (int) ulPublicKeyAttributeCount; i++) {
3578 if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {
3579 public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
3580 continue;
3583 crv = sftk_AddAttributeType(publicKey,
3584 sftk_attr_expand(&pPublicKeyTemplate[i]));
3585 if (crv != CKR_OK) break;
3588 if (crv != CKR_OK) {
3589 sftk_FreeObject(publicKey);
3590 return CKR_HOST_MEMORY;
3593 privateKey = sftk_NewObject(slot); /* fill in the handle later */
3594 if (privateKey == NULL) {
3595 sftk_FreeObject(publicKey);
3596 return CKR_HOST_MEMORY;
3599 * now load the private key template
3601 for (i=0; i < (int) ulPrivateKeyAttributeCount; i++) {
3602 if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {
3603 private_value_bits = *(CK_ULONG *)pPrivateKeyTemplate[i].pValue;
3604 continue;
3607 crv = sftk_AddAttributeType(privateKey,
3608 sftk_attr_expand(&pPrivateKeyTemplate[i]));
3609 if (crv != CKR_OK) break;
3612 if (crv != CKR_OK) {
3613 sftk_FreeObject(publicKey);
3614 sftk_FreeObject(privateKey);
3615 return CKR_HOST_MEMORY;
3617 sftk_DeleteAttributeType(privateKey,CKA_CLASS);
3618 sftk_DeleteAttributeType(privateKey,CKA_KEY_TYPE);
3619 sftk_DeleteAttributeType(privateKey,CKA_VALUE);
3620 sftk_DeleteAttributeType(publicKey,CKA_CLASS);
3621 sftk_DeleteAttributeType(publicKey,CKA_KEY_TYPE);
3622 sftk_DeleteAttributeType(publicKey,CKA_VALUE);
3624 /* Now Set up the parameters to generate the key (based on mechanism) */
3625 switch (pMechanism->mechanism) {
3626 case CKM_RSA_PKCS_KEY_PAIR_GEN:
3627 /* format the keys */
3628 sftk_DeleteAttributeType(publicKey,CKA_MODULUS);
3629 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
3630 sftk_DeleteAttributeType(privateKey,CKA_MODULUS);
3631 sftk_DeleteAttributeType(privateKey,CKA_PRIVATE_EXPONENT);
3632 sftk_DeleteAttributeType(privateKey,CKA_PUBLIC_EXPONENT);
3633 sftk_DeleteAttributeType(privateKey,CKA_PRIME_1);
3634 sftk_DeleteAttributeType(privateKey,CKA_PRIME_2);
3635 sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_1);
3636 sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_2);
3637 sftk_DeleteAttributeType(privateKey,CKA_COEFFICIENT);
3638 key_type = CKK_RSA;
3639 if (public_modulus_bits == 0) {
3640 crv = CKR_TEMPLATE_INCOMPLETE;
3641 break;
3643 if (public_modulus_bits < RSA_MIN_MODULUS_BITS) {
3644 crv = CKR_ATTRIBUTE_VALUE_INVALID;
3645 break;
3647 if (public_modulus_bits % 2 != 0) {
3648 crv = CKR_ATTRIBUTE_VALUE_INVALID;
3649 break;
3652 /* extract the exponent */
3653 crv=sftk_Attribute2SSecItem(NULL,&pubExp,publicKey,CKA_PUBLIC_EXPONENT);
3654 if (crv != CKR_OK) break;
3655 bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len);
3656 if (bitSize < 2) {
3657 crv = CKR_ATTRIBUTE_VALUE_INVALID;
3658 break;
3660 crv = sftk_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT,
3661 sftk_item_expand(&pubExp));
3662 if (crv != CKR_OK) {
3663 PORT_Free(pubExp.data);
3664 break;
3667 rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);
3668 PORT_Free(pubExp.data);
3669 if (rsaPriv == NULL) {
3670 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
3671 sftk_fatalError = PR_TRUE;
3673 crv = CKR_DEVICE_ERROR;
3674 break;
3676 /* now fill in the RSA dependent paramenters in the public key */
3677 crv = sftk_AddAttributeType(publicKey,CKA_MODULUS,
3678 sftk_item_expand(&rsaPriv->modulus));
3679 if (crv != CKR_OK) goto kpg_done;
3680 /* now fill in the RSA dependent paramenters in the private key */
3681 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
3682 sftk_item_expand(&rsaPriv->modulus));
3683 if (crv != CKR_OK) goto kpg_done;
3684 crv = sftk_AddAttributeType(privateKey,CKA_MODULUS,
3685 sftk_item_expand(&rsaPriv->modulus));
3686 if (crv != CKR_OK) goto kpg_done;
3687 crv = sftk_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT,
3688 sftk_item_expand(&rsaPriv->privateExponent));
3689 if (crv != CKR_OK) goto kpg_done;
3690 crv = sftk_AddAttributeType(privateKey,CKA_PRIME_1,
3691 sftk_item_expand(&rsaPriv->prime1));
3692 if (crv != CKR_OK) goto kpg_done;
3693 crv = sftk_AddAttributeType(privateKey,CKA_PRIME_2,
3694 sftk_item_expand(&rsaPriv->prime2));
3695 if (crv != CKR_OK) goto kpg_done;
3696 crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_1,
3697 sftk_item_expand(&rsaPriv->exponent1));
3698 if (crv != CKR_OK) goto kpg_done;
3699 crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_2,
3700 sftk_item_expand(&rsaPriv->exponent2));
3701 if (crv != CKR_OK) goto kpg_done;
3702 crv = sftk_AddAttributeType(privateKey,CKA_COEFFICIENT,
3703 sftk_item_expand(&rsaPriv->coefficient));
3704 kpg_done:
3705 /* Should zeroize the contents first, since this func doesn't. */
3706 PORT_FreeArena(rsaPriv->arena, PR_TRUE);
3707 break;
3708 case CKM_DSA_KEY_PAIR_GEN:
3709 sftk_DeleteAttributeType(publicKey,CKA_VALUE);
3710 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
3711 sftk_DeleteAttributeType(privateKey,CKA_PRIME);
3712 sftk_DeleteAttributeType(privateKey,CKA_SUBPRIME);
3713 sftk_DeleteAttributeType(privateKey,CKA_BASE);
3714 key_type = CKK_DSA;
3716 /* extract the necessary paramters and copy them to the private key */
3717 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.prime,publicKey,CKA_PRIME);
3718 if (crv != CKR_OK) break;
3719 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.subPrime,publicKey,
3720 CKA_SUBPRIME);
3721 if (crv != CKR_OK) {
3722 PORT_Free(pqgParam.prime.data);
3723 break;
3725 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.base,publicKey,CKA_BASE);
3726 if (crv != CKR_OK) {
3727 PORT_Free(pqgParam.prime.data);
3728 PORT_Free(pqgParam.subPrime.data);
3729 break;
3731 crv = sftk_AddAttributeType(privateKey,CKA_PRIME,
3732 sftk_item_expand(&pqgParam.prime));
3733 if (crv != CKR_OK) {
3734 PORT_Free(pqgParam.prime.data);
3735 PORT_Free(pqgParam.subPrime.data);
3736 PORT_Free(pqgParam.base.data);
3737 break;
3739 crv = sftk_AddAttributeType(privateKey,CKA_SUBPRIME,
3740 sftk_item_expand(&pqgParam.subPrime));
3741 if (crv != CKR_OK) {
3742 PORT_Free(pqgParam.prime.data);
3743 PORT_Free(pqgParam.subPrime.data);
3744 PORT_Free(pqgParam.base.data);
3745 break;
3747 crv = sftk_AddAttributeType(privateKey,CKA_BASE,
3748 sftk_item_expand(&pqgParam.base));
3749 if (crv != CKR_OK) {
3750 PORT_Free(pqgParam.prime.data);
3751 PORT_Free(pqgParam.subPrime.data);
3752 PORT_Free(pqgParam.base.data);
3753 break;
3756 bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data,
3757 pqgParam.subPrime.len);
3758 if (bitSize != DSA_Q_BITS) {
3759 crv = CKR_TEMPLATE_INCOMPLETE;
3760 PORT_Free(pqgParam.prime.data);
3761 PORT_Free(pqgParam.subPrime.data);
3762 PORT_Free(pqgParam.base.data);
3763 break;
3765 bitSize = sftk_GetLengthInBits(pqgParam.prime.data,pqgParam.prime.len);
3766 if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) {
3767 crv = CKR_TEMPLATE_INCOMPLETE;
3768 PORT_Free(pqgParam.prime.data);
3769 PORT_Free(pqgParam.subPrime.data);
3770 PORT_Free(pqgParam.base.data);
3771 break;
3773 bitSize = sftk_GetLengthInBits(pqgParam.base.data,pqgParam.base.len);
3774 if ((bitSize < 1) || (bitSize > DSA_MAX_P_BITS)) {
3775 crv = CKR_TEMPLATE_INCOMPLETE;
3776 PORT_Free(pqgParam.prime.data);
3777 PORT_Free(pqgParam.subPrime.data);
3778 PORT_Free(pqgParam.base.data);
3779 break;
3782 /* Generate the key */
3783 rv = DSA_NewKey(&pqgParam, &dsaPriv);
3785 PORT_Free(pqgParam.prime.data);
3786 PORT_Free(pqgParam.subPrime.data);
3787 PORT_Free(pqgParam.base.data);
3789 if (rv != SECSuccess) {
3790 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
3791 sftk_fatalError = PR_TRUE;
3793 crv = CKR_DEVICE_ERROR;
3794 break;
3797 /* store the generated key into the attributes */
3798 crv = sftk_AddAttributeType(publicKey,CKA_VALUE,
3799 sftk_item_expand(&dsaPriv->publicValue));
3800 if (crv != CKR_OK) goto dsagn_done;
3802 /* now fill in the RSA dependent paramenters in the private key */
3803 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
3804 sftk_item_expand(&dsaPriv->publicValue));
3805 if (crv != CKR_OK) goto dsagn_done;
3806 crv = sftk_AddAttributeType(privateKey,CKA_VALUE,
3807 sftk_item_expand(&dsaPriv->privateValue));
3809 dsagn_done:
3810 /* should zeroize, since this function doesn't. */
3811 PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
3812 break;
3814 case CKM_DH_PKCS_KEY_PAIR_GEN:
3815 sftk_DeleteAttributeType(privateKey,CKA_PRIME);
3816 sftk_DeleteAttributeType(privateKey,CKA_BASE);
3817 sftk_DeleteAttributeType(privateKey,CKA_VALUE);
3818 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
3819 key_type = CKK_DH;
3821 /* extract the necessary parameters and copy them to private keys */
3822 crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey,
3823 CKA_PRIME);
3824 if (crv != CKR_OK) break;
3825 crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
3826 if (crv != CKR_OK) {
3827 PORT_Free(dhParam.prime.data);
3828 break;
3830 crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
3831 sftk_item_expand(&dhParam.prime));
3832 if (crv != CKR_OK) {
3833 PORT_Free(dhParam.prime.data);
3834 PORT_Free(dhParam.base.data);
3835 break;
3837 crv = sftk_AddAttributeType(privateKey, CKA_BASE,
3838 sftk_item_expand(&dhParam.base));
3839 if (crv != CKR_OK) {
3840 PORT_Free(dhParam.prime.data);
3841 PORT_Free(dhParam.base.data);
3842 break;
3844 bitSize = sftk_GetLengthInBits(dhParam.prime.data,dhParam.prime.len);
3845 if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) {
3846 crv = CKR_TEMPLATE_INCOMPLETE;
3847 PORT_Free(dhParam.prime.data);
3848 PORT_Free(dhParam.base.data);
3849 break;
3851 bitSize = sftk_GetLengthInBits(dhParam.base.data,dhParam.base.len);
3852 if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) {
3853 crv = CKR_TEMPLATE_INCOMPLETE;
3854 PORT_Free(dhParam.prime.data);
3855 PORT_Free(dhParam.base.data);
3856 break;
3859 rv = DH_NewKey(&dhParam, &dhPriv);
3860 PORT_Free(dhParam.prime.data);
3861 PORT_Free(dhParam.base.data);
3862 if (rv != SECSuccess) {
3863 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
3864 sftk_fatalError = PR_TRUE;
3866 crv = CKR_DEVICE_ERROR;
3867 break;
3870 crv=sftk_AddAttributeType(publicKey, CKA_VALUE,
3871 sftk_item_expand(&dhPriv->publicValue));
3872 if (crv != CKR_OK) goto dhgn_done;
3874 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
3875 sftk_item_expand(&dhPriv->publicValue));
3876 if (crv != CKR_OK) goto dhgn_done;
3878 crv=sftk_AddAttributeType(privateKey, CKA_VALUE,
3879 sftk_item_expand(&dhPriv->privateValue));
3881 dhgn_done:
3882 /* should zeroize, since this function doesn't. */
3883 PORT_FreeArena(dhPriv->arena, PR_TRUE);
3884 break;
3886 #ifdef NSS_ENABLE_ECC
3887 case CKM_EC_KEY_PAIR_GEN:
3888 sftk_DeleteAttributeType(privateKey,CKA_EC_PARAMS);
3889 sftk_DeleteAttributeType(privateKey,CKA_VALUE);
3890 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
3891 key_type = CKK_EC;
3893 /* extract the necessary parameters and copy them to private keys */
3894 crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
3895 CKA_EC_PARAMS);
3896 if (crv != CKR_OK) break;
3898 crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
3899 sftk_item_expand(&ecEncodedParams));
3900 if (crv != CKR_OK) {
3901 PORT_Free(ecEncodedParams.data);
3902 break;
3905 /* Decode ec params before calling EC_NewKey */
3906 rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
3907 PORT_Free(ecEncodedParams.data);
3908 if (rv != SECSuccess) {
3909 crv = CKR_DEVICE_ERROR;
3910 break;
3912 rv = EC_NewKey(ecParams, &ecPriv);
3913 PORT_FreeArena(ecParams->arena, PR_TRUE);
3914 if (rv != SECSuccess) {
3915 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
3916 sftk_fatalError = PR_TRUE;
3918 crv = CKR_DEVICE_ERROR;
3919 break;
3922 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
3923 sftk_item_expand(&ecPriv->publicValue));
3924 if (crv != CKR_OK) goto ecgn_done;
3926 crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
3927 sftk_item_expand(&ecPriv->privateValue));
3928 if (crv != CKR_OK) goto ecgn_done;
3930 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
3931 sftk_item_expand(&ecPriv->publicValue));
3932 ecgn_done:
3933 /* should zeroize, since this function doesn't. */
3934 PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
3935 break;
3936 #endif /* NSS_ENABLE_ECC */
3938 default:
3939 crv = CKR_MECHANISM_INVALID;
3942 if (crv != CKR_OK) {
3943 sftk_FreeObject(privateKey);
3944 sftk_FreeObject(publicKey);
3945 return crv;
3949 /* Add the class, key_type The loop lets us check errors blow out
3950 * on errors and clean up at the bottom */
3951 session = NULL; /* make pedtantic happy... session cannot leave the*/
3952 /* loop below NULL unless an error is set... */
3953 do {
3954 crv = sftk_AddAttributeType(privateKey,CKA_CLASS,&privClass,
3955 sizeof(CK_OBJECT_CLASS));
3956 if (crv != CKR_OK) break;
3957 crv = sftk_AddAttributeType(publicKey,CKA_CLASS,&pubClass,
3958 sizeof(CK_OBJECT_CLASS));
3959 if (crv != CKR_OK) break;
3960 crv = sftk_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type,
3961 sizeof(CK_KEY_TYPE));
3962 if (crv != CKR_OK) break;
3963 crv = sftk_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type,
3964 sizeof(CK_KEY_TYPE));
3965 if (crv != CKR_OK) break;
3966 session = sftk_SessionFromHandle(hSession);
3967 if (session == NULL) crv = CKR_SESSION_HANDLE_INVALID;
3968 } while (0);
3970 if (crv != CKR_OK) {
3971 sftk_FreeObject(privateKey);
3972 sftk_FreeObject(publicKey);
3973 return crv;
3977 * handle the base object cleanup for the public Key
3979 crv = sftk_handleObject(privateKey,session);
3980 if (crv != CKR_OK) {
3981 sftk_FreeSession(session);
3982 sftk_FreeObject(privateKey);
3983 sftk_FreeObject(publicKey);
3984 return crv;
3988 * handle the base object cleanup for the private Key
3989 * If we have any problems, we destroy the public Key we've
3990 * created and linked.
3992 crv = sftk_handleObject(publicKey,session);
3993 sftk_FreeSession(session);
3994 if (crv != CKR_OK) {
3995 sftk_FreeObject(publicKey);
3996 NSC_DestroyObject(hSession,privateKey->handle);
3997 sftk_FreeObject(privateKey);
3998 return crv;
4000 if (sftk_isTrue(privateKey,CKA_SENSITIVE)) {
4001 sftk_forceAttribute(privateKey,CKA_ALWAYS_SENSITIVE,
4002 &cktrue,sizeof(CK_BBOOL));
4004 if (sftk_isTrue(publicKey,CKA_SENSITIVE)) {
4005 sftk_forceAttribute(publicKey,CKA_ALWAYS_SENSITIVE,
4006 &cktrue,sizeof(CK_BBOOL));
4008 if (!sftk_isTrue(privateKey,CKA_EXTRACTABLE)) {
4009 sftk_forceAttribute(privateKey,CKA_NEVER_EXTRACTABLE,
4010 &cktrue,sizeof(CK_BBOOL));
4012 if (!sftk_isTrue(publicKey,CKA_EXTRACTABLE)) {
4013 sftk_forceAttribute(publicKey,CKA_NEVER_EXTRACTABLE,
4014 &cktrue,sizeof(CK_BBOOL));
4017 /* Perform FIPS 140-2 pairwise consistency check. */
4018 crv = sftk_PairwiseConsistencyCheck(hSession,
4019 publicKey, privateKey, key_type);
4020 if (crv != CKR_OK) {
4021 NSC_DestroyObject(hSession,publicKey->handle);
4022 sftk_FreeObject(publicKey);
4023 NSC_DestroyObject(hSession,privateKey->handle);
4024 sftk_FreeObject(privateKey);
4025 if (sftk_audit_enabled) {
4026 char msg[128];
4027 PR_snprintf(msg,sizeof msg,
4028 "C_GenerateKeyPair(hSession=0x%08lX, "
4029 "pMechanism->mechanism=0x%08lX)=0x%08lX "
4030 "self-test: pair-wise consistency test failed",
4031 (PRUint32)hSession,(PRUint32)pMechanism->mechanism,
4032 (PRUint32)crv);
4033 sftk_LogAuditMessage(NSS_AUDIT_ERROR, msg);
4035 return crv;
4038 *phPrivateKey = privateKey->handle;
4039 *phPublicKey = publicKey->handle;
4040 sftk_FreeObject(publicKey);
4041 sftk_FreeObject(privateKey);
4043 return CKR_OK;
4046 static SECItem *sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp)
4048 NSSLOWKEYPrivateKey *lk = NULL;
4049 NSSLOWKEYPrivateKeyInfo *pki = NULL;
4050 SFTKAttribute *attribute = NULL;
4051 PLArenaPool *arena = NULL;
4052 SECOidTag algorithm = SEC_OID_UNKNOWN;
4053 void *dummy, *param = NULL;
4054 SECStatus rv = SECSuccess;
4055 SECItem *encodedKey = NULL;
4056 #ifdef NSS_ENABLE_ECC
4057 SECItem *fordebug;
4058 int savelen;
4059 #endif
4061 if(!key) {
4062 *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */
4063 return NULL;
4066 attribute = sftk_FindAttribute(key, CKA_KEY_TYPE);
4067 if(!attribute) {
4068 *crvp = CKR_KEY_TYPE_INCONSISTENT;
4069 return NULL;
4072 lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp);
4073 sftk_FreeAttribute(attribute);
4074 if(!lk) {
4075 return NULL;
4078 arena = PORT_NewArena(2048); /* XXX different size? */
4079 if(!arena) {
4080 *crvp = CKR_HOST_MEMORY;
4081 rv = SECFailure;
4082 goto loser;
4085 pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
4086 sizeof(NSSLOWKEYPrivateKeyInfo));
4087 if(!pki) {
4088 *crvp = CKR_HOST_MEMORY;
4089 rv = SECFailure;
4090 goto loser;
4092 pki->arena = arena;
4094 param = NULL;
4095 switch(lk->keyType) {
4096 case NSSLOWKEYRSAKey:
4097 prepare_low_rsa_priv_key_for_asn1(lk);
4098 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
4099 nsslowkey_RSAPrivateKeyTemplate);
4100 algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
4101 break;
4102 case NSSLOWKEYDSAKey:
4103 prepare_low_dsa_priv_key_export_for_asn1(lk);
4104 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
4105 nsslowkey_DSAPrivateKeyExportTemplate);
4106 prepare_low_pqg_params_for_asn1(&lk->u.dsa.params);
4107 param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
4108 nsslowkey_PQGParamsTemplate);
4109 algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
4110 break;
4111 #ifdef NSS_ENABLE_ECC
4112 case NSSLOWKEYECKey:
4113 prepare_low_ec_priv_key_for_asn1(lk);
4114 /* Public value is encoded as a bit string so adjust length
4115 * to be in bits before ASN encoding and readjust
4116 * immediately after.
4118 * Since the SECG specification recommends not including the
4119 * parameters as part of ECPrivateKey, we zero out the curveOID
4120 * length before encoding and restore it later.
4122 lk->u.ec.publicValue.len <<= 3;
4123 savelen = lk->u.ec.ecParams.curveOID.len;
4124 lk->u.ec.ecParams.curveOID.len = 0;
4125 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
4126 nsslowkey_ECPrivateKeyTemplate);
4127 lk->u.ec.ecParams.curveOID.len = savelen;
4128 lk->u.ec.publicValue.len >>= 3;
4130 fordebug = &pki->privateKey;
4131 SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType,
4132 fordebug);
4134 param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding);
4136 algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
4137 break;
4138 #endif /* NSS_ENABLE_ECC */
4139 case NSSLOWKEYDHKey:
4140 default:
4141 dummy = NULL;
4142 break;
4145 if(!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) {
4146 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
4147 rv = SECFailure;
4148 goto loser;
4151 rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm,
4152 (SECItem*)param);
4153 if(rv != SECSuccess) {
4154 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
4155 rv = SECFailure;
4156 goto loser;
4159 dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
4160 NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
4161 if(!dummy) {
4162 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
4163 rv = SECFailure;
4164 goto loser;
4167 encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
4168 nsslowkey_PrivateKeyInfoTemplate);
4169 *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR;
4171 #ifdef NSS_ENABLE_ECC
4172 fordebug = encodedKey;
4173 SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType,
4174 fordebug);
4175 #endif
4176 loser:
4177 if(arena) {
4178 PORT_FreeArena(arena, PR_TRUE);
4181 if(lk && (lk != key->objectInfo)) {
4182 nsslowkey_DestroyPrivateKey(lk);
4185 if(param) {
4186 SECITEM_ZfreeItem((SECItem*)param, PR_TRUE);
4189 if(rv != SECSuccess) {
4190 return NULL;
4193 return encodedKey;
4196 /* it doesn't matter yet, since we colapse error conditions in the
4197 * level above, but we really should map those few key error differences */
4198 static CK_RV
4199 sftk_mapWrap(CK_RV crv)
4201 switch (crv) {
4202 case CKR_ENCRYPTED_DATA_INVALID: crv = CKR_WRAPPED_KEY_INVALID; break;
4204 return crv;
4207 /* NSC_WrapKey wraps (i.e., encrypts) a key. */
4208 CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession,
4209 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
4210 CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
4211 CK_ULONG_PTR pulWrappedKeyLen)
4213 SFTKSession *session;
4214 SFTKAttribute *attribute;
4215 SFTKObject *key;
4216 CK_RV crv;
4218 CHECK_FORK();
4220 session = sftk_SessionFromHandle(hSession);
4221 if (session == NULL) {
4222 return CKR_SESSION_HANDLE_INVALID;
4225 key = sftk_ObjectFromHandle(hKey,session);
4226 sftk_FreeSession(session);
4227 if (key == NULL) {
4228 return CKR_KEY_HANDLE_INVALID;
4231 switch(key->objclass) {
4232 case CKO_SECRET_KEY:
4234 SFTKSessionContext *context = NULL;
4235 SECItem pText;
4237 attribute = sftk_FindAttribute(key,CKA_VALUE);
4239 if (attribute == NULL) {
4240 crv = CKR_KEY_TYPE_INCONSISTENT;
4241 break;
4243 crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
4244 CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
4245 if (crv != CKR_OK) {
4246 sftk_FreeAttribute(attribute);
4247 break;
4250 pText.type = siBuffer;
4251 pText.data = (unsigned char *)attribute->attrib.pValue;
4252 pText.len = attribute->attrib.ulValueLen;
4254 /* Find out if this is a block cipher. */
4255 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,NULL);
4256 if (crv != CKR_OK || !context)
4257 break;
4258 if (context->blockSize > 1) {
4259 unsigned int remainder = pText.len % context->blockSize;
4260 if (!context->doPad && remainder) {
4261 /* When wrapping secret keys with unpadded block ciphers,
4262 ** the keys are zero padded, if necessary, to fill out
4263 ** a full block.
4265 pText.len += context->blockSize - remainder;
4266 pText.data = PORT_ZAlloc(pText.len);
4267 if (pText.data)
4268 memcpy(pText.data, attribute->attrib.pValue,
4269 attribute->attrib.ulValueLen);
4270 else {
4271 crv = CKR_HOST_MEMORY;
4272 break;
4277 crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data,
4278 pText.len, pWrappedKey, pulWrappedKeyLen);
4279 /* always force a finalize, both on errors and when
4280 * we are just getting the size */
4281 if (crv != CKR_OK || pWrappedKey == NULL) {
4282 CK_RV lcrv ;
4283 lcrv = sftk_GetContext(hSession,&context,
4284 SFTK_ENCRYPT,PR_FALSE,NULL);
4285 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
4286 if (lcrv == CKR_OK && context) {
4287 sftk_FreeContext(context);
4291 if (pText.data != (unsigned char *)attribute->attrib.pValue)
4292 PORT_ZFree(pText.data, pText.len);
4293 sftk_FreeAttribute(attribute);
4294 break;
4297 case CKO_PRIVATE_KEY:
4299 SECItem *bpki = sftk_PackagePrivateKey(key, &crv);
4300 SFTKSessionContext *context = NULL;
4302 if(!bpki) {
4303 break;
4306 crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
4307 CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
4308 if(crv != CKR_OK) {
4309 SECITEM_ZfreeItem(bpki, PR_TRUE);
4310 crv = CKR_KEY_TYPE_INCONSISTENT;
4311 break;
4314 crv = NSC_Encrypt(hSession, bpki->data, bpki->len,
4315 pWrappedKey, pulWrappedKeyLen);
4316 /* always force a finalize */
4317 if (crv != CKR_OK || pWrappedKey == NULL) {
4318 CK_RV lcrv ;
4319 lcrv = sftk_GetContext(hSession,&context,
4320 SFTK_ENCRYPT,PR_FALSE,NULL);
4321 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
4322 if (lcrv == CKR_OK && context) {
4323 sftk_FreeContext(context);
4326 SECITEM_ZfreeItem(bpki, PR_TRUE);
4327 break;
4330 default:
4331 crv = CKR_KEY_TYPE_INCONSISTENT;
4332 break;
4334 sftk_FreeObject(key);
4336 return sftk_mapWrap(crv);
4340 * import a pprivate key info into the desired slot
4342 static SECStatus
4343 sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
4345 CK_BBOOL cktrue = CK_TRUE;
4346 CK_KEY_TYPE keyType = CKK_RSA;
4347 SECStatus rv = SECFailure;
4348 const SEC_ASN1Template *keyTemplate, *paramTemplate;
4349 void *paramDest = NULL;
4350 PLArenaPool *arena;
4351 NSSLOWKEYPrivateKey *lpk = NULL;
4352 NSSLOWKEYPrivateKeyInfo *pki = NULL;
4353 CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
4355 arena = PORT_NewArena(2048);
4356 if(!arena) {
4357 return SECFailure;
4360 pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
4361 sizeof(NSSLOWKEYPrivateKeyInfo));
4362 if(!pki) {
4363 PORT_FreeArena(arena, PR_FALSE);
4364 return SECFailure;
4367 if(SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki)
4368 != SECSuccess) {
4369 PORT_FreeArena(arena, PR_TRUE);
4370 return SECFailure;
4373 lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena,
4374 sizeof(NSSLOWKEYPrivateKey));
4375 if(lpk == NULL) {
4376 goto loser;
4378 lpk->arena = arena;
4380 switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
4381 case SEC_OID_PKCS1_RSA_ENCRYPTION:
4382 keyTemplate = nsslowkey_RSAPrivateKeyTemplate;
4383 paramTemplate = NULL;
4384 paramDest = NULL;
4385 lpk->keyType = NSSLOWKEYRSAKey;
4386 prepare_low_rsa_priv_key_for_asn1(lpk);
4387 break;
4388 case SEC_OID_ANSIX9_DSA_SIGNATURE:
4389 keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate;
4390 paramTemplate = nsslowkey_PQGParamsTemplate;
4391 paramDest = &(lpk->u.dsa.params);
4392 lpk->keyType = NSSLOWKEYDSAKey;
4393 prepare_low_dsa_priv_key_export_for_asn1(lpk);
4394 prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params);
4395 break;
4396 /* case NSSLOWKEYDHKey: */
4397 #ifdef NSS_ENABLE_ECC
4398 case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
4399 keyTemplate = nsslowkey_ECPrivateKeyTemplate;
4400 paramTemplate = NULL;
4401 paramDest = &(lpk->u.ec.ecParams.DEREncoding);
4402 lpk->keyType = NSSLOWKEYECKey;
4403 prepare_low_ec_priv_key_for_asn1(lpk);
4404 prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams);
4405 break;
4406 #endif /* NSS_ENABLE_ECC */
4407 default:
4408 keyTemplate = NULL;
4409 paramTemplate = NULL;
4410 paramDest = NULL;
4411 break;
4414 if(!keyTemplate) {
4415 goto loser;
4418 /* decode the private key and any algorithm parameters */
4419 rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
4421 #ifdef NSS_ENABLE_ECC
4422 if (lpk->keyType == NSSLOWKEYECKey) {
4423 /* convert length in bits to length in bytes */
4424 lpk->u.ec.publicValue.len >>= 3;
4425 rv = SECITEM_CopyItem(arena,
4426 &(lpk->u.ec.ecParams.DEREncoding),
4427 &(pki->algorithm.parameters));
4428 if(rv != SECSuccess) {
4429 goto loser;
4432 #endif /* NSS_ENABLE_ECC */
4434 if(rv != SECSuccess) {
4435 goto loser;
4437 if(paramDest && paramTemplate) {
4438 rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate,
4439 &(pki->algorithm.parameters));
4440 if(rv != SECSuccess) {
4441 goto loser;
4445 rv = SECFailure;
4447 switch (lpk->keyType) {
4448 case NSSLOWKEYRSAKey:
4449 keyType = CKK_RSA;
4450 if(sftk_hasAttribute(key, CKA_NETSCAPE_DB)) {
4451 sftk_DeleteAttributeType(key, CKA_NETSCAPE_DB);
4453 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
4454 sizeof(keyType));
4455 if(crv != CKR_OK) break;
4456 crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue,
4457 sizeof(CK_BBOOL));
4458 if(crv != CKR_OK) break;
4459 crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue,
4460 sizeof(CK_BBOOL));
4461 if(crv != CKR_OK) break;
4462 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
4463 sizeof(CK_BBOOL));
4464 if(crv != CKR_OK) break;
4465 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
4466 sizeof(CK_BBOOL));
4467 if(crv != CKR_OK) break;
4468 crv = sftk_AddAttributeType(key, CKA_MODULUS,
4469 sftk_item_expand(&lpk->u.rsa.modulus));
4470 if(crv != CKR_OK) break;
4471 crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT,
4472 sftk_item_expand(&lpk->u.rsa.publicExponent));
4473 if(crv != CKR_OK) break;
4474 crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT,
4475 sftk_item_expand(&lpk->u.rsa.privateExponent));
4476 if(crv != CKR_OK) break;
4477 crv = sftk_AddAttributeType(key, CKA_PRIME_1,
4478 sftk_item_expand(&lpk->u.rsa.prime1));
4479 if(crv != CKR_OK) break;
4480 crv = sftk_AddAttributeType(key, CKA_PRIME_2,
4481 sftk_item_expand(&lpk->u.rsa.prime2));
4482 if(crv != CKR_OK) break;
4483 crv = sftk_AddAttributeType(key, CKA_EXPONENT_1,
4484 sftk_item_expand(&lpk->u.rsa.exponent1));
4485 if(crv != CKR_OK) break;
4486 crv = sftk_AddAttributeType(key, CKA_EXPONENT_2,
4487 sftk_item_expand(&lpk->u.rsa.exponent2));
4488 if(crv != CKR_OK) break;
4489 crv = sftk_AddAttributeType(key, CKA_COEFFICIENT,
4490 sftk_item_expand(&lpk->u.rsa.coefficient));
4491 break;
4492 case NSSLOWKEYDSAKey:
4493 keyType = CKK_DSA;
4494 crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK :
4495 CKR_KEY_TYPE_INCONSISTENT;
4496 if(crv != CKR_OK) break;
4497 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
4498 sizeof(keyType));
4499 if(crv != CKR_OK) break;
4500 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
4501 sizeof(CK_BBOOL));
4502 if(crv != CKR_OK) break;
4503 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
4504 sizeof(CK_BBOOL));
4505 if(crv != CKR_OK) break;
4506 crv = sftk_AddAttributeType(key, CKA_PRIME,
4507 sftk_item_expand(&lpk->u.dsa.params.prime));
4508 if(crv != CKR_OK) break;
4509 crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
4510 sftk_item_expand(&lpk->u.dsa.params.subPrime));
4511 if(crv != CKR_OK) break;
4512 crv = sftk_AddAttributeType(key, CKA_BASE,
4513 sftk_item_expand(&lpk->u.dsa.params.base));
4514 if(crv != CKR_OK) break;
4515 crv = sftk_AddAttributeType(key, CKA_VALUE,
4516 sftk_item_expand(&lpk->u.dsa.privateValue));
4517 if(crv != CKR_OK) break;
4518 break;
4519 #ifdef notdef
4520 case NSSLOWKEYDHKey:
4521 template = dhTemplate;
4522 templateCount = sizeof(dhTemplate)/sizeof(CK_ATTRIBUTE);
4523 keyType = CKK_DH;
4524 break;
4525 #endif
4526 /* what about fortezza??? */
4527 #ifdef NSS_ENABLE_ECC
4528 case NSSLOWKEYECKey:
4529 keyType = CKK_EC;
4530 crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK :
4531 CKR_KEY_TYPE_INCONSISTENT;
4532 if(crv != CKR_OK) break;
4533 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
4534 sizeof(keyType));
4535 if(crv != CKR_OK) break;
4536 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
4537 sizeof(CK_BBOOL));
4538 if(crv != CKR_OK) break;
4539 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
4540 sizeof(CK_BBOOL));
4541 if(crv != CKR_OK) break;
4542 crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue,
4543 sizeof(CK_BBOOL));
4544 if(crv != CKR_OK) break;
4545 crv = sftk_AddAttributeType(key, CKA_EC_PARAMS,
4546 sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding));
4547 if(crv != CKR_OK) break;
4548 crv = sftk_AddAttributeType(key, CKA_VALUE,
4549 sftk_item_expand(&lpk->u.ec.privateValue));
4550 if(crv != CKR_OK) break;
4551 /* XXX Do we need to decode the EC Params here ?? */
4552 break;
4553 #endif /* NSS_ENABLE_ECC */
4554 default:
4555 crv = CKR_KEY_TYPE_INCONSISTENT;
4556 break;
4559 loser:
4560 if(lpk) {
4561 nsslowkey_DestroyPrivateKey(lpk);
4564 if(crv != CKR_OK) {
4565 return SECFailure;
4568 return SECSuccess;
4572 /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
4573 CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
4574 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
4575 CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
4576 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
4577 CK_OBJECT_HANDLE_PTR phKey)
4579 SFTKObject *key = NULL;
4580 SFTKSession *session;
4581 CK_ULONG key_length = 0;
4582 unsigned char * buf = NULL;
4583 CK_RV crv = CKR_OK;
4584 int i;
4585 CK_ULONG bsize = ulWrappedKeyLen;
4586 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
4587 SECItem bpki;
4588 CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
4590 CHECK_FORK();
4592 if (!slot) {
4593 return CKR_SESSION_HANDLE_INVALID;
4596 * now lets create an object to hang the attributes off of
4598 key = sftk_NewObject(slot); /* fill in the handle later */
4599 if (key == NULL) {
4600 return CKR_HOST_MEMORY;
4604 * load the template values into the object
4606 for (i=0; i < (int) ulAttributeCount; i++) {
4607 if (pTemplate[i].type == CKA_VALUE_LEN) {
4608 key_length = *(CK_ULONG *)pTemplate[i].pValue;
4609 continue;
4611 if (pTemplate[i].type == CKA_CLASS) {
4612 target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
4614 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i]));
4615 if (crv != CKR_OK) break;
4617 if (crv != CKR_OK) {
4618 sftk_FreeObject(key);
4619 return crv;
4622 crv = sftk_CryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP,
4623 SFTK_DECRYPT, PR_FALSE);
4624 if (crv != CKR_OK) {
4625 sftk_FreeObject(key);
4626 return sftk_mapWrap(crv);
4629 /* allocate the buffer to decrypt into
4630 * this assumes the unwrapped key is never larger than the
4631 * wrapped key. For all the mechanisms we support this is true */
4632 buf = (unsigned char *)PORT_Alloc( ulWrappedKeyLen);
4633 bsize = ulWrappedKeyLen;
4635 crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
4636 if (crv != CKR_OK) {
4637 sftk_FreeObject(key);
4638 PORT_Free(buf);
4639 return sftk_mapWrap(crv);
4642 switch(target_type) {
4643 case CKO_SECRET_KEY:
4644 if (!sftk_hasAttribute(key,CKA_KEY_TYPE)) {
4645 crv = CKR_TEMPLATE_INCOMPLETE;
4646 break;
4649 if (key_length == 0 || key_length > bsize) {
4650 key_length = bsize;
4652 if (key_length > MAX_KEY_LEN) {
4653 crv = CKR_TEMPLATE_INCONSISTENT;
4654 break;
4657 /* add the value */
4658 crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length);
4659 break;
4660 case CKO_PRIVATE_KEY:
4661 bpki.data = (unsigned char *)buf;
4662 bpki.len = bsize;
4663 crv = CKR_OK;
4664 if(sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) {
4665 crv = CKR_TEMPLATE_INCOMPLETE;
4667 break;
4668 default:
4669 crv = CKR_TEMPLATE_INCONSISTENT;
4670 break;
4673 PORT_ZFree(buf, bsize);
4674 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
4676 /* get the session */
4677 session = sftk_SessionFromHandle(hSession);
4678 if (session == NULL) {
4679 sftk_FreeObject(key);
4680 return CKR_SESSION_HANDLE_INVALID;
4684 * handle the base object stuff
4686 crv = sftk_handleObject(key,session);
4687 *phKey = key->handle;
4688 sftk_FreeSession(session);
4689 sftk_FreeObject(key);
4691 return crv;
4696 * The SSL key gen mechanism create's lots of keys. This function handles the
4697 * details of each of these key creation.
4699 static CK_RV
4700 sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey,
4701 PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
4702 CK_OBJECT_HANDLE *keyHandle)
4704 SFTKObject *key;
4705 SFTKSession *session;
4706 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
4707 CK_BBOOL cktrue = CK_TRUE;
4708 CK_BBOOL ckfalse = CK_FALSE;
4709 CK_RV crv = CKR_HOST_MEMORY;
4712 * now lets create an object to hang the attributes off of
4714 *keyHandle = CK_INVALID_HANDLE;
4715 key = sftk_NewObject(baseKey->slot);
4716 if (key == NULL) return CKR_HOST_MEMORY;
4717 sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE;
4719 crv = sftk_CopyObject(key,baseKey);
4720 if (crv != CKR_OK) goto loser;
4721 if (isMacKey) {
4722 crv = sftk_forceAttribute(key,CKA_KEY_TYPE,&keyType,sizeof(keyType));
4723 if (crv != CKR_OK) goto loser;
4724 crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
4725 if (crv != CKR_OK) goto loser;
4726 crv = sftk_forceAttribute(key,CKA_ENCRYPT,&ckfalse,sizeof(CK_BBOOL));
4727 if (crv != CKR_OK) goto loser;
4728 crv = sftk_forceAttribute(key,CKA_DECRYPT,&ckfalse,sizeof(CK_BBOOL));
4729 if (crv != CKR_OK) goto loser;
4730 crv = sftk_forceAttribute(key,CKA_SIGN,&cktrue,sizeof(CK_BBOOL));
4731 if (crv != CKR_OK) goto loser;
4732 crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
4733 if (crv != CKR_OK) goto loser;
4734 crv = sftk_forceAttribute(key,CKA_WRAP,&ckfalse,sizeof(CK_BBOOL));
4735 if (crv != CKR_OK) goto loser;
4736 crv = sftk_forceAttribute(key,CKA_UNWRAP,&ckfalse,sizeof(CK_BBOOL));
4737 if (crv != CKR_OK) goto loser;
4739 crv = sftk_forceAttribute(key,CKA_VALUE,keyBlock,keySize);
4740 if (crv != CKR_OK) goto loser;
4742 /* get the session */
4743 crv = CKR_HOST_MEMORY;
4744 session = sftk_SessionFromHandle(hSession);
4745 if (session == NULL) { goto loser; }
4747 crv = sftk_handleObject(key,session);
4748 sftk_FreeSession(session);
4749 *keyHandle = key->handle;
4750 loser:
4751 if (key) sftk_FreeObject(key);
4752 return crv;
4756 * if there is an error, we need to free the keys we already created in SSL
4757 * This is the routine that will do it..
4759 static void
4760 sftk_freeSSLKeys(CK_SESSION_HANDLE session,
4761 CK_SSL3_KEY_MAT_OUT *returnedMaterial )
4763 if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) {
4764 NSC_DestroyObject(session,returnedMaterial->hClientMacSecret);
4766 if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) {
4767 NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
4769 if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) {
4770 NSC_DestroyObject(session, returnedMaterial->hClientKey);
4772 if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) {
4773 NSC_DestroyObject(session, returnedMaterial->hServerKey);
4778 * when deriving from sensitive and extractable keys, we need to preserve some
4779 * of the semantics in the derived key. This helper routine maintains these
4780 * semantics.
4782 static CK_RV
4783 sftk_DeriveSensitiveCheck(SFTKObject *baseKey,SFTKObject *destKey)
4785 PRBool hasSensitive;
4786 PRBool sensitive = PR_FALSE;
4787 PRBool hasExtractable;
4788 PRBool extractable = PR_TRUE;
4789 CK_RV crv = CKR_OK;
4790 SFTKAttribute *att;
4792 hasSensitive = PR_FALSE;
4793 att = sftk_FindAttribute(destKey,CKA_SENSITIVE);
4794 if (att) {
4795 hasSensitive = PR_TRUE;
4796 sensitive = (PRBool) *(CK_BBOOL *)att->attrib.pValue;
4797 sftk_FreeAttribute(att);
4800 hasExtractable = PR_FALSE;
4801 att = sftk_FindAttribute(destKey,CKA_EXTRACTABLE);
4802 if (att) {
4803 hasExtractable = PR_TRUE;
4804 extractable = (PRBool) *(CK_BBOOL *)att->attrib.pValue;
4805 sftk_FreeAttribute(att);
4809 /* don't make a key more accessible */
4810 if (sftk_isTrue(baseKey,CKA_SENSITIVE) && hasSensitive &&
4811 (sensitive == PR_FALSE)) {
4812 return CKR_KEY_FUNCTION_NOT_PERMITTED;
4814 if (!sftk_isTrue(baseKey,CKA_EXTRACTABLE) && hasExtractable &&
4815 (extractable == PR_TRUE)) {
4816 return CKR_KEY_FUNCTION_NOT_PERMITTED;
4819 /* inherit parent's sensitivity */
4820 if (!hasSensitive) {
4821 att = sftk_FindAttribute(baseKey,CKA_SENSITIVE);
4822 if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT;
4823 crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib));
4824 sftk_FreeAttribute(att);
4825 if (crv != CKR_OK) return crv;
4827 if (!hasExtractable) {
4828 att = sftk_FindAttribute(baseKey,CKA_EXTRACTABLE);
4829 if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT;
4830 crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib));
4831 sftk_FreeAttribute(att);
4832 if (crv != CKR_OK) return crv;
4835 /* we should inherit the parent's always extractable/ never sensitive info,
4836 * but handleObject always forces this attributes, so we would need to do
4837 * something special. */
4838 return CKR_OK;
4842 * make known fixed PKCS #11 key types to their sizes in bytes
4844 unsigned long
4845 sftk_MapKeySize(CK_KEY_TYPE keyType)
4847 switch (keyType) {
4848 case CKK_CDMF:
4849 return 8;
4850 case CKK_DES:
4851 return 8;
4852 case CKK_DES2:
4853 return 16;
4854 case CKK_DES3:
4855 return 24;
4856 /* IDEA and CAST need to be added */
4857 default:
4858 break;
4860 return 0;
4864 * SSL Key generation given pre master secret
4866 #define NUM_MIXERS 9
4867 static const char * const mixers[NUM_MIXERS] = {
4868 "A",
4869 "BB",
4870 "CCC",
4871 "DDDD",
4872 "EEEEE",
4873 "FFFFFF",
4874 "GGGGGGG",
4875 "HHHHHHHH",
4876 "IIIIIIIII" };
4877 #define SSL3_PMS_LENGTH 48
4878 #define SSL3_MASTER_SECRET_LENGTH 48
4879 #define SSL3_RANDOM_LENGTH 32
4882 /* NSC_DeriveKey derives a key from a base key, creating a new key object. */
4883 CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
4884 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
4885 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
4886 CK_OBJECT_HANDLE_PTR phKey)
4888 SFTKSession * session;
4889 SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession);
4890 SFTKObject * key;
4891 SFTKObject * sourceKey;
4892 SFTKAttribute * att;
4893 SFTKAttribute * att2;
4894 unsigned char * buf;
4895 SHA1Context * sha;
4896 MD5Context * md5;
4897 MD2Context * md2;
4898 CK_ULONG macSize;
4899 CK_ULONG tmpKeySize;
4900 CK_ULONG IVSize;
4901 CK_ULONG keySize = 0;
4902 CK_RV crv = CKR_OK;
4903 CK_BBOOL cktrue = CK_TRUE;
4904 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
4905 CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
4906 CK_KEY_DERIVATION_STRING_DATA *stringPtr;
4907 PRBool isTLS = PR_FALSE;
4908 PRBool isDH = PR_FALSE;
4909 SECStatus rv;
4910 int i;
4911 unsigned int outLen;
4912 unsigned char sha_out[SHA1_LENGTH];
4913 unsigned char key_block[NUM_MIXERS * MD5_LENGTH];
4914 unsigned char key_block2[MD5_LENGTH];
4915 PRBool isFIPS;
4917 CHECK_FORK();
4919 if (!slot) {
4920 return CKR_SESSION_HANDLE_INVALID;
4923 * now lets create an object to hang the attributes off of
4925 if (phKey) *phKey = CK_INVALID_HANDLE;
4927 key = sftk_NewObject(slot); /* fill in the handle later */
4928 if (key == NULL) {
4929 return CKR_HOST_MEMORY;
4931 isFIPS = (slot->slotID == FIPS_SLOT_ID);
4934 * load the template values into the object
4936 for (i=0; i < (int) ulAttributeCount; i++) {
4937 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i]));
4938 if (crv != CKR_OK) break;
4940 if (pTemplate[i].type == CKA_KEY_TYPE) {
4941 keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
4943 if (pTemplate[i].type == CKA_VALUE_LEN) {
4944 keySize = *(CK_ULONG *)pTemplate[i].pValue;
4947 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
4949 if (keySize == 0) {
4950 keySize = sftk_MapKeySize(keyType);
4953 /* Derive can only create SECRET KEY's currently... */
4954 classType = CKO_SECRET_KEY;
4955 crv = sftk_forceAttribute (key,CKA_CLASS,&classType,sizeof(classType));
4956 if (crv != CKR_OK) {
4957 sftk_FreeObject(key);
4958 return crv;
4961 /* look up the base key we're deriving with */
4962 session = sftk_SessionFromHandle(hSession);
4963 if (session == NULL) {
4964 sftk_FreeObject(key);
4965 return CKR_SESSION_HANDLE_INVALID;
4968 sourceKey = sftk_ObjectFromHandle(hBaseKey,session);
4969 sftk_FreeSession(session);
4970 if (sourceKey == NULL) {
4971 sftk_FreeObject(key);
4972 return CKR_KEY_HANDLE_INVALID;
4975 /* get the value of the base key */
4976 att = sftk_FindAttribute(sourceKey,CKA_VALUE);
4977 if (att == NULL) {
4978 sftk_FreeObject(key);
4979 sftk_FreeObject(sourceKey);
4980 return CKR_KEY_HANDLE_INVALID;
4983 switch (pMechanism->mechanism) {
4985 * generate the master secret
4987 case CKM_TLS_MASTER_KEY_DERIVE:
4988 case CKM_TLS_MASTER_KEY_DERIVE_DH:
4989 isTLS = PR_TRUE;
4990 /* fall thru */
4991 case CKM_SSL3_MASTER_KEY_DERIVE:
4992 case CKM_SSL3_MASTER_KEY_DERIVE_DH:
4994 CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
4995 SSL3RSAPreMasterSecret * rsa_pms;
4996 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
4998 if ((pMechanism->mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) ||
4999 (pMechanism->mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH))
5000 isDH = PR_TRUE;
5002 /* first do the consistancy checks */
5003 if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
5004 crv = CKR_KEY_TYPE_INCONSISTENT;
5005 break;
5007 att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE);
5008 if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
5009 CKK_GENERIC_SECRET)) {
5010 if (att2) sftk_FreeAttribute(att2);
5011 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5012 break;
5014 sftk_FreeAttribute(att2);
5015 if (keyType != CKK_GENERIC_SECRET) {
5016 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5017 break;
5019 if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
5020 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5021 break;
5024 /* finally do the key gen */
5025 ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
5026 pMechanism->pParameter;
5028 PORT_Memcpy(crsrdata,
5029 ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
5030 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
5031 ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
5033 if (ssl3_master->pVersion) {
5034 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
5035 rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue;
5036 /* don't leak more key material then necessary for SSL to work */
5037 if ((sessKey == NULL) || sessKey->wasDerived) {
5038 ssl3_master->pVersion->major = 0xff;
5039 ssl3_master->pVersion->minor = 0xff;
5040 } else {
5041 ssl3_master->pVersion->major = rsa_pms->client_version[0];
5042 ssl3_master->pVersion->minor = rsa_pms->client_version[1];
5045 if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
5046 crv = CKR_MECHANISM_PARAM_INVALID;
5047 break;
5049 if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
5050 crv = CKR_MECHANISM_PARAM_INVALID;
5051 break;
5054 if (isTLS) {
5055 SECStatus status;
5056 SECItem crsr = { siBuffer, NULL, 0 };
5057 SECItem master = { siBuffer, NULL, 0 };
5058 SECItem pms = { siBuffer, NULL, 0 };
5060 crsr.data = crsrdata;
5061 crsr.len = sizeof crsrdata;
5062 master.data = key_block;
5063 master.len = SSL3_MASTER_SECRET_LENGTH;
5064 pms.data = (unsigned char*)att->attrib.pValue;
5065 pms.len = att->attrib.ulValueLen;
5067 status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS);
5068 if (status != SECSuccess) {
5069 crv = CKR_FUNCTION_FAILED;
5070 break;
5072 } else {
5073 /* now allocate the hash contexts */
5074 md5 = MD5_NewContext();
5075 if (md5 == NULL) {
5076 crv = CKR_HOST_MEMORY;
5077 break;
5079 sha = SHA1_NewContext();
5080 if (sha == NULL) {
5081 PORT_Free(md5);
5082 crv = CKR_HOST_MEMORY;
5083 break;
5085 for (i = 0; i < 3; i++) {
5086 SHA1_Begin(sha);
5087 SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));
5088 SHA1_Update(sha, (const unsigned char*)att->attrib.pValue,
5089 att->attrib.ulValueLen);
5090 SHA1_Update(sha, crsrdata, sizeof crsrdata);
5091 SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
5092 PORT_Assert(outLen == SHA1_LENGTH);
5094 MD5_Begin(md5);
5095 MD5_Update(md5, (const unsigned char*)att->attrib.pValue,
5096 att->attrib.ulValueLen);
5097 MD5_Update(md5, sha_out, outLen);
5098 MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);
5099 PORT_Assert(outLen == MD5_LENGTH);
5101 PORT_Free(md5);
5102 PORT_Free(sha);
5105 /* store the results */
5106 crv = sftk_forceAttribute
5107 (key,CKA_VALUE,key_block,SSL3_MASTER_SECRET_LENGTH);
5108 if (crv != CKR_OK) break;
5109 keyType = CKK_GENERIC_SECRET;
5110 crv = sftk_forceAttribute (key,CKA_KEY_TYPE,&keyType,sizeof(keyType));
5111 if (isTLS) {
5112 /* TLS's master secret is used to "sign" finished msgs with PRF. */
5113 /* XXX This seems like a hack. But SFTK_Derive only accepts
5114 * one "operation" argument. */
5115 crv = sftk_forceAttribute(key,CKA_SIGN, &cktrue,sizeof(CK_BBOOL));
5116 if (crv != CKR_OK) break;
5117 crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
5118 if (crv != CKR_OK) break;
5119 /* While we're here, we might as well force this, too. */
5120 crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
5121 if (crv != CKR_OK) break;
5123 break;
5126 case CKM_TLS_KEY_AND_MAC_DERIVE:
5127 isTLS = PR_TRUE;
5128 /* fall thru */
5129 case CKM_SSL3_KEY_AND_MAC_DERIVE:
5131 CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
5132 CK_SSL3_KEY_MAT_OUT * ssl3_keys_out;
5133 CK_ULONG effKeySize;
5134 unsigned int block_needed;
5135 unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
5136 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
5138 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5139 if (crv != CKR_OK) break;
5141 if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
5142 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5143 break;
5145 att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE);
5146 if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
5147 CKK_GENERIC_SECRET)) {
5148 if (att2) sftk_FreeAttribute(att2);
5149 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5150 break;
5152 sftk_FreeAttribute(att2);
5153 md5 = MD5_NewContext();
5154 if (md5 == NULL) {
5155 crv = CKR_HOST_MEMORY;
5156 break;
5158 sha = SHA1_NewContext();
5159 if (sha == NULL) {
5160 PORT_Free(md5);
5161 crv = CKR_HOST_MEMORY;
5162 break;
5164 ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter;
5166 PORT_Memcpy(srcrdata,
5167 ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
5168 PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
5169 ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
5171 PORT_Memcpy(crsrdata,
5172 ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
5173 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
5174 ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
5177 * clear out our returned keys so we can recover on failure
5179 ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
5180 ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;
5181 ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;
5182 ssl3_keys_out->hClientKey = CK_INVALID_HANDLE;
5183 ssl3_keys_out->hServerKey = CK_INVALID_HANDLE;
5186 * How much key material do we need?
5188 macSize = ssl3_keys->ulMacSizeInBits/8;
5189 effKeySize = ssl3_keys->ulKeySizeInBits/8;
5190 IVSize = ssl3_keys->ulIVSizeInBits/8;
5191 if (keySize == 0) {
5192 effKeySize = keySize;
5194 block_needed = 2 * (macSize + effKeySize +
5195 ((!ssl3_keys->bIsExport) * IVSize));
5196 PORT_Assert(block_needed <= sizeof key_block);
5197 if (block_needed > sizeof key_block)
5198 block_needed = sizeof key_block;
5201 * generate the key material: This looks amazingly similar to the
5202 * PMS code, and is clearly crying out for a function to provide it.
5204 if (isTLS) {
5205 SECStatus status;
5206 SECItem srcr = { siBuffer, NULL, 0 };
5207 SECItem keyblk = { siBuffer, NULL, 0 };
5208 SECItem master = { siBuffer, NULL, 0 };
5210 srcr.data = srcrdata;
5211 srcr.len = sizeof srcrdata;
5212 keyblk.data = key_block;
5213 keyblk.len = block_needed;
5214 master.data = (unsigned char*)att->attrib.pValue;
5215 master.len = att->attrib.ulValueLen;
5217 status = TLS_PRF(&master, "key expansion", &srcr, &keyblk,
5218 isFIPS);
5219 if (status != SECSuccess) {
5220 goto key_and_mac_derive_fail;
5222 } else {
5223 unsigned int block_bytes = 0;
5224 /* key_block =
5225 * MD5(master_secret + SHA('A' + master_secret +
5226 * ServerHello.random + ClientHello.random)) +
5227 * MD5(master_secret + SHA('BB' + master_secret +
5228 * ServerHello.random + ClientHello.random)) +
5229 * MD5(master_secret + SHA('CCC' + master_secret +
5230 * ServerHello.random + ClientHello.random)) +
5231 * [...];
5233 for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) {
5234 SHA1_Begin(sha);
5235 SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));
5236 SHA1_Update(sha, (const unsigned char*)att->attrib.pValue,
5237 att->attrib.ulValueLen);
5238 SHA1_Update(sha, srcrdata, sizeof srcrdata);
5239 SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
5240 PORT_Assert(outLen == SHA1_LENGTH);
5241 MD5_Begin(md5);
5242 MD5_Update(md5, (const unsigned char*)att->attrib.pValue,
5243 att->attrib.ulValueLen);
5244 MD5_Update(md5, sha_out, outLen);
5245 MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);
5246 PORT_Assert(outLen == MD5_LENGTH);
5247 block_bytes += outLen;
5252 * Put the key material where it goes.
5254 i = 0; /* now shows how much consumed */
5257 * The key_block is partitioned as follows:
5258 * client_write_MAC_secret[CipherSpec.hash_size]
5260 crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,
5261 &ssl3_keys_out->hClientMacSecret);
5262 if (crv != CKR_OK)
5263 goto key_and_mac_derive_fail;
5265 i += macSize;
5268 * server_write_MAC_secret[CipherSpec.hash_size]
5270 crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,
5271 &ssl3_keys_out->hServerMacSecret);
5272 if (crv != CKR_OK) {
5273 goto key_and_mac_derive_fail;
5275 i += macSize;
5277 if (keySize) {
5278 if (!ssl3_keys->bIsExport) {
5280 ** Generate Domestic write keys and IVs.
5281 ** client_write_key[CipherSpec.key_material]
5283 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],
5284 keySize, &ssl3_keys_out->hClientKey);
5285 if (crv != CKR_OK) {
5286 goto key_and_mac_derive_fail;
5288 i += keySize;
5291 ** server_write_key[CipherSpec.key_material]
5293 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],
5294 keySize, &ssl3_keys_out->hServerKey);
5295 if (crv != CKR_OK) {
5296 goto key_and_mac_derive_fail;
5298 i += keySize;
5301 ** client_write_IV[CipherSpec.IV_size]
5303 if (IVSize > 0) {
5304 PORT_Memcpy(ssl3_keys_out->pIVClient,
5305 &key_block[i], IVSize);
5306 i += IVSize;
5310 ** server_write_IV[CipherSpec.IV_size]
5312 if (IVSize > 0) {
5313 PORT_Memcpy(ssl3_keys_out->pIVServer,
5314 &key_block[i], IVSize);
5315 i += IVSize;
5317 PORT_Assert(i <= sizeof key_block);
5319 } else if (!isTLS) {
5322 ** Generate SSL3 Export write keys and IVs.
5323 ** client_write_key[CipherSpec.key_material]
5324 ** final_client_write_key = MD5(client_write_key +
5325 ** ClientHello.random + ServerHello.random);
5327 MD5_Begin(md5);
5328 MD5_Update(md5, &key_block[i], effKeySize);
5329 MD5_Update(md5, crsrdata, sizeof crsrdata);
5330 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
5331 i += effKeySize;
5332 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2,
5333 keySize,&ssl3_keys_out->hClientKey);
5334 if (crv != CKR_OK) {
5335 goto key_and_mac_derive_fail;
5339 ** server_write_key[CipherSpec.key_material]
5340 ** final_server_write_key = MD5(server_write_key +
5341 ** ServerHello.random + ClientHello.random);
5343 MD5_Begin(md5);
5344 MD5_Update(md5, &key_block[i], effKeySize);
5345 MD5_Update(md5, srcrdata, sizeof srcrdata);
5346 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
5347 i += effKeySize;
5348 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2,
5349 keySize,&ssl3_keys_out->hServerKey);
5350 if (crv != CKR_OK) {
5351 goto key_and_mac_derive_fail;
5355 ** client_write_IV =
5356 ** MD5(ClientHello.random + ServerHello.random);
5358 MD5_Begin(md5);
5359 MD5_Update(md5, crsrdata, sizeof crsrdata);
5360 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
5361 PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize);
5364 ** server_write_IV =
5365 ** MD5(ServerHello.random + ClientHello.random);
5367 MD5_Begin(md5);
5368 MD5_Update(md5, srcrdata, sizeof srcrdata);
5369 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
5370 PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize);
5372 } else {
5375 ** Generate TLS Export write keys and IVs.
5377 SECStatus status;
5378 SECItem secret = { siBuffer, NULL, 0 };
5379 SECItem crsr = { siBuffer, NULL, 0 };
5380 SECItem keyblk = { siBuffer, NULL, 0 };
5383 ** client_write_key[CipherSpec.key_material]
5384 ** final_client_write_key = PRF(client_write_key,
5385 ** "client write key",
5386 ** client_random + server_random);
5388 secret.data = &key_block[i];
5389 secret.len = effKeySize;
5390 i += effKeySize;
5391 crsr.data = crsrdata;
5392 crsr.len = sizeof crsrdata;
5393 keyblk.data = key_block2;
5394 keyblk.len = sizeof key_block2;
5395 status = TLS_PRF(&secret, "client write key", &crsr, &keyblk,
5396 isFIPS);
5397 if (status != SECSuccess) {
5398 goto key_and_mac_derive_fail;
5400 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2,
5401 keySize, &ssl3_keys_out->hClientKey);
5402 if (crv != CKR_OK) {
5403 goto key_and_mac_derive_fail;
5407 ** server_write_key[CipherSpec.key_material]
5408 ** final_server_write_key = PRF(server_write_key,
5409 ** "server write key",
5410 ** client_random + server_random);
5412 secret.data = &key_block[i];
5413 secret.len = effKeySize;
5414 i += effKeySize;
5415 keyblk.data = key_block2;
5416 keyblk.len = sizeof key_block2;
5417 status = TLS_PRF(&secret, "server write key", &crsr, &keyblk,
5418 isFIPS);
5419 if (status != SECSuccess) {
5420 goto key_and_mac_derive_fail;
5422 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2,
5423 keySize, &ssl3_keys_out->hServerKey);
5424 if (crv != CKR_OK) {
5425 goto key_and_mac_derive_fail;
5429 ** iv_block = PRF("", "IV block",
5430 ** client_random + server_random);
5431 ** client_write_IV[SecurityParameters.IV_size]
5432 ** server_write_IV[SecurityParameters.IV_size]
5434 if (IVSize) {
5435 secret.data = NULL;
5436 secret.len = 0;
5437 keyblk.data = &key_block[i];
5438 keyblk.len = 2 * IVSize;
5439 status = TLS_PRF(&secret, "IV block", &crsr, &keyblk,
5440 isFIPS);
5441 if (status != SECSuccess) {
5442 goto key_and_mac_derive_fail;
5444 PORT_Memcpy(ssl3_keys_out->pIVClient, keyblk.data, IVSize);
5445 PORT_Memcpy(ssl3_keys_out->pIVServer, keyblk.data + IVSize,
5446 IVSize);
5451 crv = CKR_OK;
5453 if (0) {
5454 key_and_mac_derive_fail:
5455 if (crv == CKR_OK)
5456 crv = CKR_FUNCTION_FAILED;
5457 sftk_freeSSLKeys(hSession, ssl3_keys_out);
5459 MD5_DestroyContext(md5, PR_TRUE);
5460 SHA1_DestroyContext(sha, PR_TRUE);
5461 sftk_FreeObject(key);
5462 key = NULL;
5463 break;
5466 case CKM_CONCATENATE_BASE_AND_KEY:
5468 SFTKObject *newKey;
5470 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5471 if (crv != CKR_OK) break;
5473 session = sftk_SessionFromHandle(hSession);
5474 if (session == NULL) {
5475 crv = CKR_SESSION_HANDLE_INVALID;
5476 break;
5479 newKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
5480 pMechanism->pParameter,session);
5481 sftk_FreeSession(session);
5482 if ( newKey == NULL) {
5483 crv = CKR_KEY_HANDLE_INVALID;
5484 break;
5487 if (sftk_isTrue(newKey,CKA_SENSITIVE)) {
5488 crv = sftk_forceAttribute(newKey,CKA_SENSITIVE,&cktrue,
5489 sizeof(CK_BBOOL));
5490 if (crv != CKR_OK) {
5491 sftk_FreeObject(newKey);
5492 break;
5496 att2 = sftk_FindAttribute(newKey,CKA_VALUE);
5497 if (att2 == NULL) {
5498 sftk_FreeObject(newKey);
5499 crv = CKR_KEY_HANDLE_INVALID;
5500 break;
5502 tmpKeySize = att->attrib.ulValueLen+att2->attrib.ulValueLen;
5503 if (keySize == 0) keySize = tmpKeySize;
5504 if (keySize > tmpKeySize) {
5505 sftk_FreeObject(newKey);
5506 sftk_FreeAttribute(att2);
5507 crv = CKR_TEMPLATE_INCONSISTENT;
5508 break;
5510 buf = (unsigned char*)PORT_Alloc(tmpKeySize);
5511 if (buf == NULL) {
5512 sftk_FreeAttribute(att2);
5513 sftk_FreeObject(newKey);
5514 crv = CKR_HOST_MEMORY;
5515 break;
5518 PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);
5519 PORT_Memcpy(buf+att->attrib.ulValueLen,
5520 att2->attrib.pValue,att2->attrib.ulValueLen);
5522 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
5523 PORT_ZFree(buf,tmpKeySize);
5524 sftk_FreeAttribute(att2);
5525 sftk_FreeObject(newKey);
5526 break;
5529 case CKM_CONCATENATE_BASE_AND_DATA:
5530 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5531 if (crv != CKR_OK) break;
5533 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;
5534 tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;
5535 if (keySize == 0) keySize = tmpKeySize;
5536 if (keySize > tmpKeySize) {
5537 crv = CKR_TEMPLATE_INCONSISTENT;
5538 break;
5540 buf = (unsigned char*)PORT_Alloc(tmpKeySize);
5541 if (buf == NULL) {
5542 crv = CKR_HOST_MEMORY;
5543 break;
5546 PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);
5547 PORT_Memcpy(buf+att->attrib.ulValueLen,stringPtr->pData,
5548 stringPtr->ulLen);
5550 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
5551 PORT_ZFree(buf,tmpKeySize);
5552 break;
5553 case CKM_CONCATENATE_DATA_AND_BASE:
5554 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5555 if (crv != CKR_OK) break;
5557 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
5558 tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;
5559 if (keySize == 0) keySize = tmpKeySize;
5560 if (keySize > tmpKeySize) {
5561 crv = CKR_TEMPLATE_INCONSISTENT;
5562 break;
5564 buf = (unsigned char*)PORT_Alloc(tmpKeySize);
5565 if (buf == NULL) {
5566 crv = CKR_HOST_MEMORY;
5567 break;
5570 PORT_Memcpy(buf,stringPtr->pData,stringPtr->ulLen);
5571 PORT_Memcpy(buf+stringPtr->ulLen,att->attrib.pValue,
5572 att->attrib.ulValueLen);
5574 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
5575 PORT_ZFree(buf,tmpKeySize);
5576 break;
5577 case CKM_XOR_BASE_AND_DATA:
5578 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5579 if (crv != CKR_OK) break;
5581 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
5582 tmpKeySize = PR_MIN(att->attrib.ulValueLen,stringPtr->ulLen);
5583 if (keySize == 0) keySize = tmpKeySize;
5584 if (keySize > tmpKeySize) {
5585 crv = CKR_TEMPLATE_INCONSISTENT;
5586 break;
5588 buf = (unsigned char*)PORT_Alloc(keySize);
5589 if (buf == NULL) {
5590 crv = CKR_HOST_MEMORY;
5591 break;
5595 PORT_Memcpy(buf,att->attrib.pValue,keySize);
5596 for (i=0; i < (int)keySize; i++) {
5597 buf[i] ^= stringPtr->pData[i];
5600 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
5601 PORT_ZFree(buf,keySize);
5602 break;
5604 case CKM_EXTRACT_KEY_FROM_KEY:
5606 /* the following assumes 8 bits per byte */
5607 CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
5608 CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
5609 CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
5611 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5612 if (crv != CKR_OK) break;
5614 if (keySize == 0) {
5615 crv = CKR_TEMPLATE_INCOMPLETE;
5616 break;
5618 /* make sure we have enough bits in the original key */
5619 if (att->attrib.ulValueLen <
5620 (offset + keySize + ((shift != 0)? 1 :0)) ) {
5621 crv = CKR_MECHANISM_PARAM_INVALID;
5622 break;
5624 buf = (unsigned char*)PORT_Alloc(keySize);
5625 if (buf == NULL) {
5626 crv = CKR_HOST_MEMORY;
5627 break;
5630 /* copy the bits we need into the new key */
5631 for (i=0; i < (int)keySize; i++) {
5632 unsigned char *value =
5633 ((unsigned char *)att->attrib.pValue)+offset+i;
5634 if (shift) {
5635 buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
5636 } else {
5637 buf[i] = value[0];
5641 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
5642 PORT_ZFree(buf,keySize);
5643 break;
5645 case CKM_MD2_KEY_DERIVATION:
5646 if (keySize == 0) keySize = MD2_LENGTH;
5647 if (keySize > MD2_LENGTH) {
5648 crv = CKR_TEMPLATE_INCONSISTENT;
5649 break;
5651 /* now allocate the hash contexts */
5652 md2 = MD2_NewContext();
5653 if (md2 == NULL) {
5654 crv = CKR_HOST_MEMORY;
5655 break;
5657 MD2_Begin(md2);
5658 MD2_Update(md2,(const unsigned char*)att->attrib.pValue,
5659 att->attrib.ulValueLen);
5660 MD2_End(md2,key_block,&outLen,MD2_LENGTH);
5661 MD2_DestroyContext(md2, PR_TRUE);
5663 crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize);
5664 break;
5665 case CKM_MD5_KEY_DERIVATION:
5666 if (keySize == 0) keySize = MD5_LENGTH;
5667 if (keySize > MD5_LENGTH) {
5668 crv = CKR_TEMPLATE_INCONSISTENT;
5669 break;
5671 /* now allocate the hash contexts */
5672 md5 = MD5_NewContext();
5673 if (md5 == NULL) {
5674 crv = CKR_HOST_MEMORY;
5675 break;
5677 MD5_Begin(md5);
5678 MD5_Update(md5,(const unsigned char*)att->attrib.pValue,
5679 att->attrib.ulValueLen);
5680 MD5_End(md5,key_block,&outLen,MD5_LENGTH);
5681 MD5_DestroyContext(md5, PR_TRUE);
5683 crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize);
5684 break;
5685 case CKM_SHA1_KEY_DERIVATION:
5686 if (keySize == 0) keySize = SHA1_LENGTH;
5687 if (keySize > SHA1_LENGTH) {
5688 crv = CKR_TEMPLATE_INCONSISTENT;
5689 break;
5691 /* now allocate the hash contexts */
5692 sha = SHA1_NewContext();
5693 if (sha == NULL) {
5694 crv = CKR_HOST_MEMORY;
5695 break;
5697 SHA1_Begin(sha);
5698 SHA1_Update(sha,(const unsigned char*)att->attrib.pValue,
5699 att->attrib.ulValueLen);
5700 SHA1_End(sha,key_block,&outLen,SHA1_LENGTH);
5701 SHA1_DestroyContext(sha, PR_TRUE);
5703 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
5704 break;
5706 case CKM_DH_PKCS_DERIVE:
5708 SECItem derived, dhPublic;
5709 SECItem dhPrime, dhValue;
5710 /* sourceKey - values for the local existing low key */
5711 /* get prime and value attributes */
5712 crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
5713 if (crv != SECSuccess) break;
5714 crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
5715 if (crv != SECSuccess) {
5716 PORT_Free(dhPrime.data);
5717 break;
5720 dhPublic.data = pMechanism->pParameter;
5721 dhPublic.len = pMechanism->ulParameterLen;
5723 /* calculate private value - oct */
5724 rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
5726 PORT_Free(dhPrime.data);
5727 PORT_Free(dhValue.data);
5729 if (rv == SECSuccess) {
5730 sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
5731 PORT_ZFree(derived.data, derived.len);
5732 } else
5733 crv = CKR_HOST_MEMORY;
5735 break;
5738 #ifdef NSS_ENABLE_ECC
5739 case CKM_ECDH1_DERIVE:
5740 case CKM_ECDH1_COFACTOR_DERIVE:
5742 SECItem ecScalar, ecPoint;
5743 SECItem tmp;
5744 PRBool withCofactor = PR_FALSE;
5745 unsigned char secret_hash[20];
5746 unsigned char *secret;
5747 unsigned char *keyData = NULL;
5748 int secretlen;
5749 CK_ECDH1_DERIVE_PARAMS *mechParams;
5750 NSSLOWKEYPrivateKey *privKey;
5752 /* Check mechanism parameters */
5753 mechParams = (CK_ECDH1_DERIVE_PARAMS *) pMechanism->pParameter;
5754 if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) ||
5755 ((mechParams->kdf == CKD_NULL) &&
5756 ((mechParams->ulSharedDataLen != 0) ||
5757 (mechParams->pSharedData != NULL)))) {
5758 crv = CKR_MECHANISM_PARAM_INVALID;
5759 break;
5762 privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv);
5763 if (privKey == NULL) {
5764 break;
5767 /* Now we are working with a non-NULL private key */
5768 SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue);
5770 ecPoint.data = mechParams->pPublicData;
5771 ecPoint.len = mechParams->ulPublicDataLen;
5773 if (pMechanism->mechanism == CKM_ECDH1_COFACTOR_DERIVE) {
5774 withCofactor = PR_TRUE;
5775 } else {
5776 /* When not using cofactor derivation, one should
5777 * validate the public key to avoid small subgroup
5778 * attacks.
5780 if (EC_ValidatePublicKey(&privKey->u.ec.ecParams, &ecPoint)
5781 != SECSuccess) {
5782 crv = CKR_ARGUMENTS_BAD;
5783 PORT_Free(ecScalar.data);
5784 if (privKey != sourceKey->objectInfo)
5785 nsslowkey_DestroyPrivateKey(privKey);
5786 break;
5790 rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
5791 withCofactor, &tmp);
5792 PORT_Free(ecScalar.data);
5793 if (privKey != sourceKey->objectInfo)
5794 nsslowkey_DestroyPrivateKey(privKey);
5796 if (rv != SECSuccess) {
5797 crv = CKR_DEVICE_ERROR;
5798 break;
5802 * tmp is the raw data created by ECDH_Derive,
5803 * secret and secretlen are the values we will eventually pass as our
5804 * generated key.
5806 secret = tmp.data;
5807 secretlen = tmp.len;
5810 * apply the kdf function.
5812 if (mechParams->kdf == CKD_SHA1_KDF) {
5813 /* Compute SHA1 hash */
5814 PORT_Memset(secret_hash, 0, 20);
5815 rv = SHA1_HashBuf(secret_hash, tmp.data, tmp.len);
5816 if (rv != SECSuccess) {
5817 PORT_ZFree(tmp.data, tmp.len);
5818 crv = CKR_HOST_MEMORY;
5819 break;
5821 secret = secret_hash;
5822 secretlen = 20;
5826 * if keySize is supplied, then we are generating a key of a specific
5827 * length. This is done by taking the least significant 'keySize'
5828 * bytes from the unsigned value calculated by ECDH. Note: this may
5829 * mean padding temp with extra leading zeros from what ECDH_Derive
5830 * already returned (which itself may contain leading zeros).
5832 if (keySize) {
5833 if (secretlen < keySize) {
5834 keyData = PORT_ZAlloc(keySize);
5835 if (!keyData) {
5836 PORT_ZFree(tmp.data, tmp.len);
5837 crv = CKR_HOST_MEMORY;
5838 break;
5840 PORT_Memcpy(&keyData[keySize-secretlen],secret,secretlen);
5841 secret = keyData;
5842 } else {
5843 secret += (secretlen - keySize);
5845 secretlen = keySize;
5848 sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
5849 PORT_ZFree(tmp.data, tmp.len);
5850 if (keyData) {
5851 PORT_ZFree(keyData, keySize);
5853 PORT_Memset(secret_hash, 0, 20);
5855 break;
5857 #endif /* NSS_ENABLE_ECC */
5859 default:
5860 crv = CKR_MECHANISM_INVALID;
5862 sftk_FreeAttribute(att);
5863 sftk_FreeObject(sourceKey);
5864 if (crv != CKR_OK) {
5865 if (key) sftk_FreeObject(key);
5866 return crv;
5869 /* link the key object into the list */
5870 if (key) {
5871 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
5872 PORT_Assert(sessKey);
5873 /* get the session */
5874 sessKey->wasDerived = PR_TRUE;
5875 session = sftk_SessionFromHandle(hSession);
5876 if (session == NULL) {
5877 sftk_FreeObject(key);
5878 return CKR_HOST_MEMORY;
5881 crv = sftk_handleObject(key,session);
5882 sftk_FreeSession(session);
5883 *phKey = key->handle;
5884 sftk_FreeObject(key);
5886 return crv;
5890 /* NSC_GetFunctionStatus obtains an updated status of a function running
5891 * in parallel with an application. */
5892 CK_RV NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
5894 CHECK_FORK();
5896 return CKR_FUNCTION_NOT_PARALLEL;
5899 /* NSC_CancelFunction cancels a function running in parallel */
5900 CK_RV NSC_CancelFunction(CK_SESSION_HANDLE hSession)
5902 CHECK_FORK();
5904 return CKR_FUNCTION_NOT_PARALLEL;
5907 /* NSC_GetOperationState saves the state of the cryptographic
5908 *operation in a session.
5909 * NOTE: This code only works for digest functions for now. eventually need
5910 * to add full flatten/resurect to our state stuff so that all types of state
5911 * can be saved */
5912 CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession,
5913 CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
5915 SFTKSessionContext *context;
5916 SFTKSession *session;
5917 CK_RV crv;
5918 CK_ULONG pOSLen = *pulOperationStateLen;
5920 CHECK_FORK();
5922 /* make sure we're legal */
5923 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
5924 if (crv != CKR_OK) return crv;
5926 *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE)
5927 + sizeof(SFTKContextType);
5928 if (pOperationState == NULL) {
5929 sftk_FreeSession(session);
5930 return CKR_OK;
5931 } else {
5932 if (pOSLen < *pulOperationStateLen) {
5933 return CKR_BUFFER_TOO_SMALL;
5936 PORT_Memcpy(pOperationState,&context->type,sizeof(SFTKContextType));
5937 pOperationState += sizeof(SFTKContextType);
5938 PORT_Memcpy(pOperationState,&context->currentMech,
5939 sizeof(CK_MECHANISM_TYPE));
5940 pOperationState += sizeof(CK_MECHANISM_TYPE);
5941 PORT_Memcpy(pOperationState,context->cipherInfo,context->cipherInfoLen);
5942 sftk_FreeSession(session);
5943 return CKR_OK;
5947 #define sftk_Decrement(stateSize,len) \
5948 stateSize = ((stateSize) > (CK_ULONG)(len)) ? \
5949 ((stateSize) - (CK_ULONG)(len)) : 0;
5951 /* NSC_SetOperationState restores the state of the cryptographic
5952 * operation in a session. This is coded like it can restore lots of
5953 * states, but it only works for truly flat cipher structures. */
5954 CK_RV NSC_SetOperationState(CK_SESSION_HANDLE hSession,
5955 CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
5956 CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
5958 SFTKSessionContext *context;
5959 SFTKSession *session;
5960 SFTKContextType type;
5961 CK_MECHANISM mech;
5962 CK_RV crv = CKR_OK;
5964 CHECK_FORK();
5966 while (ulOperationStateLen != 0) {
5967 /* get what type of state we're dealing with... */
5968 PORT_Memcpy(&type,pOperationState, sizeof(SFTKContextType));
5970 /* fix up session contexts based on type */
5971 session = sftk_SessionFromHandle(hSession);
5972 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5973 context = sftk_ReturnContextByType(session, type);
5974 sftk_SetContextByType(session, type, NULL);
5975 if (context) {
5976 sftk_FreeContext(context);
5978 pOperationState += sizeof(SFTKContextType);
5979 sftk_Decrement(ulOperationStateLen,sizeof(SFTKContextType));
5982 /* get the mechanism structure */
5983 PORT_Memcpy(&mech.mechanism,pOperationState,sizeof(CK_MECHANISM_TYPE));
5984 pOperationState += sizeof(CK_MECHANISM_TYPE);
5985 sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
5986 /* should be filled in... but not necessary for hash */
5987 mech.pParameter = NULL;
5988 mech.ulParameterLen = 0;
5989 switch (type) {
5990 case SFTK_HASH:
5991 crv = NSC_DigestInit(hSession,&mech);
5992 if (crv != CKR_OK) break;
5993 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE,
5994 NULL);
5995 if (crv != CKR_OK) break;
5996 PORT_Memcpy(context->cipherInfo,pOperationState,
5997 context->cipherInfoLen);
5998 pOperationState += context->cipherInfoLen;
5999 sftk_Decrement(ulOperationStateLen,context->cipherInfoLen);
6000 break;
6001 default:
6002 /* do sign/encrypt/decrypt later */
6003 crv = CKR_SAVED_STATE_INVALID;
6005 sftk_FreeSession(session);
6006 if (crv != CKR_OK) break;
6008 return crv;
6011 /* Dual-function cryptographic operations */
6013 /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
6014 * operation. */
6015 CK_RV NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
6016 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
6017 CK_ULONG_PTR pulEncryptedPartLen)
6019 CK_RV crv;
6021 CHECK_FORK();
6023 crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart,
6024 pulEncryptedPartLen);
6025 if (crv != CKR_OK) return crv;
6026 crv = NSC_DigestUpdate(hSession,pPart,ulPartLen);
6028 return crv;
6032 /* NSC_DecryptDigestUpdate continues a multiple-part decryption and
6033 * digesting operation. */
6034 CK_RV NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
6035 CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
6036 CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
6038 CK_RV crv;
6040 CHECK_FORK();
6042 crv = NSC_DecryptUpdate(hSession,pEncryptedPart, ulEncryptedPartLen,
6043 pPart, pulPartLen);
6044 if (crv != CKR_OK) return crv;
6045 crv = NSC_DigestUpdate(hSession,pPart,*pulPartLen);
6047 return crv;
6051 /* NSC_SignEncryptUpdate continues a multiple-part signing and
6052 * encryption operation. */
6053 CK_RV NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
6054 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
6055 CK_ULONG_PTR pulEncryptedPartLen)
6057 CK_RV crv;
6059 CHECK_FORK();
6061 crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart,
6062 pulEncryptedPartLen);
6063 if (crv != CKR_OK) return crv;
6064 crv = NSC_SignUpdate(hSession,pPart,ulPartLen);
6066 return crv;
6070 /* NSC_DecryptVerifyUpdate continues a multiple-part decryption
6071 * and verify operation. */
6072 CK_RV NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
6073 CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
6074 CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
6076 CK_RV crv;
6078 CHECK_FORK();
6080 crv = NSC_DecryptUpdate(hSession,pEncryptedData, ulEncryptedDataLen,
6081 pData, pulDataLen);
6082 if (crv != CKR_OK) return crv;
6083 crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
6085 return crv;
6088 /* NSC_DigestKey continues a multi-part message-digesting operation,
6089 * by digesting the value of a secret key as part of the data already digested.
6091 CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
6093 SFTKSession *session = NULL;
6094 SFTKObject *key = NULL;
6095 SFTKAttribute *att;
6096 CK_RV crv;
6098 CHECK_FORK();
6100 session = sftk_SessionFromHandle(hSession);
6101 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6103 key = sftk_ObjectFromHandle(hKey,session);
6104 sftk_FreeSession(session);
6105 if (key == NULL) return CKR_KEY_HANDLE_INVALID;
6107 /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
6109 /* make sure it's a valid key for this operation */
6110 if (key->objclass != CKO_SECRET_KEY) {
6111 sftk_FreeObject(key);
6112 return CKR_KEY_TYPE_INCONSISTENT;
6114 /* get the key value */
6115 att = sftk_FindAttribute(key,CKA_VALUE);
6116 sftk_FreeObject(key);
6117 if (!att) {
6118 return CKR_KEY_HANDLE_INVALID;
6120 crv = NSC_DigestUpdate(hSession,(CK_BYTE_PTR)att->attrib.pValue,
6121 att->attrib.ulValueLen);
6122 sftk_FreeAttribute(att);
6123 return crv;