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
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.
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.
64 #include "lowpbe.h" /* We do PBE below */
74 #define __PASTE(x,y) x##y
77 * we renamed all our internal functions, get the correct
78 * definitions for them...
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
91 uint8 client_version[2];
93 } SSL3RSAPreMasterSecret;
95 static void sftk_Null(void *data, PRBool freeit)
100 #ifdef NSS_ENABLE_ECC
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]); \
110 #define SEC_PRINT(a, b, c, d)
112 #endif /* NSS_ENABLE_ECC */
115 * free routines.... Free local type allocated data, and convert
116 * other free routines to the destroy signature.
119 sftk_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit)
121 nsslowkey_DestroyPrivateKey(key);
125 sftk_Space(void *data, PRBool freeit)
131 * map all the SEC_ERROR_xxx error codes that may be returned by freebl
132 * functions to CKR_xxx. return CKR_DEVICE_ERROR by default for backward
136 sftk_MapCryptError(int error)
139 case SEC_ERROR_INVALID_ARGS:
140 case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */
141 return CKR_ARGUMENTS_BAD;
142 case SEC_ERROR_INPUT_LEN:
143 return CKR_DATA_LEN_RANGE;
144 case SEC_ERROR_OUTPUT_LEN:
145 return CKR_BUFFER_TOO_SMALL;
146 case SEC_ERROR_LIBRARY_FAILURE:
147 return CKR_GENERAL_ERROR;
148 case SEC_ERROR_NO_MEMORY:
149 return CKR_HOST_MEMORY;
150 case SEC_ERROR_BAD_SIGNATURE:
151 return CKR_SIGNATURE_INVALID;
152 case SEC_ERROR_INVALID_KEY:
153 return CKR_KEY_SIZE_RANGE;
154 case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */
155 return CKR_KEY_SIZE_RANGE; /* the closest error code */
156 case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM:
157 return CKR_TEMPLATE_INCONSISTENT;
158 /* EC functions set this error if NSS_ENABLE_ECC is not defined */
159 case SEC_ERROR_UNSUPPORTED_KEYALG:
160 return CKR_MECHANISM_INVALID;
161 case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE:
162 return CKR_DOMAIN_PARAMS_INVALID;
163 /* key pair generation failed after max number of attempts */
164 case SEC_ERROR_NEED_RANDOM:
165 return CKR_FUNCTION_FAILED;
167 return CKR_DEVICE_ERROR;
170 /* used by Decrypt and UnwrapKey (indirectly) */
172 sftk_MapDecryptError(int error)
175 case SEC_ERROR_BAD_DATA:
176 return CKR_ENCRYPTED_DATA_INVALID;
178 return sftk_MapCryptError(error);
183 * return CKR_SIGNATURE_INVALID instead of CKR_DEVICE_ERROR by default for
184 * backward compatibilty.
187 sftk_MapVerifyError(int error)
189 CK_RV crv = sftk_MapCryptError(error);
190 if (crv == CKR_DEVICE_ERROR)
191 crv = CKR_SIGNATURE_INVALID;
197 * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
198 * Deprecating a full des key to 40 bit key strenth.
201 sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
203 unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
204 unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
205 unsigned char enc_src[8];
206 unsigned char enc_dest[8];
212 /* zero the parity bits */
213 for (i=0; i < 8; i++) {
214 enc_src[i] = cdmfkey[i] & 0xfe;
217 /* encrypt with key 1 */
218 descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);
219 if (descx == NULL) return CKR_HOST_MEMORY;
220 rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);
221 DES_DestroyContext(descx,PR_TRUE);
222 if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError());
224 /* xor source with des, zero the parity bits and deprecate the key*/
225 for (i=0; i < 8; i++) {
227 enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;
229 enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;
233 /* encrypt with key 2 */
234 descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);
235 if (descx == NULL) return CKR_HOST_MEMORY;
236 rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);
237 DES_DestroyContext(descx,PR_TRUE);
238 if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError());
240 /* set the corret parity on our new des key */
241 sftk_FormatDESKey(deskey, 8);
246 /* NSC_DestroyObject destroys an object. */
248 NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
250 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
251 SFTKSession *session;
253 SFTKFreeStatus status;
258 return CKR_SESSION_HANDLE_INVALID;
261 * This whole block just makes sure we really can destroy the
264 session = sftk_SessionFromHandle(hSession);
265 if (session == NULL) {
266 return CKR_SESSION_HANDLE_INVALID;
269 object = sftk_ObjectFromHandle(hObject,session);
270 if (object == NULL) {
271 sftk_FreeSession(session);
272 return CKR_OBJECT_HANDLE_INVALID;
275 /* don't destroy a private object if we aren't logged in */
276 if ((!slot->isLoggedIn) && (slot->needLogin) &&
277 (sftk_isTrue(object,CKA_PRIVATE))) {
278 sftk_FreeSession(session);
279 sftk_FreeObject(object);
280 return CKR_USER_NOT_LOGGED_IN;
283 /* don't destroy a token object if we aren't in a rw session */
285 if (((session->info.flags & CKF_RW_SESSION) == 0) &&
286 (sftk_isTrue(object,CKA_TOKEN))) {
287 sftk_FreeSession(session);
288 sftk_FreeObject(object);
289 return CKR_SESSION_READ_ONLY;
292 sftk_DeleteObject(session,object);
294 sftk_FreeSession(session);
297 * get some indication if the object is destroyed. Note: this is not
298 * 100%. Someone may have an object reference outstanding (though that
299 * should not be the case by here. Also note that the object is "half"
300 * destroyed. Our internal representation is destroyed, but it may still
301 * be in the data base.
303 status = sftk_FreeObject(object);
305 return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
310 ************** Crypto Functions: Utilities ************************
315 * return a context based on the SFTKContext type.
318 sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
323 return session->enc_context;
325 return session->hash_context;
327 case SFTK_SIGN_RECOVER:
329 case SFTK_VERIFY_RECOVER:
330 return session->hash_context;
336 * change a context based on the SFTKContext type.
339 sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
340 SFTKSessionContext *context)
345 session->enc_context = context;
348 session->hash_context = context;
351 case SFTK_SIGN_RECOVER:
353 case SFTK_VERIFY_RECOVER:
354 session->hash_context = context;
361 * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
362 * and C_XXX function. The function takes a session handle, the context type,
363 * and wether or not the session needs to be multipart. It returns the context,
364 * and optionally returns the session pointer (if sessionPtr != NULL) if session
365 * pointer is returned, the caller is responsible for freeing it.
368 sftk_GetContext(CK_SESSION_HANDLE handle,SFTKSessionContext **contextPtr,
369 SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr)
371 SFTKSession *session;
372 SFTKSessionContext *context;
374 session = sftk_SessionFromHandle(handle);
375 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
376 context = sftk_ReturnContextByType(session,type);
377 /* make sure the context is valid */
378 if((context==NULL)||(context->type!=type)||(needMulti&&!(context->multi))){
379 sftk_FreeSession(session);
380 return CKR_OPERATION_NOT_INITIALIZED;
382 *contextPtr = context;
383 if (sessionPtr != NULL) {
384 *sessionPtr = session;
386 sftk_FreeSession(session);
391 /** Terminate operation (in the PKCS#11 spec sense).
392 * Intuitive name for FreeContext/SetNullContext pair.
395 sftk_TerminateOp( SFTKSession *session, SFTKContextType ctype,
396 SFTKSessionContext *context )
398 sftk_FreeContext( context );
399 sftk_SetContextByType( session, ctype, NULL );
403 ************** Crypto Functions: Encrypt ************************
407 * All the NSC_InitXXX functions have a set of common checks and processing they
408 * all need to do at the beginning. This is done here.
411 sftk_InitGeneric(SFTKSession *session,SFTKSessionContext **contextPtr,
412 SFTKContextType ctype,SFTKObject **keyPtr,
413 CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
414 CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation)
416 SFTKObject *key = NULL;
418 SFTKSessionContext *context;
420 /* We can only init if there is not current context active */
421 if (sftk_ReturnContextByType(session,ctype) != NULL) {
422 return CKR_OPERATION_ACTIVE;
427 key = sftk_ObjectFromHandle(hKey,session);
429 return CKR_KEY_HANDLE_INVALID;
432 /* make sure it's a valid key for this operation */
433 if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType))
434 || !sftk_isTrue(key,operation)) {
435 sftk_FreeObject(key);
436 return CKR_KEY_TYPE_INCONSISTENT;
438 /* get the key type */
439 att = sftk_FindAttribute(key,CKA_KEY_TYPE);
441 sftk_FreeObject(key);
442 return CKR_KEY_TYPE_INCONSISTENT;
444 PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE));
445 if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) {
446 sftk_FreeAttribute(att);
447 sftk_FreeObject(key);
448 return CKR_ATTRIBUTE_VALUE_INVALID;
450 PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE));
451 sftk_FreeAttribute(att);
455 /* allocate the context structure */
456 context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext));
457 if (context == NULL) {
458 if (key) sftk_FreeObject(key);
459 return CKR_HOST_MEMORY;
461 context->type = ctype;
462 context->multi = PR_TRUE;
463 context->cipherInfo = NULL;
464 context->hashInfo = NULL;
465 context->doPad = PR_FALSE;
466 context->padDataLength = 0;
468 context->blockSize = 0;
470 *contextPtr = context;
474 /** NSC_CryptInit initializes an encryption/Decryption operation.
476 * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
477 * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block
481 sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
482 CK_OBJECT_HANDLE hKey,
483 CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage,
484 SFTKContextType contextType, PRBool isEncrypt)
486 SFTKSession *session;
488 SFTKSessionContext *context;
490 CK_RC2_CBC_PARAMS *rc2_param;
491 #if NSS_SOFTOKEN_DOES_RC5
492 CK_RC5_CBC_PARAMS *rc5_param;
495 CK_KEY_TYPE key_type;
497 unsigned effectiveKeyLength;
498 unsigned char newdeskey[24];
499 PRBool useNewKey=PR_FALSE;
502 crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage );
506 session = sftk_SessionFromHandle(hSession);
507 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
509 crv = sftk_InitGeneric(session,&context,contextType,&key,hKey,&key_type,
510 isEncrypt ?CKO_PUBLIC_KEY:CKO_PRIVATE_KEY, keyUsage);
513 sftk_FreeSession(session);
517 context->doPad = PR_FALSE;
518 switch(pMechanism->mechanism) {
521 if (key_type != CKK_RSA) {
522 crv = CKR_KEY_TYPE_INCONSISTENT;
525 context->multi = PR_FALSE;
527 NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key,CKK_RSA,&crv);
528 if (pubKey == NULL) {
531 context->maxLen = nsslowkey_PublicModulusLen(pubKey);
532 context->cipherInfo = (void *)pubKey;
533 context->update = (SFTKCipher)
534 (pMechanism->mechanism == CKM_RSA_X_509
535 ? RSA_EncryptRaw : RSA_EncryptBlock);
537 NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key,CKK_RSA,&crv);
538 if (privKey == NULL) {
541 context->maxLen = nsslowkey_PrivateModulusLen(privKey);
542 context->cipherInfo = (void *)privKey;
543 context->update = (SFTKCipher)
544 (pMechanism->mechanism == CKM_RSA_X_509
545 ? RSA_DecryptRaw : RSA_DecryptBlock);
547 context->destroy = sftk_Null;
549 case CKM_RC2_CBC_PAD:
550 context->doPad = PR_TRUE;
554 context->blockSize = 8;
555 if (key_type != CKK_RC2) {
556 crv = CKR_KEY_TYPE_INCONSISTENT;
559 att = sftk_FindAttribute(key,CKA_VALUE);
561 crv = CKR_KEY_HANDLE_INVALID;
564 rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
565 effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8;
566 context->cipherInfo =
567 RC2_CreateContext((unsigned char*)att->attrib.pValue,
568 att->attrib.ulValueLen, rc2_param->iv,
569 pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 :
570 NSS_RC2_CBC,effectiveKeyLength);
571 sftk_FreeAttribute(att);
572 if (context->cipherInfo == NULL) {
573 crv = CKR_HOST_MEMORY;
576 context->update = (SFTKCipher) (isEncrypt ? RC2_Encrypt : RC2_Decrypt);
577 context->destroy = (SFTKDestroy) RC2_DestroyContext;
579 #if NSS_SOFTOKEN_DOES_RC5
580 case CKM_RC5_CBC_PAD:
581 context->doPad = PR_TRUE;
585 if (key_type != CKK_RC5) {
586 crv = CKR_KEY_TYPE_INCONSISTENT;
589 att = sftk_FindAttribute(key,CKA_VALUE);
591 crv = CKR_KEY_HANDLE_INVALID;
594 rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
595 context->blockSize = rc5_param->ulWordsize*2;
596 rc5Key.data = (unsigned char*)att->attrib.pValue;
597 rc5Key.len = att->attrib.ulValueLen;
598 context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds,
599 rc5_param->ulWordsize,rc5_param->pIv,
600 pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
601 sftk_FreeAttribute(att);
602 if (context->cipherInfo == NULL) {
603 crv = CKR_HOST_MEMORY;
606 context->update = (SFTKCipher) (isEncrypt ? RC5_Encrypt : RC5_Decrypt);
607 context->destroy = (SFTKDestroy) RC5_DestroyContext;
611 if (key_type != CKK_RC4) {
612 crv = CKR_KEY_TYPE_INCONSISTENT;
615 att = sftk_FindAttribute(key,CKA_VALUE);
617 crv = CKR_KEY_HANDLE_INVALID;
620 context->cipherInfo =
621 RC4_CreateContext((unsigned char*)att->attrib.pValue,
622 att->attrib.ulValueLen);
623 sftk_FreeAttribute(att);
624 if (context->cipherInfo == NULL) {
625 crv = CKR_HOST_MEMORY; /* WRONG !!! */
628 context->update = (SFTKCipher) (isEncrypt ? RC4_Encrypt : RC4_Decrypt);
629 context->destroy = (SFTKDestroy) RC4_DestroyContext;
631 case CKM_CDMF_CBC_PAD:
632 context->doPad = PR_TRUE;
636 if (key_type != CKK_CDMF) {
637 crv = CKR_KEY_TYPE_INCONSISTENT;
640 t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
641 if (crv != CKR_OK) break;
644 if (key_type != CKK_DES) {
645 crv = CKR_KEY_TYPE_INCONSISTENT;
650 case CKM_DES_CBC_PAD:
651 context->doPad = PR_TRUE;
654 if (key_type != CKK_DES) {
655 crv = CKR_KEY_TYPE_INCONSISTENT;
661 if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
662 crv = CKR_KEY_TYPE_INCONSISTENT;
667 case CKM_DES3_CBC_PAD:
668 context->doPad = PR_TRUE;
671 if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
672 crv = CKR_KEY_TYPE_INCONSISTENT;
675 t = NSS_DES_EDE3_CBC;
677 context->blockSize = 8;
678 att = sftk_FindAttribute(key,CKA_VALUE);
680 crv = CKR_KEY_HANDLE_INVALID;
683 if (key_type == CKK_DES2 &&
684 (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) {
685 /* extend DES2 key to DES3 key. */
686 memcpy(newdeskey, att->attrib.pValue, 16);
687 memcpy(newdeskey + 16, newdeskey, 8);
689 } else if (key_type == CKK_CDMF) {
690 crv = sftk_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey);
692 sftk_FreeAttribute(att);
697 context->cipherInfo = DES_CreateContext(
698 useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue,
699 (unsigned char*)pMechanism->pParameter,t, isEncrypt);
701 memset(newdeskey, 0, sizeof newdeskey);
702 sftk_FreeAttribute(att);
703 if (context->cipherInfo == NULL) {
704 crv = CKR_HOST_MEMORY;
707 context->update = (SFTKCipher) (isEncrypt ? DES_Encrypt : DES_Decrypt);
708 context->destroy = (SFTKDestroy) DES_DestroyContext;
710 case CKM_SEED_CBC_PAD:
711 context->doPad = PR_TRUE;
714 if (!pMechanism->pParameter ||
715 pMechanism->ulParameterLen != 16) {
716 crv = CKR_MECHANISM_PARAM_INVALID;
721 context->blockSize = 16;
722 if (key_type != CKK_SEED) {
723 crv = CKR_KEY_TYPE_INCONSISTENT;
726 att = sftk_FindAttribute(key,CKA_VALUE);
728 crv = CKR_KEY_HANDLE_INVALID;
731 context->cipherInfo = SEED_CreateContext(
732 (unsigned char*)att->attrib.pValue,
733 (unsigned char*)pMechanism->pParameter,
734 pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC,
736 sftk_FreeAttribute(att);
737 if (context->cipherInfo == NULL) {
738 crv = CKR_HOST_MEMORY;
741 context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt);
742 context->destroy = (SFTKDestroy) SEED_DestroyContext;
745 case CKM_CAMELLIA_CBC_PAD:
746 context->doPad = PR_TRUE;
748 case CKM_CAMELLIA_CBC:
749 if (!pMechanism->pParameter ||
750 pMechanism->ulParameterLen != 16) {
751 crv = CKR_MECHANISM_PARAM_INVALID;
755 case CKM_CAMELLIA_ECB:
756 context->blockSize = 16;
757 if (key_type != CKK_CAMELLIA) {
758 crv = CKR_KEY_TYPE_INCONSISTENT;
761 att = sftk_FindAttribute(key,CKA_VALUE);
763 crv = CKR_KEY_HANDLE_INVALID;
766 context->cipherInfo = Camellia_CreateContext(
767 (unsigned char*)att->attrib.pValue,
768 (unsigned char*)pMechanism->pParameter,
769 pMechanism->mechanism ==
770 CKM_CAMELLIA_ECB ? NSS_CAMELLIA : NSS_CAMELLIA_CBC,
771 isEncrypt, att->attrib.ulValueLen);
772 sftk_FreeAttribute(att);
773 if (context->cipherInfo == NULL) {
774 crv = CKR_HOST_MEMORY;
777 context->update = (SFTKCipher) (isEncrypt ?
778 Camellia_Encrypt : Camellia_Decrypt);
779 context->destroy = (SFTKDestroy) Camellia_DestroyContext;
782 case CKM_AES_CBC_PAD:
783 context->doPad = PR_TRUE;
787 context->blockSize = 16;
788 if (key_type != CKK_AES) {
789 crv = CKR_KEY_TYPE_INCONSISTENT;
792 att = sftk_FindAttribute(key,CKA_VALUE);
794 crv = CKR_KEY_HANDLE_INVALID;
797 context->cipherInfo = AES_CreateContext(
798 (unsigned char*)att->attrib.pValue,
799 (unsigned char*)pMechanism->pParameter,
800 pMechanism->mechanism == CKM_AES_ECB ? NSS_AES : NSS_AES_CBC,
801 isEncrypt, att->attrib.ulValueLen, 16);
802 sftk_FreeAttribute(att);
803 if (context->cipherInfo == NULL) {
804 crv = CKR_HOST_MEMORY;
807 context->update = (SFTKCipher) (isEncrypt ? AES_Encrypt : AES_Decrypt);
808 context->destroy = (SFTKDestroy) AES_DestroyContext;
811 case CKM_NETSCAPE_AES_KEY_WRAP_PAD:
812 context->doPad = PR_TRUE;
814 case CKM_NETSCAPE_AES_KEY_WRAP:
815 context->multi = PR_FALSE;
816 context->blockSize = 8;
817 if (key_type != CKK_AES) {
818 crv = CKR_KEY_TYPE_INCONSISTENT;
821 att = sftk_FindAttribute(key,CKA_VALUE);
823 crv = CKR_KEY_HANDLE_INVALID;
826 context->cipherInfo = AESKeyWrap_CreateContext(
827 (unsigned char*)att->attrib.pValue,
828 (unsigned char*)pMechanism->pParameter,
829 isEncrypt, att->attrib.ulValueLen);
830 sftk_FreeAttribute(att);
831 if (context->cipherInfo == NULL) {
832 crv = CKR_HOST_MEMORY;
835 context->update = (SFTKCipher) (isEncrypt ? AESKeyWrap_Encrypt
836 : AESKeyWrap_Decrypt);
837 context->destroy = (SFTKDestroy) AESKeyWrap_DestroyContext;
841 crv = CKR_MECHANISM_INVALID;
846 sftk_FreeContext(context);
847 sftk_FreeSession(session);
850 sftk_SetContextByType(session, contextType, context);
851 sftk_FreeSession(session);
855 /* NSC_EncryptInit initializes an encryption operation. */
856 CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession,
857 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
860 return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT,
861 SFTK_ENCRYPT, PR_TRUE);
864 /* NSC_EncryptUpdate continues a multiple-part encryption operation. */
865 CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
866 CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
867 CK_ULONG_PTR pulEncryptedPartLen)
869 SFTKSessionContext *context;
870 unsigned int outlen,i;
871 unsigned int padoutlen = 0;
872 unsigned int maxout = *pulEncryptedPartLen;
878 /* make sure we're legal */
879 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,NULL);
880 if (crv != CKR_OK) return crv;
882 if (!pEncryptedPart) {
883 if (context->doPad) {
884 CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength;
885 CK_ULONG blocksToSend = totalDataAvailable/context->blockSize;
887 *pulEncryptedPartLen = blocksToSend * context->blockSize;
890 *pulEncryptedPartLen = ulPartLen;
895 if (context->doPad) {
896 /* deal with previous buffered data */
897 if (context->padDataLength != 0) {
898 /* fill in the padded to a full block size */
899 for (i=context->padDataLength;
900 (ulPartLen != 0) && i < context->blockSize; i++) {
901 context->padBuf[i] = *pPart++;
903 context->padDataLength++;
906 /* not enough data to encrypt yet? then return */
907 if (context->padDataLength != context->blockSize) {
908 *pulEncryptedPartLen = 0;
911 /* encrypt the current padded data */
912 rv = (*context->update)(context->cipherInfo, pEncryptedPart,
913 &padoutlen, context->blockSize, context->padBuf,
915 if (rv != SECSuccess) {
916 return sftk_MapCryptError(PORT_GetError());
918 pEncryptedPart += padoutlen;
921 /* save the residual */
922 context->padDataLength = ulPartLen % context->blockSize;
923 if (context->padDataLength) {
924 PORT_Memcpy(context->padBuf,
925 &pPart[ulPartLen-context->padDataLength],
926 context->padDataLength);
927 ulPartLen -= context->padDataLength;
929 /* if we've exhausted our new buffer, we're done */
930 if (ulPartLen == 0) {
931 *pulEncryptedPartLen = padoutlen;
937 /* do it: NOTE: this assumes buf size in is >= buf size out! */
938 rv = (*context->update)(context->cipherInfo,pEncryptedPart,
939 &outlen, maxout, pPart, ulPartLen);
940 *pulEncryptedPartLen = (CK_ULONG) (outlen + padoutlen);
941 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
945 /* NSC_EncryptFinal finishes a multiple-part encryption operation. */
946 CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
947 CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
949 SFTKSession *session;
950 SFTKSessionContext *context;
951 unsigned int outlen,i;
952 unsigned int maxout = *pulLastEncryptedPartLen;
954 SECStatus rv = SECSuccess;
955 PRBool contextFinished = PR_TRUE;
959 /* make sure we're legal */
960 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,&session);
961 if (crv != CKR_OK) return crv;
963 *pulLastEncryptedPartLen = 0;
964 if (!pLastEncryptedPart) {
965 /* caller is checking the amount of remaining data */
966 if (context->blockSize > 0 && context->doPad) {
967 *pulLastEncryptedPartLen = context->blockSize;
968 contextFinished = PR_FALSE; /* still have padding to go */
974 if (context->doPad) {
975 unsigned char padbyte = (unsigned char)
976 (context->blockSize - context->padDataLength);
977 /* fill out rest of pad buffer with pad magic*/
978 for (i=context->padDataLength; i < context->blockSize; i++) {
979 context->padBuf[i] = padbyte;
981 rv = (*context->update)(context->cipherInfo,pLastEncryptedPart,
982 &outlen, maxout, context->padBuf, context->blockSize);
983 if (rv == SECSuccess) *pulLastEncryptedPartLen = (CK_ULONG) outlen;
988 sftk_TerminateOp( session, SFTK_ENCRYPT, context );
989 sftk_FreeSession(session);
990 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
993 /* NSC_Encrypt encrypts single-part data. */
994 CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
995 CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
996 CK_ULONG_PTR pulEncryptedDataLen)
998 SFTKSession *session;
999 SFTKSessionContext *context;
1000 unsigned int outlen;
1001 unsigned int maxoutlen = *pulEncryptedDataLen;
1004 SECStatus rv = SECSuccess;
1007 pText.type = siBuffer;
1009 pText.len = ulDataLen;
1013 /* make sure we're legal */
1014 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,&session);
1015 if (crv != CKR_OK) return crv;
1017 if (!pEncryptedData) {
1018 *pulEncryptedDataLen = context->multi ?
1019 ulDataLen + 2 * context->blockSize : context->maxLen;
1023 if (context->doPad) {
1024 if (context->multi) {
1026 /* padding is fairly complicated, have the update and final
1027 * code deal with it */
1028 sftk_FreeSession(session);
1029 crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData,
1030 pulEncryptedDataLen);
1032 *pulEncryptedDataLen = 0;
1033 maxoutlen -= *pulEncryptedDataLen;
1034 pEncryptedData += *pulEncryptedDataLen;
1035 finalLen = maxoutlen;
1036 crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
1038 *pulEncryptedDataLen += finalLen;
1039 return crv == CKR_OK ? crv2 : crv;
1041 /* doPad without multi means that padding must be done on the first
1042 ** and only update. There will be no final.
1044 PORT_Assert(context->blockSize > 1);
1045 if (context->blockSize > 1) {
1046 CK_ULONG remainder = ulDataLen % context->blockSize;
1047 CK_ULONG padding = context->blockSize - remainder;
1048 pText.len += padding;
1049 pText.data = PORT_ZAlloc(pText.len);
1051 memcpy(pText.data, pData, ulDataLen);
1052 memset(pText.data + ulDataLen, padding, padding);
1054 crv = CKR_HOST_MEMORY;
1060 /* do it: NOTE: this assumes buf size is big enough. */
1061 rv = (*context->update)(context->cipherInfo, pEncryptedData,
1062 &outlen, maxoutlen, pText.data, pText.len);
1063 crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1064 *pulEncryptedDataLen = (CK_ULONG) outlen;
1065 if (pText.data != pData)
1066 PORT_ZFree(pText.data, pText.len);
1068 sftk_TerminateOp( session, SFTK_ENCRYPT, context );
1070 sftk_FreeSession(session);
1077 ************** Crypto Functions: Decrypt ************************
1080 /* NSC_DecryptInit initializes a decryption operation. */
1081 CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession,
1082 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1085 return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT,
1086 SFTK_DECRYPT, PR_FALSE);
1089 /* NSC_DecryptUpdate continues a multiple-part decryption operation. */
1090 CK_RV NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
1091 CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
1092 CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
1094 SFTKSessionContext *context;
1095 unsigned int padoutlen = 0;
1096 unsigned int outlen;
1097 unsigned int maxout = *pulPartLen;
1103 /* make sure we're legal */
1104 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,NULL);
1105 if (crv != CKR_OK) return crv;
1107 /* this can only happen on an NSS programming error */
1108 PORT_Assert((context->padDataLength == 0)
1109 || context->padDataLength == context->blockSize);
1113 if (context->doPad) {
1114 /* we can check the data length here because if we are padding,
1115 * then we must be using a block cipher. In the non-padding case
1116 * the error will be returned by the underlying decryption
1117 * function when do do the actual decrypt. We need to do the
1118 * check here to avoid returning a negative length to the caller.
1120 if ((ulEncryptedPartLen == 0) ||
1121 (ulEncryptedPartLen % context->blockSize) != 0) {
1122 return CKR_ENCRYPTED_DATA_LEN_RANGE;
1125 ulEncryptedPartLen + context->padDataLength - context->blockSize;
1128 /* for stream ciphers there is are no constraints on ulEncryptedPartLen.
1129 * for block ciphers, it must be a multiple of blockSize. The error is
1130 * detected when this function is called again do decrypt the output.
1132 *pulPartLen = ulEncryptedPartLen;
1136 if (context->doPad) {
1137 /* first decrypt our saved buffer */
1138 if (context->padDataLength != 0) {
1139 rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
1140 maxout, context->padBuf, context->blockSize);
1141 if (rv != SECSuccess) return sftk_MapDecryptError(PORT_GetError());
1143 maxout -= padoutlen;
1145 /* now save the final block for the next decrypt or the final */
1146 PORT_Memcpy(context->padBuf,&pEncryptedPart[ulEncryptedPartLen -
1147 context->blockSize], context->blockSize);
1148 context->padDataLength = context->blockSize;
1149 ulEncryptedPartLen -= context->padDataLength;
1152 /* do it: NOTE: this assumes buf size in is >= buf size out! */
1153 rv = (*context->update)(context->cipherInfo,pPart, &outlen,
1154 maxout, pEncryptedPart, ulEncryptedPartLen);
1155 *pulPartLen = (CK_ULONG) (outlen + padoutlen);
1156 return (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
1160 /* NSC_DecryptFinal finishes a multiple-part decryption operation. */
1161 CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
1162 CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
1164 SFTKSession *session;
1165 SFTKSessionContext *context;
1166 unsigned int outlen;
1167 unsigned int maxout = *pulLastPartLen;
1169 SECStatus rv = SECSuccess;
1173 /* make sure we're legal */
1174 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,&session);
1175 if (crv != CKR_OK) return crv;
1177 *pulLastPartLen = 0;
1179 /* caller is checking the amount of remaining data */
1180 if (context->padDataLength > 0) {
1181 *pulLastPartLen = context->padDataLength;
1187 if (context->doPad) {
1188 /* decrypt our saved buffer */
1189 if (context->padDataLength != 0) {
1190 /* this assumes that pLastPart is big enough to hold the *whole*
1192 rv = (*context->update)(context->cipherInfo, pLastPart, &outlen,
1193 maxout, context->padBuf, context->blockSize);
1194 if (rv == SECSuccess) {
1195 unsigned int padSize =
1196 (unsigned int) pLastPart[context->blockSize-1];
1197 if ((padSize > context->blockSize) || (padSize == 0)) {
1200 *pulLastPartLen = outlen - padSize;
1206 sftk_TerminateOp( session, SFTK_DECRYPT, context );
1208 sftk_FreeSession(session);
1209 return (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
1212 /* NSC_Decrypt decrypts encrypted data in a single part. */
1213 CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession,
1214 CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,
1215 CK_ULONG_PTR pulDataLen)
1217 SFTKSession *session;
1218 SFTKSessionContext *context;
1219 unsigned int outlen;
1220 unsigned int maxoutlen = *pulDataLen;
1223 SECStatus rv = SECSuccess;
1227 /* make sure we're legal */
1228 crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_FALSE,&session);
1229 if (crv != CKR_OK) return crv;
1232 *pulDataLen = ulEncryptedDataLen + context->blockSize;
1236 if (context->doPad && context->multi) {
1238 /* padding is fairly complicated, have the update and final
1239 * code deal with it */
1240 sftk_FreeSession(session);
1241 crv = NSC_DecryptUpdate(hSession,pEncryptedData,ulEncryptedDataLen,
1245 maxoutlen -= *pulDataLen;
1246 pData += *pulDataLen;
1247 finalLen = maxoutlen;
1248 crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
1250 *pulDataLen += finalLen;
1251 return crv == CKR_OK ? crv2 : crv;
1254 rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
1255 pEncryptedData, ulEncryptedDataLen);
1256 /* XXX need to do MUCH better error mapping than this. */
1257 crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
1258 if (rv == SECSuccess && context->doPad) {
1259 CK_ULONG padding = pData[outlen - 1];
1260 if (padding > context->blockSize || !padding) {
1261 crv = CKR_ENCRYPTED_DATA_INVALID;
1265 *pulDataLen = (CK_ULONG) outlen;
1266 sftk_TerminateOp( session, SFTK_DECRYPT, context );
1268 sftk_FreeSession(session);
1275 ************** Crypto Functions: Digest (HASH) ************************
1278 /* NSC_DigestInit initializes a message-digesting operation. */
1279 CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession,
1280 CK_MECHANISM_PTR pMechanism)
1282 SFTKSession *session;
1283 SFTKSessionContext *context;
1288 session = sftk_SessionFromHandle(hSession);
1289 if (session == NULL)
1290 return CKR_SESSION_HANDLE_INVALID;
1291 crv = sftk_InitGeneric(session,&context,SFTK_HASH,NULL,0,NULL, 0, 0);
1292 if (crv != CKR_OK) {
1293 sftk_FreeSession(session);
1298 #define INIT_MECH(mech,mmm) \
1300 mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \
1301 context->cipherInfo = (void *)mmm ## _ctx; \
1302 context->cipherInfoLen = mmm ## _FlattenSize(mmm ## _ctx); \
1303 context->currentMech = mech; \
1304 context->hashUpdate = (SFTKHash) mmm ## _Update; \
1305 context->end = (SFTKEnd) mmm ## _End; \
1306 context->destroy = (SFTKDestroy) mmm ## _DestroyContext; \
1307 context->maxLen = mmm ## _LENGTH; \
1309 mmm ## _Begin(mmm ## _ctx); \
1311 crv = CKR_HOST_MEMORY; \
1315 switch(pMechanism->mechanism) {
1316 INIT_MECH(CKM_MD2, MD2)
1317 INIT_MECH(CKM_MD5, MD5)
1318 INIT_MECH(CKM_SHA_1, SHA1)
1319 INIT_MECH(CKM_SHA224, SHA224)
1320 INIT_MECH(CKM_SHA256, SHA256)
1321 INIT_MECH(CKM_SHA384, SHA384)
1322 INIT_MECH(CKM_SHA512, SHA512)
1325 crv = CKR_MECHANISM_INVALID;
1329 if (crv != CKR_OK) {
1330 sftk_FreeContext(context);
1331 sftk_FreeSession(session);
1334 sftk_SetContextByType(session, SFTK_HASH, context);
1335 sftk_FreeSession(session);
1340 /* NSC_Digest digests data in a single part. */
1341 CK_RV NSC_Digest(CK_SESSION_HANDLE hSession,
1342 CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
1343 CK_ULONG_PTR pulDigestLen)
1345 SFTKSession *session;
1346 SFTKSessionContext *context;
1347 unsigned int digestLen;
1348 unsigned int maxout = *pulDigestLen;
1353 /* make sure we're legal */
1354 crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_FALSE,&session);
1355 if (crv != CKR_OK) return crv;
1357 if (pDigest == NULL) {
1358 *pulDigestLen = context->maxLen;
1363 (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
1364 /* NOTE: this assumes buf size is bigenough for the algorithm */
1365 (*context->end)(context->cipherInfo, pDigest, &digestLen,maxout);
1366 *pulDigestLen = digestLen;
1368 sftk_TerminateOp( session, SFTK_HASH, context );
1370 sftk_FreeSession(session);
1375 /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
1376 CK_RV NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
1379 SFTKSessionContext *context;
1384 /* make sure we're legal */
1385 crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_TRUE,NULL);
1386 if (crv != CKR_OK) return crv;
1388 (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);
1393 /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
1394 CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,
1395 CK_ULONG_PTR pulDigestLen)
1397 SFTKSession *session;
1398 SFTKSessionContext *context;
1399 unsigned int maxout = *pulDigestLen;
1400 unsigned int digestLen;
1405 /* make sure we're legal */
1406 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
1407 if (crv != CKR_OK) return crv;
1409 if (pDigest != NULL) {
1410 (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
1411 *pulDigestLen = digestLen;
1412 sftk_TerminateOp( session, SFTK_HASH, context );
1414 *pulDigestLen = context->maxLen;
1417 sftk_FreeSession(session);
1422 * these helper functions are used by Generic Macing and Signing functions
1423 * that use hashes as part of their operations.
1425 #define DOSUB(mmm) \
1427 sftk_doSub ## mmm(SFTKSessionContext *context) { \
1428 mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \
1429 context->hashInfo = (void *) mmm ## _ctx; \
1430 context->hashUpdate = (SFTKHash) mmm ## _Update; \
1431 context->end = (SFTKEnd) mmm ## _End; \
1432 context->hashdestroy = (SFTKDestroy) mmm ## _DestroyContext; \
1433 if (!context->hashInfo) { \
1434 return CKR_HOST_MEMORY; \
1436 mmm ## _Begin( mmm ## _ctx ); \
1449 * HMAC General copies only a portion of the result. This update routine likes
1450 * the final HMAC output with the signature.
1453 sftk_HMACCopy(CK_ULONG *copyLen,unsigned char *sig,unsigned int *sigLen,
1454 unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
1456 if (maxLen < *copyLen) return SECFailure;
1457 PORT_Memcpy(sig,hash,*copyLen);
1462 /* Verify is just a compare for HMAC */
1464 sftk_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen,
1465 unsigned char *hash, unsigned int hashLen)
1467 return (PORT_Memcmp(sig,hash,*copyLen) == 0) ? SECSuccess : SECFailure ;
1471 * common HMAC initalization routine
1474 sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash,
1475 SFTKObject *key, CK_ULONG mac_size)
1477 SFTKAttribute *keyval;
1478 HMACContext *HMACcontext;
1479 CK_ULONG *intpointer;
1480 const SECHashObject *hashObj = HASH_GetRawHashObject(hash);
1481 PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID);
1483 /* required by FIPS 198 Section 4 */
1484 if (isFIPS && (mac_size < 4 || mac_size < hashObj->length/2)) {
1485 return CKR_BUFFER_TOO_SMALL;
1488 keyval = sftk_FindAttribute(key,CKA_VALUE);
1489 if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
1491 HMACcontext = HMAC_Create(hashObj,
1492 (const unsigned char*)keyval->attrib.pValue,
1493 keyval->attrib.ulValueLen, isFIPS);
1494 context->hashInfo = HMACcontext;
1495 context->multi = PR_TRUE;
1496 sftk_FreeAttribute(keyval);
1497 if (context->hashInfo == NULL) {
1498 if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) {
1499 return CKR_KEY_SIZE_RANGE;
1501 return CKR_HOST_MEMORY;
1503 context->hashUpdate = (SFTKHash) HMAC_Update;
1504 context->end = (SFTKEnd) HMAC_Finish;
1506 context->hashdestroy = (SFTKDestroy) HMAC_Destroy;
1507 intpointer = (CK_ULONG *) PORT_Alloc(sizeof(CK_ULONG));
1508 if (intpointer == NULL) {
1509 return CKR_HOST_MEMORY;
1511 *intpointer = mac_size;
1512 context->cipherInfo = (void *) intpointer;
1513 context->destroy = (SFTKDestroy) sftk_Space;
1514 context->update = (SFTKCipher) sftk_HMACCopy;
1515 context->verify = (SFTKVerify) sftk_HMACCmp;
1516 context->maxLen = hashObj->length;
1517 HMAC_Begin(HMACcontext);
1522 * SSL Macing support. SSL Macs are inited, then update with the base
1523 * hashing algorithm, then finalized in sign and verify
1528 * 60 bytes is 3 times the maximum length MAC size that is supported.
1529 * We probably should have one copy of this table. We still need this table
1530 * in ssl to 'sign' the handshake hashes.
1532 static unsigned char ssl_pad_1 [60] = {
1533 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1534 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1535 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1536 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1537 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1538 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1539 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
1540 0x36, 0x36, 0x36, 0x36
1542 static unsigned char ssl_pad_2 [60] = {
1543 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1544 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1545 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1546 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1547 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1548 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1549 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
1550 0x5c, 0x5c, 0x5c, 0x5c
1554 sftk_SSLMACSign(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int *sigLen,
1555 unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
1557 unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
1560 info->begin(info->hashContext);
1561 info->update(info->hashContext,info->key,info->keySize);
1562 info->update(info->hashContext,ssl_pad_2,info->padSize);
1563 info->update(info->hashContext,hash,hashLen);
1564 info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH);
1565 PORT_Memcpy(sig,tmpBuf,info->macSize);
1566 *sigLen = info->macSize;
1571 sftk_SSLMACVerify(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int sigLen,
1572 unsigned char *hash, unsigned int hashLen)
1574 unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
1577 info->begin(info->hashContext);
1578 info->update(info->hashContext,info->key,info->keySize);
1579 info->update(info->hashContext,ssl_pad_2,info->padSize);
1580 info->update(info->hashContext,hash,hashLen);
1581 info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH);
1582 return (PORT_Memcmp(sig,tmpBuf,info->macSize) == 0) ?
1583 SECSuccess : SECFailure;
1587 * common HMAC initalization routine
1590 sftk_doSSLMACInit(SFTKSessionContext *context,SECOidTag oid,
1591 SFTKObject *key, CK_ULONG mac_size)
1593 SFTKAttribute *keyval;
1596 SFTKSSLMACInfo *sslmacinfo;
1597 CK_RV crv = CKR_MECHANISM_INVALID;
1599 if (oid == SEC_OID_SHA1) {
1600 crv = sftk_doSubSHA1(context);
1601 if (crv != CKR_OK) return crv;
1602 begin = (SFTKBegin) SHA1_Begin;
1605 crv = sftk_doSubMD5(context);
1606 if (crv != CKR_OK) return crv;
1607 begin = (SFTKBegin) MD5_Begin;
1610 context->multi = PR_TRUE;
1612 keyval = sftk_FindAttribute(key,CKA_VALUE);
1613 if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
1615 context->hashUpdate(context->hashInfo,keyval->attrib.pValue,
1616 keyval->attrib.ulValueLen);
1617 context->hashUpdate(context->hashInfo,ssl_pad_1,padSize);
1618 sslmacinfo = (SFTKSSLMACInfo *) PORT_Alloc(sizeof(SFTKSSLMACInfo));
1619 if (sslmacinfo == NULL) {
1620 sftk_FreeAttribute(keyval);
1621 return CKR_HOST_MEMORY;
1623 sslmacinfo->macSize = mac_size;
1624 sslmacinfo->hashContext = context->hashInfo;
1625 PORT_Memcpy(sslmacinfo->key,keyval->attrib.pValue,
1626 keyval->attrib.ulValueLen);
1627 sslmacinfo->keySize = keyval->attrib.ulValueLen;
1628 sslmacinfo->begin = begin;
1629 sslmacinfo->end = context->end;
1630 sslmacinfo->update = context->hashUpdate;
1631 sslmacinfo->padSize = padSize;
1632 sftk_FreeAttribute(keyval);
1633 context->cipherInfo = (void *) sslmacinfo;
1634 context->destroy = (SFTKDestroy) sftk_Space;
1635 context->update = (SFTKCipher) sftk_SSLMACSign;
1636 context->verify = (SFTKVerify) sftk_SSLMACVerify;
1637 context->maxLen = mac_size;
1642 ************** Crypto Functions: Sign ************************
1646 * Check if We're using CBCMacing and initialize the session context if we are.
1647 * @param contextType SFTK_SIGN or SFTK_VERIFY
1648 * @param keyUsage check whether key allows this usage
1651 sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
1652 CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,
1653 SFTKContextType contextType)
1656 CK_MECHANISM cbc_mechanism;
1657 CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
1658 CK_RC2_CBC_PARAMS rc2_params;
1659 #if NSS_SOFTOKEN_DOES_RC5
1660 CK_RC5_CBC_PARAMS rc5_params;
1661 CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
1663 unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
1664 SFTKSessionContext *context;
1666 unsigned int blockSize;
1668 switch (pMechanism->mechanism) {
1669 case CKM_RC2_MAC_GENERAL:
1671 ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
1674 /* this works because ulEffectiveBits is in the same place in both the
1675 * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */
1676 rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *)
1677 pMechanism->pParameter)->ulEffectiveBits;
1678 PORT_Memset(rc2_params.iv,0,sizeof(rc2_params.iv));
1679 cbc_mechanism.mechanism = CKM_RC2_CBC;
1680 cbc_mechanism.pParameter = &rc2_params;
1681 cbc_mechanism.ulParameterLen = sizeof(rc2_params);
1684 #if NSS_SOFTOKEN_DOES_RC5
1685 case CKM_RC5_MAC_GENERAL:
1687 ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
1690 /* this works because ulEffectiveBits is in the same place in both the
1691 * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
1692 rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
1693 rc5_params.ulWordsize = rc5_mac->ulWordsize;
1694 rc5_params.ulRounds = rc5_mac->ulRounds;
1695 rc5_params.pIv = ivBlock;
1696 if( (blockSize = rc5_mac->ulWordsize*2) > SFTK_MAX_BLOCK_SIZE )
1697 return CKR_MECHANISM_PARAM_INVALID;
1698 rc5_params.ulIvLen = blockSize;
1699 PORT_Memset(ivBlock,0,blockSize);
1700 cbc_mechanism.mechanism = CKM_RC5_CBC;
1701 cbc_mechanism.pParameter = &rc5_params;
1702 cbc_mechanism.ulParameterLen = sizeof(rc5_params);
1705 /* add cast and idea later */
1706 case CKM_DES_MAC_GENERAL:
1707 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1711 PORT_Memset(ivBlock,0,blockSize);
1712 cbc_mechanism.mechanism = CKM_DES_CBC;
1713 cbc_mechanism.pParameter = &ivBlock;
1714 cbc_mechanism.ulParameterLen = blockSize;
1716 case CKM_DES3_MAC_GENERAL:
1717 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1721 PORT_Memset(ivBlock,0,blockSize);
1722 cbc_mechanism.mechanism = CKM_DES3_CBC;
1723 cbc_mechanism.pParameter = &ivBlock;
1724 cbc_mechanism.ulParameterLen = blockSize;
1726 case CKM_CDMF_MAC_GENERAL:
1727 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1731 PORT_Memset(ivBlock,0,blockSize);
1732 cbc_mechanism.mechanism = CKM_CDMF_CBC;
1733 cbc_mechanism.pParameter = &ivBlock;
1734 cbc_mechanism.ulParameterLen = blockSize;
1736 case CKM_SEED_MAC_GENERAL:
1737 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1741 PORT_Memset(ivBlock,0,blockSize);
1742 cbc_mechanism.mechanism = CKM_SEED_CBC;
1743 cbc_mechanism.pParameter = &ivBlock;
1744 cbc_mechanism.ulParameterLen = blockSize;
1746 case CKM_CAMELLIA_MAC_GENERAL:
1747 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1749 case CKM_CAMELLIA_MAC:
1751 PORT_Memset(ivBlock,0,blockSize);
1752 cbc_mechanism.mechanism = CKM_CAMELLIA_CBC;
1753 cbc_mechanism.pParameter = &ivBlock;
1754 cbc_mechanism.ulParameterLen = blockSize;
1756 case CKM_AES_MAC_GENERAL:
1757 mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
1761 PORT_Memset(ivBlock,0,blockSize);
1762 cbc_mechanism.mechanism = CKM_AES_CBC;
1763 cbc_mechanism.pParameter = &ivBlock;
1764 cbc_mechanism.ulParameterLen = blockSize;
1767 return CKR_FUNCTION_NOT_SUPPORTED;
1770 /* if MAC size is externally supplied, it should be checked.
1772 if (mac_bytes == SFTK_INVALID_MAC_SIZE)
1773 mac_bytes = blockSize >> 1;
1775 if( mac_bytes > blockSize )
1776 return CKR_MECHANISM_PARAM_INVALID;
1779 crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
1780 CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
1781 keyUsage, contextType, PR_TRUE );
1782 if (crv != CKR_OK) return crv;
1783 crv = sftk_GetContext(hSession,&context,contextType,PR_TRUE,NULL);
1785 /* this shouldn't happen! */
1786 PORT_Assert(crv == CKR_OK);
1787 if (crv != CKR_OK) return crv;
1788 context->blockSize = blockSize;
1789 context->macSize = mac_bytes;
1794 * encode RSA PKCS #1 Signature data before signing...
1797 sftk_HashSign(SFTKHashSignInfo *info,unsigned char *sig,unsigned int *sigLen,
1798 unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
1800 return RSA_HashSign(info->hashOid,info->key,sig,sigLen,maxLen,
1804 /* XXX Old template; want to expunge it eventually. */
1805 static DERTemplate SECAlgorithmIDTemplate[] = {
1807 0, NULL, sizeof(SECAlgorithmID) },
1809 offsetof(SECAlgorithmID,algorithm), },
1810 { DER_OPTIONAL | DER_ANY,
1811 offsetof(SECAlgorithmID,parameters), },
1816 * XXX OLD Template. Once all uses have been switched over to new one,
1819 static DERTemplate SGNDigestInfoTemplate[] = {
1821 0, NULL, sizeof(SGNDigestInfo) },
1823 offsetof(SGNDigestInfo,digestAlgorithm),
1824 SECAlgorithmIDTemplate, },
1826 offsetof(SGNDigestInfo,digest), },
1831 RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
1832 unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
1833 unsigned char *hash, unsigned int hashLen)
1836 SECStatus rv = SECFailure;
1838 PLArenaPool *arena = NULL;
1839 SGNDigestInfo *di = NULL;
1843 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1844 if ( !arena ) { goto loser; }
1846 /* Construct digest info */
1847 di = SGN_CreateDigestInfo(hashOid, hash, hashLen);
1848 if (!di) { goto loser; }
1850 /* Der encode the digest as a DigestInfo */
1851 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
1852 if (rv != SECSuccess) {
1857 ** Encrypt signature after constructing appropriate PKCS#1 signature
1860 rv = RSA_Sign(key,sig,sigLen,maxLen,digder.data,digder.len);
1863 SGN_DestroyDigestInfo(di);
1864 if (arena != NULL) {
1865 PORT_FreeArena(arena, PR_FALSE);
1871 sftk_SignPSS(SFTKHashSignInfo *info,unsigned char *sig,unsigned int *sigLen,
1872 unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
1874 return RSA_SignPSS(info->params,info->key,sig,sigLen,maxLen,
1879 nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen,
1880 void *dataBuf, unsigned int dataLen)
1882 SECItem signature, digest;
1883 NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
1885 signature.data = (unsigned char *)sigBuf;
1886 signature.len = sigLen;
1887 digest.data = (unsigned char *)dataBuf;
1888 digest.len = dataLen;
1889 return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest);
1893 nsc_DSA_Sign_Stub(void *ctx, void *sigBuf,
1894 unsigned int *sigLen, unsigned int maxSigLen,
1895 void *dataBuf, unsigned int dataLen)
1897 SECItem signature, digest;
1899 NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
1901 signature.data = (unsigned char *)sigBuf;
1902 signature.len = maxSigLen;
1903 digest.data = (unsigned char *)dataBuf;
1904 digest.len = dataLen;
1905 rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest);
1906 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
1907 sftk_fatalError = PR_TRUE;
1909 *sigLen = signature.len;
1913 #ifdef NSS_ENABLE_ECC
1915 nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen,
1916 void *dataBuf, unsigned int dataLen)
1918 SECItem signature, digest;
1919 NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
1921 signature.data = (unsigned char *)sigBuf;
1922 signature.len = sigLen;
1923 digest.data = (unsigned char *)dataBuf;
1924 digest.len = dataLen;
1925 return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest);
1929 nsc_ECDSASignStub(void *ctx, void *sigBuf,
1930 unsigned int *sigLen, unsigned int maxSigLen,
1931 void *dataBuf, unsigned int dataLen)
1933 SECItem signature, digest;
1935 NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
1937 signature.data = (unsigned char *)sigBuf;
1938 signature.len = maxSigLen;
1939 digest.data = (unsigned char *)dataBuf;
1940 digest.len = dataLen;
1941 rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest);
1942 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
1943 sftk_fatalError = PR_TRUE;
1945 *sigLen = signature.len;
1948 #endif /* NSS_ENABLE_ECC */
1950 /* NSC_SignInit setups up the signing operations. There are three basic
1952 * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
1953 * to data in a single Sign operation (which often looks a lot like an
1954 * encrypt, with data coming in and data going out).
1955 * (2) Hash based signing, where we continually hash the data, then apply
1956 * some sort of signature to the end.
1957 * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key,
1958 * and only the final block is part of the mac.
1960 * For case number 3, we initialize a context much like the Encryption Context
1961 * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and
1962 * C_Final by the following method... if it's not multi-part, and it's doesn't
1963 * have a hash context, it must be a block Encryption CBC MAC.
1965 * For case number 2, we initialize a hash structure, as well as make it
1966 * multi-part. Updates are simple calls to the hash update function. Final
1967 * calls the hashend, then passes the result to the 'update' function (which
1968 * operates as a final signature function). In some hash based MAC'ing (as
1969 * opposed to hash base signatures), the update function is can be simply a
1970 * copy (as is the case with HMAC).
1972 CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession,
1973 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1975 SFTKSession *session;
1977 SFTKSessionContext *context;
1978 CK_KEY_TYPE key_type;
1980 NSSLOWKEYPrivateKey *privKey;
1981 SFTKHashSignInfo *info = NULL;
1985 /* Block Cipher MACing Algorithms use a different Context init method..*/
1986 crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN);
1987 if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv;
1989 /* we're not using a block cipher mac */
1990 session = sftk_SessionFromHandle(hSession);
1991 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1992 crv = sftk_InitGeneric(session,&context,SFTK_SIGN,&key,hKey,&key_type,
1993 CKO_PRIVATE_KEY,CKA_SIGN);
1994 if (crv != CKR_OK) {
1995 sftk_FreeSession(session);
1999 context->multi = PR_FALSE;
2001 #define INIT_RSA_SIGN_MECH(mmm) \
2002 case CKM_ ## mmm ## _RSA_PKCS: \
2003 context->multi = PR_TRUE; \
2004 crv = sftk_doSub ## mmm (context); \
2005 if (crv != CKR_OK) break; \
2006 context->update = (SFTKCipher) sftk_HashSign; \
2007 info = PORT_New(SFTKHashSignInfo); \
2008 if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \
2009 info->hashOid = SEC_OID_ ## mmm ; \
2012 switch(pMechanism->mechanism) {
2013 INIT_RSA_SIGN_MECH(MD5)
2014 INIT_RSA_SIGN_MECH(MD2)
2015 INIT_RSA_SIGN_MECH(SHA1)
2016 INIT_RSA_SIGN_MECH(SHA224)
2017 INIT_RSA_SIGN_MECH(SHA256)
2018 INIT_RSA_SIGN_MECH(SHA384)
2019 INIT_RSA_SIGN_MECH(SHA512)
2022 context->update = (SFTKCipher) RSA_Sign;
2025 context->update = (SFTKCipher) RSA_SignRaw;
2027 if (key_type != CKK_RSA) {
2028 crv = CKR_KEY_TYPE_INCONSISTENT;
2031 privKey = sftk_GetPrivKey(key,CKK_RSA,&crv);
2032 if (privKey == NULL) {
2033 crv = CKR_KEY_TYPE_INCONSISTENT;
2036 /* OK, info is allocated only if we're doing hash and sign mechanism.
2037 * It's necessary to be able to set the correct OID in the final
2041 info->key = privKey;
2042 context->cipherInfo = info;
2043 context->destroy = (SFTKDestroy)sftk_Space;
2045 context->cipherInfo = privKey;
2046 context->destroy = (SFTKDestroy)sftk_Null;
2048 context->maxLen = nsslowkey_PrivateModulusLen(privKey);
2050 case CKM_RSA_PKCS_PSS:
2051 if (key_type != CKK_RSA) {
2052 crv = CKR_KEY_TYPE_INCONSISTENT;
2055 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) {
2056 crv = CKR_MECHANISM_PARAM_INVALID;
2059 info = PORT_New(SFTKHashSignInfo);
2061 crv = CKR_HOST_MEMORY;
2064 info->params = pMechanism->pParameter;
2065 info->key = sftk_GetPrivKey(key,CKK_RSA,&crv);
2066 if (info->key == NULL) {
2070 context->cipherInfo = info;
2071 context->destroy = (SFTKDestroy) sftk_Space;
2072 context->update = (SFTKCipher) sftk_SignPSS;
2073 context->maxLen = nsslowkey_PrivateModulusLen(info->key);
2077 context->multi = PR_TRUE;
2078 crv = sftk_doSubSHA1(context);
2079 if (crv != CKR_OK) break;
2082 if (key_type != CKK_DSA) {
2083 crv = CKR_KEY_TYPE_INCONSISTENT;
2086 privKey = sftk_GetPrivKey(key,CKK_DSA,&crv);
2087 if (privKey == NULL) {
2090 context->cipherInfo = privKey;
2091 context->update = (SFTKCipher) nsc_DSA_Sign_Stub;
2092 context->destroy = (privKey == key->objectInfo) ?
2093 (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey;
2094 context->maxLen = DSA_SIGNATURE_LEN;
2098 #ifdef NSS_ENABLE_ECC
2099 case CKM_ECDSA_SHA1:
2100 context->multi = PR_TRUE;
2101 crv = sftk_doSubSHA1(context);
2102 if (crv != CKR_OK) break;
2105 if (key_type != CKK_EC) {
2106 crv = CKR_KEY_TYPE_INCONSISTENT;
2109 privKey = sftk_GetPrivKey(key,CKK_EC,&crv);
2110 if (privKey == NULL) {
2111 crv = CKR_HOST_MEMORY;
2114 context->cipherInfo = privKey;
2115 context->update = (SFTKCipher) nsc_ECDSASignStub;
2116 context->destroy = (privKey == key->objectInfo) ?
2117 (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey;
2118 context->maxLen = MAX_ECKEY_LEN * 2;
2121 #endif /* NSS_ENABLE_ECC */
2123 #define INIT_HMAC_MECH(mmm) \
2124 case CKM_ ## mmm ## _HMAC_GENERAL: \
2125 crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, \
2126 *(CK_ULONG *)pMechanism->pParameter); \
2128 case CKM_ ## mmm ## _HMAC: \
2129 crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, mmm ## _LENGTH); \
2134 INIT_HMAC_MECH(SHA224)
2135 INIT_HMAC_MECH(SHA256)
2136 INIT_HMAC_MECH(SHA384)
2137 INIT_HMAC_MECH(SHA512)
2139 case CKM_SHA_1_HMAC_GENERAL:
2140 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,
2141 *(CK_ULONG *)pMechanism->pParameter);
2143 case CKM_SHA_1_HMAC:
2144 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH);
2147 case CKM_SSL3_MD5_MAC:
2148 crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key,
2149 *(CK_ULONG *)pMechanism->pParameter);
2151 case CKM_SSL3_SHA1_MAC:
2152 crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key,
2153 *(CK_ULONG *)pMechanism->pParameter);
2155 case CKM_TLS_PRF_GENERAL:
2156 crv = sftk_TLSPRFInit(context, key, key_type);
2159 crv = CKR_MECHANISM_INVALID;
2163 if (crv != CKR_OK) {
2164 if (info) PORT_Free(info);
2165 sftk_FreeContext(context);
2166 sftk_FreeSession(session);
2169 sftk_SetContextByType(session, SFTK_SIGN, context);
2170 sftk_FreeSession(session);
2174 /** MAC one block of data by block cipher
2177 sftk_MACBlock( SFTKSessionContext *ctx, void *blk )
2179 unsigned int outlen;
2180 return ( SECSuccess == (ctx->update)( ctx->cipherInfo, ctx->macBuf, &outlen,
2181 SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize ))
2182 ? CKR_OK : sftk_MapCryptError(PORT_GetError());
2185 /** MAC last (incomplete) block of data by block cipher
2187 * Call once, then terminate MACing operation.
2190 sftk_MACFinal( SFTKSessionContext *ctx )
2192 unsigned int padLen = ctx->padDataLength;
2193 /* pad and proceed the residual */
2195 /* shd clr ctx->padLen to make sftk_MACFinal idempotent */
2196 PORT_Memset( ctx->padBuf + padLen, 0, ctx->blockSize - padLen );
2197 return sftk_MACBlock( ctx, ctx->padBuf );
2202 /** The common implementation for {Sign,Verify}Update. (S/V only vary in their
2203 * setup and final operations).
2205 * A call which results in an error terminates the operation [PKCS#11,v2.11]
2208 sftk_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
2209 CK_ULONG ulPartLen,SFTKContextType type)
2211 SFTKSession *session;
2212 SFTKSessionContext *context;
2215 /* make sure we're legal */
2216 crv = sftk_GetContext(hSession,&context,type, PR_TRUE, &session );
2217 if (crv != CKR_OK) return crv;
2219 if (context->hashInfo) {
2220 (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen);
2222 /* must be block cipher MACing */
2224 unsigned int blkSize = context->blockSize;
2225 unsigned char *residual = /* free room in context->padBuf */
2226 context->padBuf + context->padDataLength;
2227 unsigned int minInput = /* min input for MACing at least one block */
2228 blkSize - context->padDataLength;
2230 /* not enough data even for one block */
2231 if( ulPartLen < minInput ) {
2232 PORT_Memcpy( residual, pPart, ulPartLen );
2233 context->padDataLength += ulPartLen;
2236 /* MACing residual */
2237 if( context->padDataLength ) {
2238 PORT_Memcpy( residual, pPart, minInput );
2239 ulPartLen -= minInput;
2241 if( CKR_OK != (crv = sftk_MACBlock( context, context->padBuf )) )
2244 /* MACing full blocks */
2245 while( ulPartLen >= blkSize )
2247 if( CKR_OK != (crv = sftk_MACBlock( context, pPart )) )
2249 ulPartLen -= blkSize;
2252 /* save the residual */
2253 if( (context->padDataLength = ulPartLen) )
2254 PORT_Memcpy( context->padBuf, pPart, ulPartLen );
2255 } /* blk cipher MACing */
2260 sftk_TerminateOp( session, type, context );
2262 sftk_FreeSession(session);
2266 /* NSC_SignUpdate continues a multiple-part signature operation,
2267 * where the signature is (will be) an appendix to the data,
2268 * and plaintext cannot be recovered from the signature
2270 * A call which results in an error terminates the operation [PKCS#11,v2.11]
2272 CK_RV NSC_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
2276 return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN);
2280 /* NSC_SignFinal finishes a multiple-part signature operation,
2281 * returning the signature. */
2282 CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,
2283 CK_ULONG_PTR pulSignatureLen)
2285 SFTKSession *session;
2286 SFTKSessionContext *context;
2287 unsigned int outlen;
2288 unsigned int maxoutlen = *pulSignatureLen;
2293 /* make sure we're legal */
2294 crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_TRUE,&session);
2295 if (crv != CKR_OK) return crv;
2297 if (context->hashInfo) {
2298 unsigned int digestLen;
2299 unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
2302 outlen = context->maxLen; goto finish;
2304 (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
2305 if( SECSuccess != (context->update)(context->cipherInfo, pSignature,
2306 &outlen, maxoutlen, tmpbuf, digestLen))
2307 crv = sftk_MapCryptError(PORT_GetError());
2308 /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate.
2309 * Keeping "too small" CK_RV intact is a standard violation, but allows
2310 * application read EXACT signature length */
2312 /* must be block cipher MACing */
2313 outlen = context->macSize;
2314 /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/
2315 if( !pSignature || maxoutlen < outlen ) {
2316 if( pSignature ) crv = CKR_BUFFER_TOO_SMALL;
2319 if( CKR_OK == (crv = sftk_MACFinal( context )) )
2320 PORT_Memcpy(pSignature, context->macBuf, outlen );
2323 sftk_TerminateOp( session, SFTK_SIGN, context );
2325 *pulSignatureLen = outlen;
2326 sftk_FreeSession(session);
2330 /* NSC_Sign signs (encrypts with private key) data in a single part,
2331 * where the signature is (will be) an appendix to the data,
2332 * and plaintext cannot be recovered from the signature */
2333 CK_RV NSC_Sign(CK_SESSION_HANDLE hSession,
2334 CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,
2335 CK_ULONG_PTR pulSignatureLen)
2337 SFTKSession *session;
2338 SFTKSessionContext *context;
2343 /* make sure we're legal */
2344 crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_FALSE,&session);
2345 if (crv != CKR_OK) return crv;
2348 /* see also how C_SignUpdate implements this */
2349 *pulSignatureLen = (!context->multi || context->hashInfo)
2351 : context->macSize; /* must be block cipher MACing */
2355 /* multi part Signing are completely implemented by SignUpdate and
2357 if (context->multi) {
2358 /* SignFinal can't follow failed SignUpdate */
2359 if( CKR_OK == (crv = NSC_SignUpdate(hSession,pData,ulDataLen) ))
2360 crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen);
2362 /* single-part PKC signature (e.g. CKM_ECDSA) */
2363 unsigned int outlen;
2364 unsigned int maxoutlen = *pulSignatureLen;
2365 if( SECSuccess != (*context->update)(context->cipherInfo, pSignature,
2366 &outlen, maxoutlen, pData, ulDataLen))
2367 crv = sftk_MapCryptError(PORT_GetError());
2368 *pulSignatureLen = (CK_ULONG) outlen;
2369 /* "too small" here is certainly continuable */
2370 if( crv != CKR_BUFFER_TOO_SMALL )
2371 sftk_TerminateOp(session, SFTK_SIGN, context);
2375 sftk_FreeSession(session);
2381 ************** Crypto Functions: Sign Recover ************************
2383 /* NSC_SignRecoverInit initializes a signature operation,
2384 * where the (digest) data can be recovered from the signature.
2385 * E.g. encryption with the user's private key */
2386 CK_RV NSC_SignRecoverInit(CK_SESSION_HANDLE hSession,
2387 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
2391 switch (pMechanism->mechanism) {
2394 return NSC_SignInit(hSession,pMechanism,hKey);
2398 return CKR_MECHANISM_INVALID;
2402 /* NSC_SignRecover signs data in a single operation
2403 * where the (digest) data can be recovered from the signature.
2404 * E.g. encryption with the user's private key */
2405 CK_RV NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
2406 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
2410 return NSC_Sign(hSession,pData,ulDataLen,pSignature,pulSignatureLen);
2414 ************** Crypto Functions: verify ************************
2417 /* Handle RSA Signature formatting */
2419 sftk_hashCheckSign(SFTKHashVerifyInfo *info, unsigned char *sig,
2420 unsigned int sigLen, unsigned char *digest, unsigned int digestLen)
2422 return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen,
2427 RSA_HashCheckSign(SECOidTag hashOid, NSSLOWKEYPublicKey *key,
2428 unsigned char *sig, unsigned int sigLen,
2429 unsigned char *digest, unsigned int digestLen)
2433 SGNDigestInfo *di = NULL;
2434 SECStatus rv = SECSuccess;
2438 if (key == NULL) goto loser;
2440 it.len = nsslowkey_PublicModulusLen(key);
2441 if (!it.len) goto loser;
2443 it.data = (unsigned char *) PORT_Alloc(it.len);
2444 if (it.data == NULL) goto loser;
2446 /* decrypt the block */
2447 rv = RSA_CheckSignRecover(key, it.data, &it.len, it.len, sig, sigLen);
2448 if (rv != SECSuccess) goto loser;
2450 di = SGN_DecodeDigestInfo(&it);
2451 if (di == NULL) goto loser;
2452 if (di->digest.len != digestLen) goto loser;
2454 /* make sure the tag is OK */
2455 if (SECOID_GetAlgorithmTag(&di->digestAlgorithm) != hashOid) {
2458 /* make sure the "parameters" are not too bogus. */
2459 if (di->digestAlgorithm.parameters.len > 2) {
2462 /* Now check the signature */
2463 if (PORT_Memcmp(digest, di->digest.data, di->digest.len) == 0) {
2468 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
2472 if (it.data != NULL) PORT_Free(it.data);
2473 if (di != NULL) SGN_DestroyDigestInfo(di);
2479 sftk_CheckSignPSS(SFTKHashVerifyInfo *info, unsigned char *sig,
2480 unsigned int sigLen, unsigned char *digest, unsigned int digestLen)
2482 return RSA_CheckSignPSS(info->params, info->key, sig, sigLen,
2486 /* NSC_VerifyInit initializes a verification operation,
2487 * where the signature is an appendix to the data,
2488 * and plaintext cannot be recovered from the signature (e.g. DSA) */
2489 CK_RV NSC_VerifyInit(CK_SESSION_HANDLE hSession,
2490 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
2492 SFTKSession *session;
2494 SFTKSessionContext *context;
2495 CK_KEY_TYPE key_type;
2497 NSSLOWKEYPublicKey *pubKey;
2498 SFTKHashVerifyInfo *info = NULL;
2502 /* Block Cipher MACing Algorithms use a different Context init method..*/
2503 crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY);
2504 if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv;
2506 session = sftk_SessionFromHandle(hSession);
2507 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2508 crv = sftk_InitGeneric(session,&context,SFTK_VERIFY,&key,hKey,&key_type,
2509 CKO_PUBLIC_KEY,CKA_VERIFY);
2510 if (crv != CKR_OK) {
2511 sftk_FreeSession(session);
2515 context->multi = PR_FALSE;
2517 #define INIT_RSA_VFY_MECH(mmm) \
2518 case CKM_ ## mmm ## _RSA_PKCS: \
2519 context->multi = PR_TRUE; \
2520 crv = sftk_doSub ## mmm (context); \
2521 if (crv != CKR_OK) break; \
2522 context->verify = (SFTKVerify) sftk_hashCheckSign; \
2523 info = PORT_New(SFTKHashVerifyInfo); \
2524 if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \
2525 info->hashOid = SEC_OID_ ## mmm ; \
2528 switch(pMechanism->mechanism) {
2529 INIT_RSA_VFY_MECH(MD5)
2530 INIT_RSA_VFY_MECH(MD2)
2531 INIT_RSA_VFY_MECH(SHA1)
2532 INIT_RSA_VFY_MECH(SHA224)
2533 INIT_RSA_VFY_MECH(SHA256)
2534 INIT_RSA_VFY_MECH(SHA384)
2535 INIT_RSA_VFY_MECH(SHA512)
2538 context->verify = (SFTKVerify) RSA_CheckSign;
2541 context->verify = (SFTKVerify) RSA_CheckSignRaw;
2543 if (key_type != CKK_RSA) {
2544 if (info) PORT_Free(info);
2545 crv = CKR_KEY_TYPE_INCONSISTENT;
2548 pubKey = sftk_GetPubKey(key,CKK_RSA,&crv);
2549 if (pubKey == NULL) {
2550 if (info) PORT_Free(info);
2551 crv = CKR_KEY_TYPE_INCONSISTENT;
2556 context->cipherInfo = info;
2557 context->destroy = sftk_Space;
2559 context->cipherInfo = pubKey;
2560 context->destroy = sftk_Null;
2563 case CKM_RSA_PKCS_PSS:
2564 if (key_type != CKK_RSA) {
2565 crv = CKR_KEY_TYPE_INCONSISTENT;
2568 if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) {
2569 crv = CKR_MECHANISM_PARAM_INVALID;
2572 info = PORT_New(SFTKHashVerifyInfo);
2574 crv = CKR_HOST_MEMORY;
2577 info->params = pMechanism->pParameter;
2578 info->key = sftk_GetPubKey(key,CKK_RSA,&crv);
2579 if (info->key == NULL) {
2583 context->cipherInfo = info;
2584 context->destroy = (SFTKDestroy) sftk_Space;
2585 context->verify = (SFTKVerify) sftk_CheckSignPSS;
2588 context->multi = PR_TRUE;
2589 crv = sftk_doSubSHA1(context);
2590 if (crv != CKR_OK) break;
2593 if (key_type != CKK_DSA) {
2594 crv = CKR_KEY_TYPE_INCONSISTENT;
2597 pubKey = sftk_GetPubKey(key,CKK_DSA,&crv);
2598 if (pubKey == NULL) {
2601 context->cipherInfo = pubKey;
2602 context->verify = (SFTKVerify) nsc_DSA_Verify_Stub;
2603 context->destroy = sftk_Null;
2605 #ifdef NSS_ENABLE_ECC
2606 case CKM_ECDSA_SHA1:
2607 context->multi = PR_TRUE;
2608 crv = sftk_doSubSHA1(context);
2609 if (crv != CKR_OK) break;
2612 if (key_type != CKK_EC) {
2613 crv = CKR_KEY_TYPE_INCONSISTENT;
2616 pubKey = sftk_GetPubKey(key,CKK_EC,&crv);
2617 if (pubKey == NULL) {
2618 crv = CKR_HOST_MEMORY;
2621 context->cipherInfo = pubKey;
2622 context->verify = (SFTKVerify) nsc_ECDSAVerifyStub;
2623 context->destroy = sftk_Null;
2625 #endif /* NSS_ENABLE_ECC */
2629 INIT_HMAC_MECH(SHA224)
2630 INIT_HMAC_MECH(SHA256)
2631 INIT_HMAC_MECH(SHA384)
2632 INIT_HMAC_MECH(SHA512)
2634 case CKM_SHA_1_HMAC_GENERAL:
2635 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,
2636 *(CK_ULONG *)pMechanism->pParameter);
2638 case CKM_SHA_1_HMAC:
2639 crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH);
2642 case CKM_SSL3_MD5_MAC:
2643 crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key,
2644 *(CK_ULONG *)pMechanism->pParameter);
2646 case CKM_SSL3_SHA1_MAC:
2647 crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key,
2648 *(CK_ULONG *)pMechanism->pParameter);
2650 case CKM_TLS_PRF_GENERAL:
2651 crv = sftk_TLSPRFInit(context, key, key_type);
2655 crv = CKR_MECHANISM_INVALID;
2659 if (crv != CKR_OK) {
2660 if (info) PORT_Free(info);
2661 sftk_FreeContext(context);
2662 sftk_FreeSession(session);
2665 sftk_SetContextByType(session, SFTK_VERIFY, context);
2666 sftk_FreeSession(session);
2670 /* NSC_Verify verifies a signature in a single-part operation,
2671 * where the signature is an appendix to the data,
2672 * and plaintext cannot be recovered from the signature */
2673 CK_RV NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
2674 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
2676 SFTKSession *session;
2677 SFTKSessionContext *context;
2682 /* make sure we're legal */
2683 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_FALSE,&session);
2684 if (crv != CKR_OK) return crv;
2686 /* multi part Verifying are completely implemented by VerifyUpdate and
2688 if (context->multi) {
2689 /* VerifyFinal can't follow failed VerifyUpdate */
2690 if( CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen)))
2691 crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen);
2693 if (SECSuccess != (*context->verify)(context->cipherInfo,pSignature,
2694 ulSignatureLen, pData, ulDataLen))
2695 crv = sftk_MapCryptError(PORT_GetError());
2697 sftk_TerminateOp( session, SFTK_VERIFY, context );
2699 sftk_FreeSession(session);
2704 /* NSC_VerifyUpdate continues a multiple-part verification operation,
2705 * where the signature is an appendix to the data,
2706 * and plaintext cannot be recovered from the signature
2708 * A call which results in an error terminates the operation [PKCS#11,v2.11]
2710 CK_RV NSC_VerifyUpdate( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
2714 return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY);
2718 /* NSC_VerifyFinal finishes a multiple-part verification operation,
2719 * checking the signature. */
2720 CK_RV NSC_VerifyFinal(CK_SESSION_HANDLE hSession,
2721 CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)
2723 SFTKSession *session;
2724 SFTKSessionContext *context;
2730 return CKR_ARGUMENTS_BAD;
2732 /* make sure we're legal */
2733 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_TRUE,&session);
2737 if (context->hashInfo) {
2738 unsigned int digestLen;
2739 unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
2741 (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
2742 if( SECSuccess != (context->verify)(context->cipherInfo, pSignature,
2743 ulSignatureLen, tmpbuf, digestLen))
2744 crv = sftk_MapCryptError(PORT_GetError());
2745 } else if (ulSignatureLen != context->macSize) {
2746 /* must be block cipher MACing */
2747 crv = CKR_SIGNATURE_LEN_RANGE;
2748 } else if (CKR_OK == (crv = sftk_MACFinal(context))) {
2749 if (PORT_Memcmp(pSignature, context->macBuf, ulSignatureLen))
2750 crv = CKR_SIGNATURE_INVALID;
2753 sftk_TerminateOp( session, SFTK_VERIFY, context );
2754 sftk_FreeSession(session);
2760 ************** Crypto Functions: Verify Recover ************************
2763 /* NSC_VerifyRecoverInit initializes a signature verification operation,
2764 * where the data is recovered from the signature.
2765 * E.g. Decryption with the user's public key */
2766 CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
2767 CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
2769 SFTKSession *session;
2771 SFTKSessionContext *context;
2772 CK_KEY_TYPE key_type;
2774 NSSLOWKEYPublicKey *pubKey;
2778 session = sftk_SessionFromHandle(hSession);
2779 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2780 crv = sftk_InitGeneric(session,&context,SFTK_VERIFY_RECOVER,
2781 &key,hKey,&key_type,CKO_PUBLIC_KEY,CKA_VERIFY_RECOVER);
2782 if (crv != CKR_OK) {
2783 sftk_FreeSession(session);
2787 context->multi = PR_TRUE;
2789 switch(pMechanism->mechanism) {
2792 if (key_type != CKK_RSA) {
2793 crv = CKR_KEY_TYPE_INCONSISTENT;
2796 context->multi = PR_FALSE;
2797 pubKey = sftk_GetPubKey(key,CKK_RSA,&crv);
2798 if (pubKey == NULL) {
2801 context->cipherInfo = pubKey;
2802 context->update = (SFTKCipher) (pMechanism->mechanism == CKM_RSA_X_509
2803 ? RSA_CheckSignRecoverRaw : RSA_CheckSignRecover);
2804 context->destroy = sftk_Null;
2807 crv = CKR_MECHANISM_INVALID;
2811 if (crv != CKR_OK) {
2813 sftk_FreeSession(session);
2816 sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context);
2817 sftk_FreeSession(session);
2822 /* NSC_VerifyRecover verifies a signature in a single-part operation,
2823 * where the data is recovered from the signature.
2824 * E.g. Decryption with the user's public key */
2825 CK_RV NSC_VerifyRecover(CK_SESSION_HANDLE hSession,
2826 CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,
2827 CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)
2829 SFTKSession *session;
2830 SFTKSessionContext *context;
2831 unsigned int outlen;
2832 unsigned int maxoutlen = *pulDataLen;
2838 /* make sure we're legal */
2839 crv = sftk_GetContext(hSession,&context,SFTK_VERIFY_RECOVER,
2841 if (crv != CKR_OK) return crv;
2842 if (pData == NULL) {
2843 /* to return the actual size, we need to do the decrypt, just return
2844 * the max size, which is the size of the input signature. */
2845 *pulDataLen = ulSignatureLen;
2850 rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
2851 pSignature, ulSignatureLen);
2852 *pulDataLen = (CK_ULONG) outlen;
2854 sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context);
2856 sftk_FreeSession(session);
2857 return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError());
2861 **************************** Random Functions: ************************
2864 /* NSC_SeedRandom mixes additional seed material into the token's random number
2866 CK_RV NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
2873 rv = RNG_RandomUpdate(pSeed, ulSeedLen);
2874 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
2877 /* NSC_GenerateRandom generates random data. */
2878 CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
2879 CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
2885 rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen);
2887 * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't
2888 * seeded with enough entropy.
2890 return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
2894 **************************** Key Functions: ************************
2899 * generate a password based encryption key. This code uses
2900 * PKCS5 to do the work.
2903 nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
2904 void *buf, CK_ULONG *key_length, PRBool faulty3DES)
2906 SECItem *pbe_key = NULL, iv, pwitem;
2907 CK_PBE_PARAMS *pbe_params = NULL;
2908 CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
2911 iv.data = NULL; iv.len = 0;
2913 if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
2914 pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
2915 pwitem.data = (unsigned char *)pbkd2_params->pPassword;
2916 /* was this a typo in the PKCS #11 spec? */
2917 pwitem.len = *pbkd2_params->ulPasswordLen;
2919 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
2920 pwitem.data = (unsigned char *)pbe_params->pPassword;
2921 pwitem.len = pbe_params->ulPasswordLen;
2923 pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES);
2924 if (pbe_key == NULL) {
2925 return CKR_HOST_MEMORY;
2928 PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
2929 *key_length = pbe_key->len;
2930 SECITEM_ZfreeItem(pbe_key, PR_TRUE);
2934 if (pbe_params && pbe_params->pInitVector != NULL) {
2935 PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len);
2943 nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
2945 SFTKAttribute *attribute;
2947 unsigned int seedBits = 0;
2948 unsigned int primeBits;
2951 PQGParams *params = NULL;
2952 PQGVerify *vfy = NULL;
2955 attribute = sftk_FindAttribute(key, CKA_PRIME_BITS);
2956 if (attribute == NULL) {
2957 return CKR_TEMPLATE_INCOMPLETE;
2959 primeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
2960 sftk_FreeAttribute(attribute);
2961 j = PQG_PBITS_TO_INDEX(primeBits);
2962 if (j == (unsigned int)-1) {
2963 return CKR_ATTRIBUTE_VALUE_INVALID;
2966 attribute = sftk_FindAttribute(key, CKA_NETSCAPE_PQG_SEED_BITS);
2967 if (attribute != NULL) {
2968 seedBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
2969 sftk_FreeAttribute(attribute);
2972 sftk_DeleteAttributeType(key,CKA_PRIME_BITS);
2973 sftk_DeleteAttributeType(key,CKA_NETSCAPE_PQG_SEED_BITS);
2975 if (seedBits == 0) {
2976 rv = PQG_ParamGen(j, ¶ms, &vfy);
2978 rv = PQG_ParamGenSeedLen(j,seedBits/8, ¶ms, &vfy);
2981 if (rv != SECSuccess) {
2982 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2983 sftk_fatalError = PR_TRUE;
2985 return sftk_MapCryptError(PORT_GetError());
2987 crv = sftk_AddAttributeType(key,CKA_PRIME,
2988 params->prime.data, params->prime.len);
2989 if (crv != CKR_OK) goto loser;
2990 crv = sftk_AddAttributeType(key,CKA_SUBPRIME,
2991 params->subPrime.data, params->subPrime.len);
2992 if (crv != CKR_OK) goto loser;
2993 crv = sftk_AddAttributeType(key,CKA_BASE,
2994 params->base.data, params->base.len);
2995 if (crv != CKR_OK) goto loser;
2996 counter = vfy->counter;
2997 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_COUNTER,
2998 &counter, sizeof(counter));
2999 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_SEED,
3000 vfy->seed.data, vfy->seed.len);
3001 if (crv != CKR_OK) goto loser;
3002 crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_H,
3003 vfy->h.data, vfy->h.len);
3004 if (crv != CKR_OK) goto loser;
3007 PQG_DestroyParams(params);
3010 PQG_DestroyVerify(vfy);
3017 nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
3018 CK_ULONG *key_length)
3022 switch (mechanism) {
3023 case CKM_RC2_KEY_GEN:
3024 *key_type = CKK_RC2;
3025 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3027 #if NSS_SOFTOKEN_DOES_RC5
3028 case CKM_RC5_KEY_GEN:
3029 *key_type = CKK_RC5;
3030 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3033 case CKM_RC4_KEY_GEN:
3034 *key_type = CKK_RC4;
3035 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3037 case CKM_GENERIC_SECRET_KEY_GEN:
3038 *key_type = CKK_GENERIC_SECRET;
3039 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3041 case CKM_CDMF_KEY_GEN:
3042 *key_type = CKK_CDMF;
3045 case CKM_DES_KEY_GEN:
3046 *key_type = CKK_DES;
3049 case CKM_DES2_KEY_GEN:
3050 *key_type = CKK_DES2;
3053 case CKM_DES3_KEY_GEN:
3054 *key_type = CKK_DES3;
3057 case CKM_SEED_KEY_GEN:
3058 *key_type = CKK_SEED;
3061 case CKM_CAMELLIA_KEY_GEN:
3062 *key_type = CKK_CAMELLIA;
3063 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3065 case CKM_AES_KEY_GEN:
3066 *key_type = CKK_AES;
3067 if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
3071 crv = CKR_MECHANISM_INVALID;
3079 nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
3082 CK_PBE_PARAMS *pbe_params = NULL;
3083 NSSPKCS5PBEParameter *params;
3084 PRArenaPool *arena = NULL;
3089 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
3090 if (arena == NULL) {
3091 return CKR_HOST_MEMORY;
3094 params = (NSSPKCS5PBEParameter *) PORT_ArenaZAlloc(arena,
3095 sizeof(NSSPKCS5PBEParameter));
3096 if (params == NULL) {
3097 PORT_FreeArena(arena,PR_TRUE);
3098 return CKR_HOST_MEMORY;
3101 params->poolp = arena;
3103 params->pbeType = NSSPKCS5_PKCS12_V2;
3104 params->hashType = HASH_AlgSHA1;
3105 params->encAlg = SEC_OID_SHA1; /* any invalid value */
3106 params->is2KeyDES = PR_FALSE;
3107 params->keyID = pbeBitGenIntegrityKey;
3108 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
3109 params->iter = pbe_params->ulIteration;
3111 salt.data = (unsigned char *)pbe_params->pSalt;
3112 salt.len = (unsigned int)pbe_params->ulSaltLen;
3113 rv = SECITEM_CopyItem(arena,¶ms->salt,&salt);
3114 if (rv != SECSuccess) {
3115 PORT_FreeArena(arena,PR_TRUE);
3116 return CKR_HOST_MEMORY;
3118 switch (pMechanism->mechanism) {
3119 case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
3120 case CKM_PBA_SHA1_WITH_SHA1_HMAC:
3121 params->hashType = HASH_AlgSHA1;
3122 params->keyLen = 20;
3124 case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
3125 params->hashType = HASH_AlgMD5;
3126 params->keyLen = 16;
3128 case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
3129 params->hashType = HASH_AlgMD2;
3130 params->keyLen = 16;
3133 PORT_FreeArena(arena,PR_TRUE);
3134 return CKR_MECHANISM_INVALID;
3140 /* maybe this should be table driven? */
3142 nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
3143 CK_KEY_TYPE *key_type, CK_ULONG *key_length)
3147 CK_PBE_PARAMS *pbe_params = NULL;
3148 NSSPKCS5PBEParameter *params = NULL;
3149 CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
3151 CK_ULONG iteration = 0;
3155 oid = SECOID_FindOIDByMechanism(pMechanism->mechanism);
3157 return CKR_MECHANISM_INVALID;
3160 if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
3161 pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
3162 if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) {
3163 return CKR_MECHANISM_PARAM_INVALID;
3165 salt.data = (unsigned char *)pbkd2_params->pSaltSourceData;
3166 salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen;
3167 iteration = pbkd2_params->iterations;
3169 pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
3170 salt.data = (unsigned char *)pbe_params->pSalt;
3171 salt.len = (unsigned int)pbe_params->ulSaltLen;
3172 iteration = pbe_params->ulIteration;
3174 params=nsspkcs5_NewParam(oid->offset, &salt, iteration);
3175 if (params == NULL) {
3176 return CKR_MECHANISM_INVALID;
3179 switch (params->encAlg) {
3180 case SEC_OID_DES_CBC:
3181 *key_type = CKK_DES;
3182 *key_length = params->keyLen;
3184 case SEC_OID_DES_EDE3_CBC:
3185 *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3;
3186 *key_length = params->keyLen;
3188 case SEC_OID_RC2_CBC:
3189 *key_type = CKK_RC2;
3190 *key_length = params->keyLen;
3193 *key_type = CKK_RC4;
3194 *key_length = params->keyLen;
3196 case SEC_OID_PKCS5_PBKDF2:
3197 /* sigh, PKCS #11 currently only defines SHA1 for the KDF hash type.
3198 * we do the check here because this where we would handle multiple
3199 * hash types in the future */
3200 if (pbkd2_params == NULL ||
3201 pbkd2_params->prf != CKP_PKCS5_PBKD2_HMAC_SHA1) {
3202 crv = CKR_MECHANISM_PARAM_INVALID;
3205 /* key type must already be set */
3206 if (*key_type == CKK_INVALID_KEY_TYPE) {
3207 crv = CKR_TEMPLATE_INCOMPLETE;
3210 /* PBKDF2 needs to calculate the key length from the other parameters
3212 if (*key_length == 0) {
3213 *key_length = sftk_MapKeySize(*key_type);
3215 if (*key_length == 0) {
3216 crv = CKR_TEMPLATE_INCOMPLETE;
3219 params->keyLen = *key_length;
3222 crv = CKR_MECHANISM_INVALID;
3223 nsspkcs5_DestroyPBEParameter(params);
3226 if (crv == CKR_OK) {
3232 /* NSC_GenerateKey generates a secret key, creating a new key object. */
3233 CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
3234 CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,
3235 CK_OBJECT_HANDLE_PTR phKey)
3238 SFTKSession *session;
3239 PRBool checkWeak = PR_FALSE;
3240 CK_ULONG key_length = 0;
3241 CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE;
3242 CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
3244 CK_BBOOL cktrue = CK_TRUE;
3246 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
3247 unsigned char buf[MAX_KEY_LEN];
3248 enum {nsc_pbe, nsc_ssl, nsc_bulk, nsc_param, nsc_jpake} key_gen_type;
3249 NSSPKCS5PBEParameter *pbe_param;
3250 SSL3RSAPreMasterSecret *rsa_pms;
3251 CK_VERSION *version;
3252 /* in very old versions of NSS, there were implementation errors with key
3253 * generation methods. We want to beable to read these, but not
3254 * produce them any more. The affected algorithm was 3DES.
3256 PRBool faultyPBE3DES = PR_FALSE;
3257 HASH_HashType hashType;
3262 return CKR_SESSION_HANDLE_INVALID;
3265 * now lets create an object to hang the attributes off of
3267 key = sftk_NewObject(slot); /* fill in the handle later */
3269 return CKR_HOST_MEMORY;
3273 * load the template values into the object
3275 for (i=0; i < (int) ulCount; i++) {
3276 if (pTemplate[i].type == CKA_VALUE_LEN) {
3277 key_length = *(CK_ULONG *)pTemplate[i].pValue;
3280 /* some algorithms need keytype specified */
3281 if (pTemplate[i].type == CKA_KEY_TYPE) {
3282 key_type = *(CK_ULONG *)pTemplate[i].pValue;
3286 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i]));
3287 if (crv != CKR_OK) break;
3289 if (crv != CKR_OK) {
3290 sftk_FreeObject(key);
3294 /* make sure we don't have any class, key_type, or value fields */
3295 sftk_DeleteAttributeType(key,CKA_CLASS);
3296 sftk_DeleteAttributeType(key,CKA_KEY_TYPE);
3297 sftk_DeleteAttributeType(key,CKA_VALUE);
3299 /* Now Set up the parameters to generate the key (based on mechanism) */
3300 key_gen_type = nsc_bulk; /* bulk key by default */
3301 switch (pMechanism->mechanism) {
3302 case CKM_CDMF_KEY_GEN:
3303 case CKM_DES_KEY_GEN:
3304 case CKM_DES2_KEY_GEN:
3305 case CKM_DES3_KEY_GEN:
3306 checkWeak = PR_TRUE;
3307 case CKM_RC2_KEY_GEN:
3308 case CKM_RC4_KEY_GEN:
3309 case CKM_GENERIC_SECRET_KEY_GEN:
3310 case CKM_SEED_KEY_GEN:
3311 case CKM_CAMELLIA_KEY_GEN:
3312 case CKM_AES_KEY_GEN:
3313 #if NSS_SOFTOKEN_DOES_RC5
3314 case CKM_RC5_KEY_GEN:
3316 crv = nsc_SetupBulkKeyGen(pMechanism->mechanism,&key_type,&key_length);
3318 case CKM_SSL3_PRE_MASTER_KEY_GEN:
3319 key_type = CKK_GENERIC_SECRET;
3321 key_gen_type = nsc_ssl;
3323 case CKM_PBA_SHA1_WITH_SHA1_HMAC:
3324 case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
3325 case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
3326 case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
3327 key_gen_type = nsc_pbe;
3328 key_type = CKK_GENERIC_SECRET;
3329 crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param);
3331 case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
3332 faultyPBE3DES = PR_TRUE;
3333 case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:
3334 case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
3335 case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
3336 case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC:
3337 case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4:
3338 case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4:
3339 case CKM_PBE_SHA1_DES3_EDE_CBC:
3340 case CKM_PBE_SHA1_DES2_EDE_CBC:
3341 case CKM_PBE_SHA1_RC2_128_CBC:
3342 case CKM_PBE_SHA1_RC2_40_CBC:
3343 case CKM_PBE_SHA1_RC4_128:
3344 case CKM_PBE_SHA1_RC4_40:
3345 case CKM_PBE_MD5_DES_CBC:
3346 case CKM_PBE_MD2_DES_CBC:
3347 case CKM_PKCS5_PBKD2:
3348 key_gen_type = nsc_pbe;
3349 crv = nsc_SetupPBEKeyGen(pMechanism,&pbe_param, &key_type, &key_length);
3351 case CKM_DSA_PARAMETER_GEN:
3352 key_gen_type = nsc_param;
3354 objclass = CKO_KG_PARAMETERS;
3357 case CKM_NSS_JPAKE_ROUND1_SHA1: hashType = HASH_AlgSHA1; goto jpake1;
3358 case CKM_NSS_JPAKE_ROUND1_SHA256: hashType = HASH_AlgSHA256; goto jpake1;
3359 case CKM_NSS_JPAKE_ROUND1_SHA384: hashType = HASH_AlgSHA384; goto jpake1;
3360 case CKM_NSS_JPAKE_ROUND1_SHA512: hashType = HASH_AlgSHA512; goto jpake1;
3362 key_gen_type = nsc_jpake;
3363 key_type = CKK_NSS_JPAKE_ROUND1;
3364 objclass = CKO_PRIVATE_KEY;
3365 if (pMechanism->pParameter == NULL ||
3366 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) {
3367 crv = CKR_MECHANISM_PARAM_INVALID;
3370 if (sftk_isTrue(key, CKA_TOKEN)) {
3371 crv = CKR_TEMPLATE_INCONSISTENT;
3376 crv = CKR_MECHANISM_INVALID;
3380 /* make sure we aren't going to overflow the buffer */
3381 if (sizeof(buf) < key_length) {
3382 /* someone is getting pretty optimistic about how big their key can
3384 crv = CKR_TEMPLATE_INCONSISTENT;
3387 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3389 /* if there was no error,
3390 * key_type *MUST* be set in the switch statement above */
3391 PORT_Assert( key_type != CKK_INVALID_KEY_TYPE );
3394 * now to the actual key gen.
3396 switch (key_gen_type) {
3398 crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length,
3400 nsspkcs5_DestroyPBEParameter(pbe_param);
3403 rsa_pms = (SSL3RSAPreMasterSecret *)buf;
3404 version = (CK_VERSION *)pMechanism->pParameter;
3405 rsa_pms->client_version[0] = version->major;
3406 rsa_pms->client_version[1] = version->minor;
3408 NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random));
3411 /* get the key, check for weak keys and repeat if found */
3413 crv = NSC_GenerateRandom(0, buf, key_length);
3414 } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf,key_type));
3417 /* generate parameters */
3419 crv = nsc_parameter_gen(key_type,key);
3422 crv = jpake_Round1(hashType,
3423 (CK_NSS_JPAKERound1Params *) pMechanism->pParameter,
3428 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3430 /* Add the class, key_type, and value */
3431 crv = sftk_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS));
3432 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3433 crv = sftk_AddAttributeType(key,CKA_KEY_TYPE,&key_type,sizeof(CK_KEY_TYPE));
3434 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3435 if (key_length != 0) {
3436 crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length);
3437 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
3440 /* get the session */
3441 session = sftk_SessionFromHandle(hSession);
3442 if (session == NULL) {
3443 sftk_FreeObject(key);
3444 return CKR_SESSION_HANDLE_INVALID;
3448 * handle the base object stuff
3450 crv = sftk_handleObject(key,session);
3451 sftk_FreeSession(session);
3452 if (sftk_isTrue(key,CKA_SENSITIVE)) {
3453 sftk_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL));
3455 if (!sftk_isTrue(key,CKA_EXTRACTABLE)) {
3456 sftk_forceAttribute(key,CKA_NEVER_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL));
3459 *phKey = key->handle;
3460 sftk_FreeObject(key);
3464 #define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */
3465 #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */
3468 * FIPS 140-2 pairwise consistency check utilized to validate key pair.
3470 * This function returns
3471 * CKR_OK if pairwise consistency check passed
3472 * CKR_GENERAL_ERROR if pairwise consistency check failed
3473 * other error codes if paiswise consistency check could not be
3474 * performed, for example, CKR_HOST_MEMORY.
3477 sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
3478 SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType)
3481 * Key type Mechanism type
3482 * --------------------------------
3483 * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS
3484 * others => CKM_INVALID_MECHANISM
3486 * For sign/verify: CKK_RSA => CKM_RSA_PKCS
3487 * CKK_DSA => CKM_DSA
3488 * CKK_EC => CKM_ECDSA
3489 * others => CKM_INVALID_MECHANISM
3491 * None of these mechanisms has a parameter.
3493 CK_MECHANISM mech = {0, NULL, 0};
3495 CK_ULONG modulusLen;
3496 PRBool isEncryptable = PR_FALSE;
3497 PRBool canSignVerify = PR_FALSE;
3498 PRBool isDerivable = PR_FALSE;
3501 /* Variables used for Encrypt/Decrypt functions. */
3502 unsigned char *known_message = (unsigned char *)"Known Crypto Message";
3503 unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH];
3504 CK_ULONG bytes_decrypted;
3505 unsigned char *ciphertext;
3506 unsigned char *text_compared;
3507 CK_ULONG bytes_encrypted;
3508 CK_ULONG bytes_compared;
3510 /* Variables used for Signature/Verification functions. */
3511 /* always uses SHA-1 digest */
3512 unsigned char *known_digest = (unsigned char *)"Mozilla Rules World!";
3513 unsigned char *signature;
3514 CK_ULONG signature_length;
3516 if (keyType == CKK_RSA) {
3517 SFTKAttribute *attribute;
3519 /* Get modulus length of private key. */
3520 attribute = sftk_FindAttribute(privateKey, CKA_MODULUS);
3521 if (attribute == NULL) {
3522 return CKR_DEVICE_ERROR;
3524 modulusLen = attribute->attrib.ulValueLen;
3525 if (*(unsigned char *)attribute->attrib.pValue == 0) {
3528 sftk_FreeAttribute(attribute);
3531 /**************************************************/
3532 /* Pairwise Consistency Check of Encrypt/Decrypt. */
3533 /**************************************************/
3535 isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT);
3538 * If the decryption attribute is set, attempt to encrypt
3539 * with the public key and decrypt with the private key.
3541 if (isEncryptable) {
3542 if (keyType != CKK_RSA) {
3543 return CKR_DEVICE_ERROR;
3545 bytes_encrypted = modulusLen;
3546 mech.mechanism = CKM_RSA_PKCS;
3548 /* Allocate space for ciphertext. */
3549 ciphertext = (unsigned char *) PORT_ZAlloc(bytes_encrypted);
3550 if (ciphertext == NULL) {
3551 return CKR_HOST_MEMORY;
3554 /* Prepare for encryption using the public key. */
3555 crv = NSC_EncryptInit(hSession, &mech, publicKey->handle);
3556 if (crv != CKR_OK) {
3557 PORT_Free(ciphertext);
3561 /* Encrypt using the public key. */
3562 crv = NSC_Encrypt(hSession,
3564 PAIRWISE_MESSAGE_LENGTH,
3567 if (crv != CKR_OK) {
3568 PORT_Free(ciphertext);
3572 /* Always use the smaller of these two values . . . */
3573 bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH);
3576 * If there was a failure, the plaintext
3577 * goes at the end, therefore . . .
3579 text_compared = ciphertext + bytes_encrypted - bytes_compared;
3582 * Check to ensure that ciphertext does
3583 * NOT EQUAL known input message text
3584 * per FIPS PUB 140-2 directive.
3586 if (PORT_Memcmp(text_compared, known_message,
3587 bytes_compared) == 0) {
3588 /* Set error to Invalid PRIVATE Key. */
3589 PORT_SetError(SEC_ERROR_INVALID_KEY);
3590 PORT_Free(ciphertext);
3591 return CKR_GENERAL_ERROR;
3594 /* Prepare for decryption using the private key. */
3595 crv = NSC_DecryptInit(hSession, &mech, privateKey->handle);
3596 if (crv != CKR_OK) {
3597 PORT_Free(ciphertext);
3601 memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH);
3604 * Initialize bytes decrypted to be the
3605 * expected PAIRWISE_MESSAGE_LENGTH.
3607 bytes_decrypted = PAIRWISE_MESSAGE_LENGTH;
3610 * Decrypt using the private key.
3611 * NOTE: No need to reset the
3612 * value of bytes_encrypted.
3614 crv = NSC_Decrypt(hSession,
3620 /* Finished with ciphertext; free it. */
3621 PORT_Free(ciphertext);
3623 if (crv != CKR_OK) {
3628 * Check to ensure that the output plaintext
3629 * does EQUAL known input message text.
3631 if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) ||
3632 (PORT_Memcmp(plaintext, known_message,
3633 PAIRWISE_MESSAGE_LENGTH) != 0)) {
3634 /* Set error to Bad PUBLIC Key. */
3635 PORT_SetError(SEC_ERROR_BAD_KEY);
3636 return CKR_GENERAL_ERROR;
3640 /**********************************************/
3641 /* Pairwise Consistency Check of Sign/Verify. */
3642 /**********************************************/
3644 canSignVerify = sftk_isTrue(privateKey, CKA_SIGN);
3646 if (canSignVerify) {
3647 /* Determine length of signature. */
3650 signature_length = modulusLen;
3651 mech.mechanism = CKM_RSA_PKCS;
3654 signature_length = DSA_SIGNATURE_LEN;
3655 mech.mechanism = CKM_DSA;
3657 #ifdef NSS_ENABLE_ECC
3659 signature_length = MAX_ECKEY_LEN * 2;
3660 mech.mechanism = CKM_ECDSA;
3664 return CKR_DEVICE_ERROR;
3667 /* Allocate space for signature data. */
3668 signature = (unsigned char *) PORT_ZAlloc(signature_length);
3669 if (signature == NULL) {
3670 return CKR_HOST_MEMORY;
3673 /* Sign the known hash using the private key. */
3674 crv = NSC_SignInit(hSession, &mech, privateKey->handle);
3675 if (crv != CKR_OK) {
3676 PORT_Free(signature);
3680 crv = NSC_Sign(hSession,
3682 PAIRWISE_DIGEST_LENGTH,
3685 if (crv != CKR_OK) {
3686 PORT_Free(signature);
3690 /* Verify the known hash using the public key. */
3691 crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
3692 if (crv != CKR_OK) {
3693 PORT_Free(signature);
3697 crv = NSC_Verify(hSession,
3699 PAIRWISE_DIGEST_LENGTH,
3703 /* Free signature data. */
3704 PORT_Free(signature);
3706 if ((crv == CKR_SIGNATURE_LEN_RANGE) ||
3707 (crv == CKR_SIGNATURE_INVALID)) {
3708 return CKR_GENERAL_ERROR;
3710 if (crv != CKR_OK) {
3715 /**********************************************/
3716 /* Pairwise Consistency Check for Derivation */
3717 /**********************************************/
3719 isDerivable = sftk_isTrue(privateKey, CKA_DERIVE);
3723 * We are not doing consistency check for Diffie-Hellman Key -
3724 * otherwise it would be here
3725 * This is also true for Elliptic Curve Diffie-Hellman keys
3726 * NOTE: EC keys are currently subjected to pairwise
3727 * consistency check for signing/verification.
3730 * FIPS 140-2 had the following pairwise consistency test for
3731 * public and private keys used for key agreement:
3732 * If the keys are used to perform key agreement, then the
3733 * cryptographic module shall create a second, compatible
3734 * key pair. The cryptographic module shall perform both
3735 * sides of the key agreement algorithm and shall compare
3736 * the resulting shared values. If the shared values are
3737 * not equal, the test shall fail.
3738 * This test was removed in Change Notice 3.
3746 /* NSC_GenerateKeyPair generates a public-key/private-key pair,
3747 * creating new key objects. */
3748 CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession,
3749 CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
3750 CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
3751 CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
3752 CK_OBJECT_HANDLE_PTR phPrivateKey)
3754 SFTKObject * publicKey,*privateKey;
3755 SFTKSession * session;
3756 CK_KEY_TYPE key_type;
3758 CK_BBOOL cktrue = CK_TRUE;
3760 CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
3761 CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
3763 SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession);
3764 unsigned int bitSize;
3767 int public_modulus_bits = 0;
3769 RSAPrivateKey * rsaPriv;
3774 DSAPrivateKey * dsaPriv;
3776 /* Diffie Hellman */
3777 int private_value_bits = 0;
3778 DHPrivateKey * dhPriv;
3780 #ifdef NSS_ENABLE_ECC
3781 /* Elliptic Curve Cryptography */
3782 SECItem ecEncodedParams; /* DER Encoded parameters */
3783 ECPrivateKey * ecPriv;
3784 ECParams * ecParams;
3785 #endif /* NSS_ENABLE_ECC */
3790 return CKR_SESSION_HANDLE_INVALID;
3793 * now lets create an object to hang the attributes off of
3795 publicKey = sftk_NewObject(slot); /* fill in the handle later */
3796 if (publicKey == NULL) {
3797 return CKR_HOST_MEMORY;
3801 * load the template values into the publicKey
3803 for (i=0; i < (int) ulPublicKeyAttributeCount; i++) {
3804 if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {
3805 public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
3809 crv = sftk_AddAttributeType(publicKey,
3810 sftk_attr_expand(&pPublicKeyTemplate[i]));
3811 if (crv != CKR_OK) break;
3814 if (crv != CKR_OK) {
3815 sftk_FreeObject(publicKey);
3816 return CKR_HOST_MEMORY;
3819 privateKey = sftk_NewObject(slot); /* fill in the handle later */
3820 if (privateKey == NULL) {
3821 sftk_FreeObject(publicKey);
3822 return CKR_HOST_MEMORY;
3825 * now load the private key template
3827 for (i=0; i < (int) ulPrivateKeyAttributeCount; i++) {
3828 if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {
3829 private_value_bits = *(CK_ULONG *)pPrivateKeyTemplate[i].pValue;
3833 crv = sftk_AddAttributeType(privateKey,
3834 sftk_attr_expand(&pPrivateKeyTemplate[i]));
3835 if (crv != CKR_OK) break;
3838 if (crv != CKR_OK) {
3839 sftk_FreeObject(publicKey);
3840 sftk_FreeObject(privateKey);
3841 return CKR_HOST_MEMORY;
3843 sftk_DeleteAttributeType(privateKey,CKA_CLASS);
3844 sftk_DeleteAttributeType(privateKey,CKA_KEY_TYPE);
3845 sftk_DeleteAttributeType(privateKey,CKA_VALUE);
3846 sftk_DeleteAttributeType(publicKey,CKA_CLASS);
3847 sftk_DeleteAttributeType(publicKey,CKA_KEY_TYPE);
3848 sftk_DeleteAttributeType(publicKey,CKA_VALUE);
3850 /* Now Set up the parameters to generate the key (based on mechanism) */
3851 switch (pMechanism->mechanism) {
3852 case CKM_RSA_PKCS_KEY_PAIR_GEN:
3853 /* format the keys */
3854 sftk_DeleteAttributeType(publicKey,CKA_MODULUS);
3855 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
3856 sftk_DeleteAttributeType(privateKey,CKA_MODULUS);
3857 sftk_DeleteAttributeType(privateKey,CKA_PRIVATE_EXPONENT);
3858 sftk_DeleteAttributeType(privateKey,CKA_PUBLIC_EXPONENT);
3859 sftk_DeleteAttributeType(privateKey,CKA_PRIME_1);
3860 sftk_DeleteAttributeType(privateKey,CKA_PRIME_2);
3861 sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_1);
3862 sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_2);
3863 sftk_DeleteAttributeType(privateKey,CKA_COEFFICIENT);
3865 if (public_modulus_bits == 0) {
3866 crv = CKR_TEMPLATE_INCOMPLETE;
3869 if (public_modulus_bits < RSA_MIN_MODULUS_BITS) {
3870 crv = CKR_ATTRIBUTE_VALUE_INVALID;
3873 if (public_modulus_bits % 2 != 0) {
3874 crv = CKR_ATTRIBUTE_VALUE_INVALID;
3878 /* extract the exponent */
3879 crv=sftk_Attribute2SSecItem(NULL,&pubExp,publicKey,CKA_PUBLIC_EXPONENT);
3880 if (crv != CKR_OK) break;
3881 bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len);
3883 crv = CKR_ATTRIBUTE_VALUE_INVALID;
3886 crv = sftk_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT,
3887 sftk_item_expand(&pubExp));
3888 if (crv != CKR_OK) {
3889 PORT_Free(pubExp.data);
3893 rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);
3894 PORT_Free(pubExp.data);
3895 if (rsaPriv == NULL) {
3896 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
3897 sftk_fatalError = PR_TRUE;
3899 crv = sftk_MapCryptError(PORT_GetError());
3902 /* now fill in the RSA dependent paramenters in the public key */
3903 crv = sftk_AddAttributeType(publicKey,CKA_MODULUS,
3904 sftk_item_expand(&rsaPriv->modulus));
3905 if (crv != CKR_OK) goto kpg_done;
3906 /* now fill in the RSA dependent paramenters in the private key */
3907 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
3908 sftk_item_expand(&rsaPriv->modulus));
3909 if (crv != CKR_OK) goto kpg_done;
3910 crv = sftk_AddAttributeType(privateKey,CKA_MODULUS,
3911 sftk_item_expand(&rsaPriv->modulus));
3912 if (crv != CKR_OK) goto kpg_done;
3913 crv = sftk_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT,
3914 sftk_item_expand(&rsaPriv->privateExponent));
3915 if (crv != CKR_OK) goto kpg_done;
3916 crv = sftk_AddAttributeType(privateKey,CKA_PRIME_1,
3917 sftk_item_expand(&rsaPriv->prime1));
3918 if (crv != CKR_OK) goto kpg_done;
3919 crv = sftk_AddAttributeType(privateKey,CKA_PRIME_2,
3920 sftk_item_expand(&rsaPriv->prime2));
3921 if (crv != CKR_OK) goto kpg_done;
3922 crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_1,
3923 sftk_item_expand(&rsaPriv->exponent1));
3924 if (crv != CKR_OK) goto kpg_done;
3925 crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_2,
3926 sftk_item_expand(&rsaPriv->exponent2));
3927 if (crv != CKR_OK) goto kpg_done;
3928 crv = sftk_AddAttributeType(privateKey,CKA_COEFFICIENT,
3929 sftk_item_expand(&rsaPriv->coefficient));
3931 /* Should zeroize the contents first, since this func doesn't. */
3932 PORT_FreeArena(rsaPriv->arena, PR_TRUE);
3934 case CKM_DSA_KEY_PAIR_GEN:
3935 sftk_DeleteAttributeType(publicKey,CKA_VALUE);
3936 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
3937 sftk_DeleteAttributeType(privateKey,CKA_PRIME);
3938 sftk_DeleteAttributeType(privateKey,CKA_SUBPRIME);
3939 sftk_DeleteAttributeType(privateKey,CKA_BASE);
3942 /* extract the necessary parameters and copy them to the private key */
3943 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.prime,publicKey,CKA_PRIME);
3944 if (crv != CKR_OK) break;
3945 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.subPrime,publicKey,
3947 if (crv != CKR_OK) {
3948 PORT_Free(pqgParam.prime.data);
3951 crv=sftk_Attribute2SSecItem(NULL,&pqgParam.base,publicKey,CKA_BASE);
3952 if (crv != CKR_OK) {
3953 PORT_Free(pqgParam.prime.data);
3954 PORT_Free(pqgParam.subPrime.data);
3957 crv = sftk_AddAttributeType(privateKey,CKA_PRIME,
3958 sftk_item_expand(&pqgParam.prime));
3959 if (crv != CKR_OK) {
3960 PORT_Free(pqgParam.prime.data);
3961 PORT_Free(pqgParam.subPrime.data);
3962 PORT_Free(pqgParam.base.data);
3965 crv = sftk_AddAttributeType(privateKey,CKA_SUBPRIME,
3966 sftk_item_expand(&pqgParam.subPrime));
3967 if (crv != CKR_OK) {
3968 PORT_Free(pqgParam.prime.data);
3969 PORT_Free(pqgParam.subPrime.data);
3970 PORT_Free(pqgParam.base.data);
3973 crv = sftk_AddAttributeType(privateKey,CKA_BASE,
3974 sftk_item_expand(&pqgParam.base));
3975 if (crv != CKR_OK) {
3976 PORT_Free(pqgParam.prime.data);
3977 PORT_Free(pqgParam.subPrime.data);
3978 PORT_Free(pqgParam.base.data);
3982 bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data,
3983 pqgParam.subPrime.len);
3984 if (bitSize != DSA_Q_BITS) {
3985 crv = CKR_TEMPLATE_INCOMPLETE;
3986 PORT_Free(pqgParam.prime.data);
3987 PORT_Free(pqgParam.subPrime.data);
3988 PORT_Free(pqgParam.base.data);
3991 bitSize = sftk_GetLengthInBits(pqgParam.prime.data,pqgParam.prime.len);
3992 if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) {
3993 crv = CKR_TEMPLATE_INCOMPLETE;
3994 PORT_Free(pqgParam.prime.data);
3995 PORT_Free(pqgParam.subPrime.data);
3996 PORT_Free(pqgParam.base.data);
3999 bitSize = sftk_GetLengthInBits(pqgParam.base.data,pqgParam.base.len);
4000 if ((bitSize < 1) || (bitSize > DSA_MAX_P_BITS)) {
4001 crv = CKR_TEMPLATE_INCOMPLETE;
4002 PORT_Free(pqgParam.prime.data);
4003 PORT_Free(pqgParam.subPrime.data);
4004 PORT_Free(pqgParam.base.data);
4008 /* Generate the key */
4009 rv = DSA_NewKey(&pqgParam, &dsaPriv);
4011 PORT_Free(pqgParam.prime.data);
4012 PORT_Free(pqgParam.subPrime.data);
4013 PORT_Free(pqgParam.base.data);
4015 if (rv != SECSuccess) {
4016 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4017 sftk_fatalError = PR_TRUE;
4019 crv = sftk_MapCryptError(PORT_GetError());
4023 /* store the generated key into the attributes */
4024 crv = sftk_AddAttributeType(publicKey,CKA_VALUE,
4025 sftk_item_expand(&dsaPriv->publicValue));
4026 if (crv != CKR_OK) goto dsagn_done;
4028 /* now fill in the RSA dependent paramenters in the private key */
4029 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
4030 sftk_item_expand(&dsaPriv->publicValue));
4031 if (crv != CKR_OK) goto dsagn_done;
4032 crv = sftk_AddAttributeType(privateKey,CKA_VALUE,
4033 sftk_item_expand(&dsaPriv->privateValue));
4036 /* should zeroize, since this function doesn't. */
4037 PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
4040 case CKM_DH_PKCS_KEY_PAIR_GEN:
4041 sftk_DeleteAttributeType(privateKey,CKA_PRIME);
4042 sftk_DeleteAttributeType(privateKey,CKA_BASE);
4043 sftk_DeleteAttributeType(privateKey,CKA_VALUE);
4044 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
4047 /* extract the necessary parameters and copy them to private keys */
4048 crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey,
4050 if (crv != CKR_OK) break;
4051 crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
4052 if (crv != CKR_OK) {
4053 PORT_Free(dhParam.prime.data);
4056 crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
4057 sftk_item_expand(&dhParam.prime));
4058 if (crv != CKR_OK) {
4059 PORT_Free(dhParam.prime.data);
4060 PORT_Free(dhParam.base.data);
4063 crv = sftk_AddAttributeType(privateKey, CKA_BASE,
4064 sftk_item_expand(&dhParam.base));
4065 if (crv != CKR_OK) {
4066 PORT_Free(dhParam.prime.data);
4067 PORT_Free(dhParam.base.data);
4070 bitSize = sftk_GetLengthInBits(dhParam.prime.data,dhParam.prime.len);
4071 if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) {
4072 crv = CKR_TEMPLATE_INCOMPLETE;
4073 PORT_Free(dhParam.prime.data);
4074 PORT_Free(dhParam.base.data);
4077 bitSize = sftk_GetLengthInBits(dhParam.base.data,dhParam.base.len);
4078 if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) {
4079 crv = CKR_TEMPLATE_INCOMPLETE;
4080 PORT_Free(dhParam.prime.data);
4081 PORT_Free(dhParam.base.data);
4085 rv = DH_NewKey(&dhParam, &dhPriv);
4086 PORT_Free(dhParam.prime.data);
4087 PORT_Free(dhParam.base.data);
4088 if (rv != SECSuccess) {
4089 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4090 sftk_fatalError = PR_TRUE;
4092 crv = sftk_MapCryptError(PORT_GetError());
4096 crv=sftk_AddAttributeType(publicKey, CKA_VALUE,
4097 sftk_item_expand(&dhPriv->publicValue));
4098 if (crv != CKR_OK) goto dhgn_done;
4100 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
4101 sftk_item_expand(&dhPriv->publicValue));
4102 if (crv != CKR_OK) goto dhgn_done;
4104 crv=sftk_AddAttributeType(privateKey, CKA_VALUE,
4105 sftk_item_expand(&dhPriv->privateValue));
4108 /* should zeroize, since this function doesn't. */
4109 PORT_FreeArena(dhPriv->arena, PR_TRUE);
4112 #ifdef NSS_ENABLE_ECC
4113 case CKM_EC_KEY_PAIR_GEN:
4114 sftk_DeleteAttributeType(privateKey,CKA_EC_PARAMS);
4115 sftk_DeleteAttributeType(privateKey,CKA_VALUE);
4116 sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
4119 /* extract the necessary parameters and copy them to private keys */
4120 crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
4122 if (crv != CKR_OK) break;
4124 crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
4125 sftk_item_expand(&ecEncodedParams));
4126 if (crv != CKR_OK) {
4127 PORT_Free(ecEncodedParams.data);
4131 /* Decode ec params before calling EC_NewKey */
4132 rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
4133 PORT_Free(ecEncodedParams.data);
4134 if (rv != SECSuccess) {
4135 crv = sftk_MapCryptError(PORT_GetError());
4138 rv = EC_NewKey(ecParams, &ecPriv);
4139 PORT_FreeArena(ecParams->arena, PR_TRUE);
4140 if (rv != SECSuccess) {
4141 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4142 sftk_fatalError = PR_TRUE;
4144 crv = sftk_MapCryptError(PORT_GetError());
4148 if (getenv("NSS_USE_DECODED_CKA_EC_POINT")) {
4149 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
4150 sftk_item_expand(&ecPriv->publicValue));
4152 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
4153 &ecPriv->publicValue,
4154 SEC_ASN1_GET(SEC_OctetStringTemplate));
4156 crv = CKR_ARGUMENTS_BAD;
4159 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
4160 sftk_item_expand(pubValue));
4161 SECITEM_FreeItem(pubValue, PR_TRUE);
4163 if (crv != CKR_OK) goto ecgn_done;
4165 crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
4166 sftk_item_expand(&ecPriv->privateValue));
4167 if (crv != CKR_OK) goto ecgn_done;
4169 crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
4170 sftk_item_expand(&ecPriv->publicValue));
4172 /* should zeroize, since this function doesn't. */
4173 PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
4175 #endif /* NSS_ENABLE_ECC */
4178 crv = CKR_MECHANISM_INVALID;
4181 if (crv != CKR_OK) {
4182 sftk_FreeObject(privateKey);
4183 sftk_FreeObject(publicKey);
4188 /* Add the class, key_type The loop lets us check errors blow out
4189 * on errors and clean up at the bottom */
4190 session = NULL; /* make pedtantic happy... session cannot leave the*/
4191 /* loop below NULL unless an error is set... */
4193 crv = sftk_AddAttributeType(privateKey,CKA_CLASS,&privClass,
4194 sizeof(CK_OBJECT_CLASS));
4195 if (crv != CKR_OK) break;
4196 crv = sftk_AddAttributeType(publicKey,CKA_CLASS,&pubClass,
4197 sizeof(CK_OBJECT_CLASS));
4198 if (crv != CKR_OK) break;
4199 crv = sftk_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type,
4200 sizeof(CK_KEY_TYPE));
4201 if (crv != CKR_OK) break;
4202 crv = sftk_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type,
4203 sizeof(CK_KEY_TYPE));
4204 if (crv != CKR_OK) break;
4205 session = sftk_SessionFromHandle(hSession);
4206 if (session == NULL) crv = CKR_SESSION_HANDLE_INVALID;
4209 if (crv != CKR_OK) {
4210 sftk_FreeObject(privateKey);
4211 sftk_FreeObject(publicKey);
4216 * handle the base object cleanup for the public Key
4218 crv = sftk_handleObject(privateKey,session);
4219 if (crv != CKR_OK) {
4220 sftk_FreeSession(session);
4221 sftk_FreeObject(privateKey);
4222 sftk_FreeObject(publicKey);
4227 * handle the base object cleanup for the private Key
4228 * If we have any problems, we destroy the public Key we've
4229 * created and linked.
4231 crv = sftk_handleObject(publicKey,session);
4232 sftk_FreeSession(session);
4233 if (crv != CKR_OK) {
4234 sftk_FreeObject(publicKey);
4235 NSC_DestroyObject(hSession,privateKey->handle);
4236 sftk_FreeObject(privateKey);
4239 if (sftk_isTrue(privateKey,CKA_SENSITIVE)) {
4240 sftk_forceAttribute(privateKey,CKA_ALWAYS_SENSITIVE,
4241 &cktrue,sizeof(CK_BBOOL));
4243 if (sftk_isTrue(publicKey,CKA_SENSITIVE)) {
4244 sftk_forceAttribute(publicKey,CKA_ALWAYS_SENSITIVE,
4245 &cktrue,sizeof(CK_BBOOL));
4247 if (!sftk_isTrue(privateKey,CKA_EXTRACTABLE)) {
4248 sftk_forceAttribute(privateKey,CKA_NEVER_EXTRACTABLE,
4249 &cktrue,sizeof(CK_BBOOL));
4251 if (!sftk_isTrue(publicKey,CKA_EXTRACTABLE)) {
4252 sftk_forceAttribute(publicKey,CKA_NEVER_EXTRACTABLE,
4253 &cktrue,sizeof(CK_BBOOL));
4256 /* Perform FIPS 140-2 pairwise consistency check. */
4257 crv = sftk_PairwiseConsistencyCheck(hSession,
4258 publicKey, privateKey, key_type);
4259 if (crv != CKR_OK) {
4260 NSC_DestroyObject(hSession,publicKey->handle);
4261 sftk_FreeObject(publicKey);
4262 NSC_DestroyObject(hSession,privateKey->handle);
4263 sftk_FreeObject(privateKey);
4264 if (sftk_audit_enabled) {
4266 PR_snprintf(msg,sizeof msg,
4267 "C_GenerateKeyPair(hSession=0x%08lX, "
4268 "pMechanism->mechanism=0x%08lX)=0x%08lX "
4269 "self-test: pair-wise consistency test failed",
4270 (PRUint32)hSession,(PRUint32)pMechanism->mechanism,
4272 sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg);
4277 *phPrivateKey = privateKey->handle;
4278 *phPublicKey = publicKey->handle;
4279 sftk_FreeObject(publicKey);
4280 sftk_FreeObject(privateKey);
4285 static SECItem *sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp)
4287 NSSLOWKEYPrivateKey *lk = NULL;
4288 NSSLOWKEYPrivateKeyInfo *pki = NULL;
4289 SFTKAttribute *attribute = NULL;
4290 PLArenaPool *arena = NULL;
4291 SECOidTag algorithm = SEC_OID_UNKNOWN;
4292 void *dummy, *param = NULL;
4293 SECStatus rv = SECSuccess;
4294 SECItem *encodedKey = NULL;
4295 #ifdef NSS_ENABLE_ECC
4301 *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */
4305 attribute = sftk_FindAttribute(key, CKA_KEY_TYPE);
4307 *crvp = CKR_KEY_TYPE_INCONSISTENT;
4311 lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp);
4312 sftk_FreeAttribute(attribute);
4317 arena = PORT_NewArena(2048); /* XXX different size? */
4319 *crvp = CKR_HOST_MEMORY;
4324 pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
4325 sizeof(NSSLOWKEYPrivateKeyInfo));
4327 *crvp = CKR_HOST_MEMORY;
4334 switch(lk->keyType) {
4335 case NSSLOWKEYRSAKey:
4336 prepare_low_rsa_priv_key_for_asn1(lk);
4337 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
4338 nsslowkey_RSAPrivateKeyTemplate);
4339 algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
4341 case NSSLOWKEYDSAKey:
4342 prepare_low_dsa_priv_key_export_for_asn1(lk);
4343 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
4344 nsslowkey_DSAPrivateKeyExportTemplate);
4345 prepare_low_pqg_params_for_asn1(&lk->u.dsa.params);
4346 param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
4347 nsslowkey_PQGParamsTemplate);
4348 algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
4350 #ifdef NSS_ENABLE_ECC
4351 case NSSLOWKEYECKey:
4352 prepare_low_ec_priv_key_for_asn1(lk);
4353 /* Public value is encoded as a bit string so adjust length
4354 * to be in bits before ASN encoding and readjust
4355 * immediately after.
4357 * Since the SECG specification recommends not including the
4358 * parameters as part of ECPrivateKey, we zero out the curveOID
4359 * length before encoding and restore it later.
4361 lk->u.ec.publicValue.len <<= 3;
4362 savelen = lk->u.ec.ecParams.curveOID.len;
4363 lk->u.ec.ecParams.curveOID.len = 0;
4364 dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
4365 nsslowkey_ECPrivateKeyTemplate);
4366 lk->u.ec.ecParams.curveOID.len = savelen;
4367 lk->u.ec.publicValue.len >>= 3;
4369 fordebug = &pki->privateKey;
4370 SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType,
4373 param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding);
4375 algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
4377 #endif /* NSS_ENABLE_ECC */
4378 case NSSLOWKEYDHKey:
4384 if(!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) {
4385 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
4390 rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm,
4392 if(rv != SECSuccess) {
4393 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
4398 dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
4399 NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
4401 *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
4406 encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
4407 nsslowkey_PrivateKeyInfoTemplate);
4408 *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR;
4410 #ifdef NSS_ENABLE_ECC
4411 fordebug = encodedKey;
4412 SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType,
4417 PORT_FreeArena(arena, PR_TRUE);
4420 if(lk && (lk != key->objectInfo)) {
4421 nsslowkey_DestroyPrivateKey(lk);
4425 SECITEM_ZfreeItem((SECItem*)param, PR_TRUE);
4428 if(rv != SECSuccess) {
4435 /* it doesn't matter yet, since we colapse error conditions in the
4436 * level above, but we really should map those few key error differences */
4438 sftk_mapWrap(CK_RV crv)
4441 case CKR_ENCRYPTED_DATA_INVALID: crv = CKR_WRAPPED_KEY_INVALID; break;
4446 /* NSC_WrapKey wraps (i.e., encrypts) a key. */
4447 CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession,
4448 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
4449 CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
4450 CK_ULONG_PTR pulWrappedKeyLen)
4452 SFTKSession *session;
4453 SFTKAttribute *attribute;
4459 session = sftk_SessionFromHandle(hSession);
4460 if (session == NULL) {
4461 return CKR_SESSION_HANDLE_INVALID;
4464 key = sftk_ObjectFromHandle(hKey,session);
4465 sftk_FreeSession(session);
4467 return CKR_KEY_HANDLE_INVALID;
4470 switch(key->objclass) {
4471 case CKO_SECRET_KEY:
4473 SFTKSessionContext *context = NULL;
4476 attribute = sftk_FindAttribute(key,CKA_VALUE);
4478 if (attribute == NULL) {
4479 crv = CKR_KEY_TYPE_INCONSISTENT;
4482 crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
4483 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
4484 if (crv != CKR_OK) {
4485 sftk_FreeAttribute(attribute);
4489 pText.type = siBuffer;
4490 pText.data = (unsigned char *)attribute->attrib.pValue;
4491 pText.len = attribute->attrib.ulValueLen;
4493 /* Find out if this is a block cipher. */
4494 crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,NULL);
4495 if (crv != CKR_OK || !context)
4497 if (context->blockSize > 1) {
4498 unsigned int remainder = pText.len % context->blockSize;
4499 if (!context->doPad && remainder) {
4500 /* When wrapping secret keys with unpadded block ciphers,
4501 ** the keys are zero padded, if necessary, to fill out
4504 pText.len += context->blockSize - remainder;
4505 pText.data = PORT_ZAlloc(pText.len);
4507 memcpy(pText.data, attribute->attrib.pValue,
4508 attribute->attrib.ulValueLen);
4510 crv = CKR_HOST_MEMORY;
4516 crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data,
4517 pText.len, pWrappedKey, pulWrappedKeyLen);
4518 /* always force a finalize, both on errors and when
4519 * we are just getting the size */
4520 if (crv != CKR_OK || pWrappedKey == NULL) {
4522 lcrv = sftk_GetContext(hSession,&context,
4523 SFTK_ENCRYPT,PR_FALSE,NULL);
4524 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
4525 if (lcrv == CKR_OK && context) {
4526 sftk_FreeContext(context);
4530 if (pText.data != (unsigned char *)attribute->attrib.pValue)
4531 PORT_ZFree(pText.data, pText.len);
4532 sftk_FreeAttribute(attribute);
4536 case CKO_PRIVATE_KEY:
4538 SECItem *bpki = sftk_PackagePrivateKey(key, &crv);
4539 SFTKSessionContext *context = NULL;
4545 crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
4546 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
4548 SECITEM_ZfreeItem(bpki, PR_TRUE);
4549 crv = CKR_KEY_TYPE_INCONSISTENT;
4553 crv = NSC_Encrypt(hSession, bpki->data, bpki->len,
4554 pWrappedKey, pulWrappedKeyLen);
4555 /* always force a finalize */
4556 if (crv != CKR_OK || pWrappedKey == NULL) {
4558 lcrv = sftk_GetContext(hSession,&context,
4559 SFTK_ENCRYPT,PR_FALSE,NULL);
4560 sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
4561 if (lcrv == CKR_OK && context) {
4562 sftk_FreeContext(context);
4565 SECITEM_ZfreeItem(bpki, PR_TRUE);
4570 crv = CKR_KEY_TYPE_INCONSISTENT;
4573 sftk_FreeObject(key);
4575 return sftk_mapWrap(crv);
4579 * import a pprivate key info into the desired slot
4582 sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
4584 CK_BBOOL cktrue = CK_TRUE;
4585 CK_KEY_TYPE keyType = CKK_RSA;
4586 SECStatus rv = SECFailure;
4587 const SEC_ASN1Template *keyTemplate, *paramTemplate;
4588 void *paramDest = NULL;
4590 NSSLOWKEYPrivateKey *lpk = NULL;
4591 NSSLOWKEYPrivateKeyInfo *pki = NULL;
4592 CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
4594 arena = PORT_NewArena(2048);
4599 pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
4600 sizeof(NSSLOWKEYPrivateKeyInfo));
4602 PORT_FreeArena(arena, PR_FALSE);
4606 if(SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki)
4608 PORT_FreeArena(arena, PR_TRUE);
4612 lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena,
4613 sizeof(NSSLOWKEYPrivateKey));
4619 switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
4620 case SEC_OID_PKCS1_RSA_ENCRYPTION:
4621 keyTemplate = nsslowkey_RSAPrivateKeyTemplate;
4622 paramTemplate = NULL;
4624 lpk->keyType = NSSLOWKEYRSAKey;
4625 prepare_low_rsa_priv_key_for_asn1(lpk);
4627 case SEC_OID_ANSIX9_DSA_SIGNATURE:
4628 keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate;
4629 paramTemplate = nsslowkey_PQGParamsTemplate;
4630 paramDest = &(lpk->u.dsa.params);
4631 lpk->keyType = NSSLOWKEYDSAKey;
4632 prepare_low_dsa_priv_key_export_for_asn1(lpk);
4633 prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params);
4635 /* case NSSLOWKEYDHKey: */
4636 #ifdef NSS_ENABLE_ECC
4637 case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
4638 keyTemplate = nsslowkey_ECPrivateKeyTemplate;
4639 paramTemplate = NULL;
4640 paramDest = &(lpk->u.ec.ecParams.DEREncoding);
4641 lpk->keyType = NSSLOWKEYECKey;
4642 prepare_low_ec_priv_key_for_asn1(lpk);
4643 prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams);
4645 #endif /* NSS_ENABLE_ECC */
4648 paramTemplate = NULL;
4657 /* decode the private key and any algorithm parameters */
4658 rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
4660 #ifdef NSS_ENABLE_ECC
4661 if (lpk->keyType == NSSLOWKEYECKey) {
4662 /* convert length in bits to length in bytes */
4663 lpk->u.ec.publicValue.len >>= 3;
4664 rv = SECITEM_CopyItem(arena,
4665 &(lpk->u.ec.ecParams.DEREncoding),
4666 &(pki->algorithm.parameters));
4667 if(rv != SECSuccess) {
4671 #endif /* NSS_ENABLE_ECC */
4673 if(rv != SECSuccess) {
4676 if(paramDest && paramTemplate) {
4677 rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate,
4678 &(pki->algorithm.parameters));
4679 if(rv != SECSuccess) {
4686 switch (lpk->keyType) {
4687 case NSSLOWKEYRSAKey:
4689 if(sftk_hasAttribute(key, CKA_NETSCAPE_DB)) {
4690 sftk_DeleteAttributeType(key, CKA_NETSCAPE_DB);
4692 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
4694 if(crv != CKR_OK) break;
4695 crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue,
4697 if(crv != CKR_OK) break;
4698 crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue,
4700 if(crv != CKR_OK) break;
4701 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
4703 if(crv != CKR_OK) break;
4704 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
4706 if(crv != CKR_OK) break;
4707 crv = sftk_AddAttributeType(key, CKA_MODULUS,
4708 sftk_item_expand(&lpk->u.rsa.modulus));
4709 if(crv != CKR_OK) break;
4710 crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT,
4711 sftk_item_expand(&lpk->u.rsa.publicExponent));
4712 if(crv != CKR_OK) break;
4713 crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT,
4714 sftk_item_expand(&lpk->u.rsa.privateExponent));
4715 if(crv != CKR_OK) break;
4716 crv = sftk_AddAttributeType(key, CKA_PRIME_1,
4717 sftk_item_expand(&lpk->u.rsa.prime1));
4718 if(crv != CKR_OK) break;
4719 crv = sftk_AddAttributeType(key, CKA_PRIME_2,
4720 sftk_item_expand(&lpk->u.rsa.prime2));
4721 if(crv != CKR_OK) break;
4722 crv = sftk_AddAttributeType(key, CKA_EXPONENT_1,
4723 sftk_item_expand(&lpk->u.rsa.exponent1));
4724 if(crv != CKR_OK) break;
4725 crv = sftk_AddAttributeType(key, CKA_EXPONENT_2,
4726 sftk_item_expand(&lpk->u.rsa.exponent2));
4727 if(crv != CKR_OK) break;
4728 crv = sftk_AddAttributeType(key, CKA_COEFFICIENT,
4729 sftk_item_expand(&lpk->u.rsa.coefficient));
4731 case NSSLOWKEYDSAKey:
4733 crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK :
4734 CKR_KEY_TYPE_INCONSISTENT;
4735 if(crv != CKR_OK) break;
4736 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
4738 if(crv != CKR_OK) break;
4739 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
4741 if(crv != CKR_OK) break;
4742 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
4744 if(crv != CKR_OK) break;
4745 crv = sftk_AddAttributeType(key, CKA_PRIME,
4746 sftk_item_expand(&lpk->u.dsa.params.prime));
4747 if(crv != CKR_OK) break;
4748 crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
4749 sftk_item_expand(&lpk->u.dsa.params.subPrime));
4750 if(crv != CKR_OK) break;
4751 crv = sftk_AddAttributeType(key, CKA_BASE,
4752 sftk_item_expand(&lpk->u.dsa.params.base));
4753 if(crv != CKR_OK) break;
4754 crv = sftk_AddAttributeType(key, CKA_VALUE,
4755 sftk_item_expand(&lpk->u.dsa.privateValue));
4756 if(crv != CKR_OK) break;
4759 case NSSLOWKEYDHKey:
4760 template = dhTemplate;
4761 templateCount = sizeof(dhTemplate)/sizeof(CK_ATTRIBUTE);
4765 /* what about fortezza??? */
4766 #ifdef NSS_ENABLE_ECC
4767 case NSSLOWKEYECKey:
4769 crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK :
4770 CKR_KEY_TYPE_INCONSISTENT;
4771 if(crv != CKR_OK) break;
4772 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
4774 if(crv != CKR_OK) break;
4775 crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
4777 if(crv != CKR_OK) break;
4778 crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
4780 if(crv != CKR_OK) break;
4781 crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue,
4783 if(crv != CKR_OK) break;
4784 crv = sftk_AddAttributeType(key, CKA_EC_PARAMS,
4785 sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding));
4786 if(crv != CKR_OK) break;
4787 crv = sftk_AddAttributeType(key, CKA_VALUE,
4788 sftk_item_expand(&lpk->u.ec.privateValue));
4789 if(crv != CKR_OK) break;
4790 /* XXX Do we need to decode the EC Params here ?? */
4792 #endif /* NSS_ENABLE_ECC */
4794 crv = CKR_KEY_TYPE_INCONSISTENT;
4800 nsslowkey_DestroyPrivateKey(lpk);
4811 /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
4812 CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
4813 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
4814 CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
4815 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
4816 CK_OBJECT_HANDLE_PTR phKey)
4818 SFTKObject *key = NULL;
4819 SFTKSession *session;
4820 CK_ULONG key_length = 0;
4821 unsigned char * buf = NULL;
4824 CK_ULONG bsize = ulWrappedKeyLen;
4825 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
4827 CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
4832 return CKR_SESSION_HANDLE_INVALID;
4835 * now lets create an object to hang the attributes off of
4837 key = sftk_NewObject(slot); /* fill in the handle later */
4839 return CKR_HOST_MEMORY;
4843 * load the template values into the object
4845 for (i=0; i < (int) ulAttributeCount; i++) {
4846 if (pTemplate[i].type == CKA_VALUE_LEN) {
4847 key_length = *(CK_ULONG *)pTemplate[i].pValue;
4850 if (pTemplate[i].type == CKA_CLASS) {
4851 target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
4853 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i]));
4854 if (crv != CKR_OK) break;
4856 if (crv != CKR_OK) {
4857 sftk_FreeObject(key);
4861 crv = sftk_CryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP,
4862 CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE);
4863 if (crv != CKR_OK) {
4864 sftk_FreeObject(key);
4865 return sftk_mapWrap(crv);
4868 /* allocate the buffer to decrypt into
4869 * this assumes the unwrapped key is never larger than the
4870 * wrapped key. For all the mechanisms we support this is true */
4871 buf = (unsigned char *)PORT_Alloc( ulWrappedKeyLen);
4872 bsize = ulWrappedKeyLen;
4874 crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
4875 if (crv != CKR_OK) {
4876 sftk_FreeObject(key);
4878 return sftk_mapWrap(crv);
4881 switch(target_type) {
4882 case CKO_SECRET_KEY:
4883 if (!sftk_hasAttribute(key,CKA_KEY_TYPE)) {
4884 crv = CKR_TEMPLATE_INCOMPLETE;
4888 if (key_length == 0 || key_length > bsize) {
4891 if (key_length > MAX_KEY_LEN) {
4892 crv = CKR_TEMPLATE_INCONSISTENT;
4897 crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length);
4899 case CKO_PRIVATE_KEY:
4900 bpki.data = (unsigned char *)buf;
4903 if(sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) {
4904 crv = CKR_TEMPLATE_INCOMPLETE;
4908 crv = CKR_TEMPLATE_INCONSISTENT;
4912 PORT_ZFree(buf, bsize);
4913 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
4915 /* get the session */
4916 session = sftk_SessionFromHandle(hSession);
4917 if (session == NULL) {
4918 sftk_FreeObject(key);
4919 return CKR_SESSION_HANDLE_INVALID;
4923 * handle the base object stuff
4925 crv = sftk_handleObject(key,session);
4926 *phKey = key->handle;
4927 sftk_FreeSession(session);
4928 sftk_FreeObject(key);
4935 * The SSL key gen mechanism create's lots of keys. This function handles the
4936 * details of each of these key creation.
4939 sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey,
4940 PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
4941 CK_OBJECT_HANDLE *keyHandle)
4944 SFTKSession *session;
4945 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
4946 CK_BBOOL cktrue = CK_TRUE;
4947 CK_BBOOL ckfalse = CK_FALSE;
4948 CK_RV crv = CKR_HOST_MEMORY;
4951 * now lets create an object to hang the attributes off of
4953 *keyHandle = CK_INVALID_HANDLE;
4954 key = sftk_NewObject(baseKey->slot);
4955 if (key == NULL) return CKR_HOST_MEMORY;
4956 sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE;
4958 crv = sftk_CopyObject(key,baseKey);
4959 if (crv != CKR_OK) goto loser;
4961 crv = sftk_forceAttribute(key,CKA_KEY_TYPE,&keyType,sizeof(keyType));
4962 if (crv != CKR_OK) goto loser;
4963 crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
4964 if (crv != CKR_OK) goto loser;
4965 crv = sftk_forceAttribute(key,CKA_ENCRYPT,&ckfalse,sizeof(CK_BBOOL));
4966 if (crv != CKR_OK) goto loser;
4967 crv = sftk_forceAttribute(key,CKA_DECRYPT,&ckfalse,sizeof(CK_BBOOL));
4968 if (crv != CKR_OK) goto loser;
4969 crv = sftk_forceAttribute(key,CKA_SIGN,&cktrue,sizeof(CK_BBOOL));
4970 if (crv != CKR_OK) goto loser;
4971 crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
4972 if (crv != CKR_OK) goto loser;
4973 crv = sftk_forceAttribute(key,CKA_WRAP,&ckfalse,sizeof(CK_BBOOL));
4974 if (crv != CKR_OK) goto loser;
4975 crv = sftk_forceAttribute(key,CKA_UNWRAP,&ckfalse,sizeof(CK_BBOOL));
4976 if (crv != CKR_OK) goto loser;
4978 crv = sftk_forceAttribute(key,CKA_VALUE,keyBlock,keySize);
4979 if (crv != CKR_OK) goto loser;
4981 /* get the session */
4982 crv = CKR_HOST_MEMORY;
4983 session = sftk_SessionFromHandle(hSession);
4984 if (session == NULL) { goto loser; }
4986 crv = sftk_handleObject(key,session);
4987 sftk_FreeSession(session);
4988 *keyHandle = key->handle;
4990 if (key) sftk_FreeObject(key);
4995 * if there is an error, we need to free the keys we already created in SSL
4996 * This is the routine that will do it..
4999 sftk_freeSSLKeys(CK_SESSION_HANDLE session,
5000 CK_SSL3_KEY_MAT_OUT *returnedMaterial )
5002 if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) {
5003 NSC_DestroyObject(session,returnedMaterial->hClientMacSecret);
5005 if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) {
5006 NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
5008 if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) {
5009 NSC_DestroyObject(session, returnedMaterial->hClientKey);
5011 if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) {
5012 NSC_DestroyObject(session, returnedMaterial->hServerKey);
5017 * when deriving from sensitive and extractable keys, we need to preserve some
5018 * of the semantics in the derived key. This helper routine maintains these
5022 sftk_DeriveSensitiveCheck(SFTKObject *baseKey,SFTKObject *destKey)
5024 PRBool hasSensitive;
5025 PRBool sensitive = PR_FALSE;
5026 PRBool hasExtractable;
5027 PRBool extractable = PR_TRUE;
5031 hasSensitive = PR_FALSE;
5032 att = sftk_FindAttribute(destKey,CKA_SENSITIVE);
5034 hasSensitive = PR_TRUE;
5035 sensitive = (PRBool) *(CK_BBOOL *)att->attrib.pValue;
5036 sftk_FreeAttribute(att);
5039 hasExtractable = PR_FALSE;
5040 att = sftk_FindAttribute(destKey,CKA_EXTRACTABLE);
5042 hasExtractable = PR_TRUE;
5043 extractable = (PRBool) *(CK_BBOOL *)att->attrib.pValue;
5044 sftk_FreeAttribute(att);
5048 /* don't make a key more accessible */
5049 if (sftk_isTrue(baseKey,CKA_SENSITIVE) && hasSensitive &&
5050 (sensitive == PR_FALSE)) {
5051 return CKR_KEY_FUNCTION_NOT_PERMITTED;
5053 if (!sftk_isTrue(baseKey,CKA_EXTRACTABLE) && hasExtractable &&
5054 (extractable == PR_TRUE)) {
5055 return CKR_KEY_FUNCTION_NOT_PERMITTED;
5058 /* inherit parent's sensitivity */
5059 if (!hasSensitive) {
5060 att = sftk_FindAttribute(baseKey,CKA_SENSITIVE);
5061 if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT;
5062 crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib));
5063 sftk_FreeAttribute(att);
5064 if (crv != CKR_OK) return crv;
5066 if (!hasExtractable) {
5067 att = sftk_FindAttribute(baseKey,CKA_EXTRACTABLE);
5068 if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT;
5069 crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib));
5070 sftk_FreeAttribute(att);
5071 if (crv != CKR_OK) return crv;
5074 /* we should inherit the parent's always extractable/ never sensitive info,
5075 * but handleObject always forces this attributes, so we would need to do
5076 * something special. */
5081 * make known fixed PKCS #11 key types to their sizes in bytes
5084 sftk_MapKeySize(CK_KEY_TYPE keyType)
5095 /* IDEA and CAST need to be added */
5103 * SSL Key generation given pre master secret
5105 #define NUM_MIXERS 9
5106 static const char * const mixers[NUM_MIXERS] = {
5116 #define SSL3_PMS_LENGTH 48
5117 #define SSL3_MASTER_SECRET_LENGTH 48
5118 #define SSL3_RANDOM_LENGTH 32
5121 /* NSC_DeriveKey derives a key from a base key, creating a new key object. */
5122 CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
5123 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
5124 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
5125 CK_OBJECT_HANDLE_PTR phKey)
5127 SFTKSession * session;
5128 SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession);
5130 SFTKObject * sourceKey;
5131 SFTKAttribute * att = NULL;
5132 SFTKAttribute * att2 = NULL;
5133 unsigned char * buf;
5138 CK_ULONG tmpKeySize;
5140 CK_ULONG keySize = 0;
5142 CK_BBOOL cktrue = CK_TRUE;
5143 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
5144 CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
5145 CK_KEY_DERIVATION_STRING_DATA *stringPtr;
5146 PRBool isTLS = PR_FALSE;
5147 PRBool isDH = PR_FALSE;
5150 unsigned int outLen;
5151 unsigned char sha_out[SHA1_LENGTH];
5152 unsigned char key_block[NUM_MIXERS * MD5_LENGTH];
5153 unsigned char key_block2[MD5_LENGTH];
5155 HASH_HashType hashType;
5156 PRBool extractValue = PR_TRUE;
5161 return CKR_SESSION_HANDLE_INVALID;
5164 * now lets create an object to hang the attributes off of
5166 if (phKey) *phKey = CK_INVALID_HANDLE;
5168 key = sftk_NewObject(slot); /* fill in the handle later */
5170 return CKR_HOST_MEMORY;
5172 isFIPS = (slot->slotID == FIPS_SLOT_ID);
5175 * load the template values into the object
5177 for (i=0; i < (int) ulAttributeCount; i++) {
5178 crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i]));
5179 if (crv != CKR_OK) break;
5181 if (pTemplate[i].type == CKA_KEY_TYPE) {
5182 keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
5184 if (pTemplate[i].type == CKA_VALUE_LEN) {
5185 keySize = *(CK_ULONG *)pTemplate[i].pValue;
5188 if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
5191 keySize = sftk_MapKeySize(keyType);
5194 switch (pMechanism->mechanism) {
5195 case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */
5196 case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */
5197 case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */
5198 case CKM_NSS_JPAKE_ROUND2_SHA512:
5199 extractValue = PR_FALSE;
5200 classType = CKO_PRIVATE_KEY;
5202 case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */
5203 case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
5204 case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
5205 case CKM_NSS_JPAKE_FINAL_SHA512:
5206 extractValue = PR_FALSE;
5209 classType = CKO_SECRET_KEY;
5212 crv = sftk_forceAttribute (key,CKA_CLASS,&classType,sizeof(classType));
5213 if (crv != CKR_OK) {
5214 sftk_FreeObject(key);
5218 /* look up the base key we're deriving with */
5219 session = sftk_SessionFromHandle(hSession);
5220 if (session == NULL) {
5221 sftk_FreeObject(key);
5222 return CKR_SESSION_HANDLE_INVALID;
5225 sourceKey = sftk_ObjectFromHandle(hBaseKey,session);
5226 sftk_FreeSession(session);
5227 if (sourceKey == NULL) {
5228 sftk_FreeObject(key);
5229 return CKR_KEY_HANDLE_INVALID;
5233 /* get the value of the base key */
5234 att = sftk_FindAttribute(sourceKey,CKA_VALUE);
5236 sftk_FreeObject(key);
5237 sftk_FreeObject(sourceKey);
5238 return CKR_KEY_HANDLE_INVALID;
5242 switch (pMechanism->mechanism) {
5244 * generate the master secret
5246 case CKM_TLS_MASTER_KEY_DERIVE:
5247 case CKM_TLS_MASTER_KEY_DERIVE_DH:
5250 case CKM_SSL3_MASTER_KEY_DERIVE:
5251 case CKM_SSL3_MASTER_KEY_DERIVE_DH:
5253 CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
5254 SSL3RSAPreMasterSecret * rsa_pms;
5255 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
5257 if ((pMechanism->mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) ||
5258 (pMechanism->mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH))
5261 /* first do the consistancy checks */
5262 if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
5263 crv = CKR_KEY_TYPE_INCONSISTENT;
5266 att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE);
5267 if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
5268 CKK_GENERIC_SECRET)) {
5269 if (att2) sftk_FreeAttribute(att2);
5270 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5273 sftk_FreeAttribute(att2);
5274 if (keyType != CKK_GENERIC_SECRET) {
5275 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5278 if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
5279 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5283 /* finally do the key gen */
5284 ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
5285 pMechanism->pParameter;
5287 PORT_Memcpy(crsrdata,
5288 ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
5289 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
5290 ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
5292 if (ssl3_master->pVersion) {
5293 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
5294 rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue;
5295 /* don't leak more key material then necessary for SSL to work */
5296 if ((sessKey == NULL) || sessKey->wasDerived) {
5297 ssl3_master->pVersion->major = 0xff;
5298 ssl3_master->pVersion->minor = 0xff;
5300 ssl3_master->pVersion->major = rsa_pms->client_version[0];
5301 ssl3_master->pVersion->minor = rsa_pms->client_version[1];
5304 if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
5305 crv = CKR_MECHANISM_PARAM_INVALID;
5308 if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
5309 crv = CKR_MECHANISM_PARAM_INVALID;
5315 SECItem crsr = { siBuffer, NULL, 0 };
5316 SECItem master = { siBuffer, NULL, 0 };
5317 SECItem pms = { siBuffer, NULL, 0 };
5319 crsr.data = crsrdata;
5320 crsr.len = sizeof crsrdata;
5321 master.data = key_block;
5322 master.len = SSL3_MASTER_SECRET_LENGTH;
5323 pms.data = (unsigned char*)att->attrib.pValue;
5324 pms.len = att->attrib.ulValueLen;
5326 status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS);
5327 if (status != SECSuccess) {
5328 crv = CKR_FUNCTION_FAILED;
5332 /* now allocate the hash contexts */
5333 md5 = MD5_NewContext();
5335 crv = CKR_HOST_MEMORY;
5338 sha = SHA1_NewContext();
5341 crv = CKR_HOST_MEMORY;
5344 for (i = 0; i < 3; i++) {
5346 SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));
5347 SHA1_Update(sha, (const unsigned char*)att->attrib.pValue,
5348 att->attrib.ulValueLen);
5349 SHA1_Update(sha, crsrdata, sizeof crsrdata);
5350 SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
5351 PORT_Assert(outLen == SHA1_LENGTH);
5354 MD5_Update(md5, (const unsigned char*)att->attrib.pValue,
5355 att->attrib.ulValueLen);
5356 MD5_Update(md5, sha_out, outLen);
5357 MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);
5358 PORT_Assert(outLen == MD5_LENGTH);
5364 /* store the results */
5365 crv = sftk_forceAttribute
5366 (key,CKA_VALUE,key_block,SSL3_MASTER_SECRET_LENGTH);
5367 if (crv != CKR_OK) break;
5368 keyType = CKK_GENERIC_SECRET;
5369 crv = sftk_forceAttribute (key,CKA_KEY_TYPE,&keyType,sizeof(keyType));
5371 /* TLS's master secret is used to "sign" finished msgs with PRF. */
5372 /* XXX This seems like a hack. But SFTK_Derive only accepts
5373 * one "operation" argument. */
5374 crv = sftk_forceAttribute(key,CKA_SIGN, &cktrue,sizeof(CK_BBOOL));
5375 if (crv != CKR_OK) break;
5376 crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
5377 if (crv != CKR_OK) break;
5378 /* While we're here, we might as well force this, too. */
5379 crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
5380 if (crv != CKR_OK) break;
5385 case CKM_TLS_KEY_AND_MAC_DERIVE:
5388 case CKM_SSL3_KEY_AND_MAC_DERIVE:
5390 CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
5391 CK_SSL3_KEY_MAT_OUT * ssl3_keys_out;
5392 CK_ULONG effKeySize;
5393 unsigned int block_needed;
5394 unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
5395 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
5397 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5398 if (crv != CKR_OK) break;
5400 if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
5401 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5404 att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE);
5405 if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
5406 CKK_GENERIC_SECRET)) {
5407 if (att2) sftk_FreeAttribute(att2);
5408 crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
5411 sftk_FreeAttribute(att2);
5412 md5 = MD5_NewContext();
5414 crv = CKR_HOST_MEMORY;
5417 sha = SHA1_NewContext();
5420 crv = CKR_HOST_MEMORY;
5423 ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter;
5425 PORT_Memcpy(srcrdata,
5426 ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
5427 PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
5428 ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
5430 PORT_Memcpy(crsrdata,
5431 ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
5432 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
5433 ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
5436 * clear out our returned keys so we can recover on failure
5438 ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
5439 ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;
5440 ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;
5441 ssl3_keys_out->hClientKey = CK_INVALID_HANDLE;
5442 ssl3_keys_out->hServerKey = CK_INVALID_HANDLE;
5445 * How much key material do we need?
5447 macSize = ssl3_keys->ulMacSizeInBits/8;
5448 effKeySize = ssl3_keys->ulKeySizeInBits/8;
5449 IVSize = ssl3_keys->ulIVSizeInBits/8;
5451 effKeySize = keySize;
5453 block_needed = 2 * (macSize + effKeySize +
5454 ((!ssl3_keys->bIsExport) * IVSize));
5455 PORT_Assert(block_needed <= sizeof key_block);
5456 if (block_needed > sizeof key_block)
5457 block_needed = sizeof key_block;
5460 * generate the key material: This looks amazingly similar to the
5461 * PMS code, and is clearly crying out for a function to provide it.
5465 SECItem srcr = { siBuffer, NULL, 0 };
5466 SECItem keyblk = { siBuffer, NULL, 0 };
5467 SECItem master = { siBuffer, NULL, 0 };
5469 srcr.data = srcrdata;
5470 srcr.len = sizeof srcrdata;
5471 keyblk.data = key_block;
5472 keyblk.len = block_needed;
5473 master.data = (unsigned char*)att->attrib.pValue;
5474 master.len = att->attrib.ulValueLen;
5476 status = TLS_PRF(&master, "key expansion", &srcr, &keyblk,
5478 if (status != SECSuccess) {
5479 goto key_and_mac_derive_fail;
5482 unsigned int block_bytes = 0;
5484 * MD5(master_secret + SHA('A' + master_secret +
5485 * ServerHello.random + ClientHello.random)) +
5486 * MD5(master_secret + SHA('BB' + master_secret +
5487 * ServerHello.random + ClientHello.random)) +
5488 * MD5(master_secret + SHA('CCC' + master_secret +
5489 * ServerHello.random + ClientHello.random)) +
5492 for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) {
5494 SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));
5495 SHA1_Update(sha, (const unsigned char*)att->attrib.pValue,
5496 att->attrib.ulValueLen);
5497 SHA1_Update(sha, srcrdata, sizeof srcrdata);
5498 SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
5499 PORT_Assert(outLen == SHA1_LENGTH);
5501 MD5_Update(md5, (const unsigned char*)att->attrib.pValue,
5502 att->attrib.ulValueLen);
5503 MD5_Update(md5, sha_out, outLen);
5504 MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);
5505 PORT_Assert(outLen == MD5_LENGTH);
5506 block_bytes += outLen;
5511 * Put the key material where it goes.
5513 i = 0; /* now shows how much consumed */
5516 * The key_block is partitioned as follows:
5517 * client_write_MAC_secret[CipherSpec.hash_size]
5519 crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,
5520 &ssl3_keys_out->hClientMacSecret);
5522 goto key_and_mac_derive_fail;
5527 * server_write_MAC_secret[CipherSpec.hash_size]
5529 crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,
5530 &ssl3_keys_out->hServerMacSecret);
5531 if (crv != CKR_OK) {
5532 goto key_and_mac_derive_fail;
5537 if (!ssl3_keys->bIsExport) {
5539 ** Generate Domestic write keys and IVs.
5540 ** client_write_key[CipherSpec.key_material]
5542 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],
5543 keySize, &ssl3_keys_out->hClientKey);
5544 if (crv != CKR_OK) {
5545 goto key_and_mac_derive_fail;
5550 ** server_write_key[CipherSpec.key_material]
5552 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],
5553 keySize, &ssl3_keys_out->hServerKey);
5554 if (crv != CKR_OK) {
5555 goto key_and_mac_derive_fail;
5560 ** client_write_IV[CipherSpec.IV_size]
5563 PORT_Memcpy(ssl3_keys_out->pIVClient,
5564 &key_block[i], IVSize);
5569 ** server_write_IV[CipherSpec.IV_size]
5572 PORT_Memcpy(ssl3_keys_out->pIVServer,
5573 &key_block[i], IVSize);
5576 PORT_Assert(i <= sizeof key_block);
5578 } else if (!isTLS) {
5581 ** Generate SSL3 Export write keys and IVs.
5582 ** client_write_key[CipherSpec.key_material]
5583 ** final_client_write_key = MD5(client_write_key +
5584 ** ClientHello.random + ServerHello.random);
5587 MD5_Update(md5, &key_block[i], effKeySize);
5588 MD5_Update(md5, crsrdata, sizeof crsrdata);
5589 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
5591 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2,
5592 keySize,&ssl3_keys_out->hClientKey);
5593 if (crv != CKR_OK) {
5594 goto key_and_mac_derive_fail;
5598 ** server_write_key[CipherSpec.key_material]
5599 ** final_server_write_key = MD5(server_write_key +
5600 ** ServerHello.random + ClientHello.random);
5603 MD5_Update(md5, &key_block[i], effKeySize);
5604 MD5_Update(md5, srcrdata, sizeof srcrdata);
5605 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
5607 crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2,
5608 keySize,&ssl3_keys_out->hServerKey);
5609 if (crv != CKR_OK) {
5610 goto key_and_mac_derive_fail;
5614 ** client_write_IV =
5615 ** MD5(ClientHello.random + ServerHello.random);
5618 MD5_Update(md5, crsrdata, sizeof crsrdata);
5619 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
5620 PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize);
5623 ** server_write_IV =
5624 ** MD5(ServerHello.random + ClientHello.random);
5627 MD5_Update(md5, srcrdata, sizeof srcrdata);
5628 MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
5629 PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize);
5634 ** Generate TLS Export write keys and IVs.
5637 SECItem secret = { siBuffer, NULL, 0 };
5638 SECItem crsr = { siBuffer, NULL, 0 };
5639 SECItem keyblk = { siBuffer, NULL, 0 };
5642 ** client_write_key[CipherSpec.key_material]
5643 ** final_client_write_key = PRF(client_write_key,
5644 ** "client write key",
5645 ** client_random + server_random);
5647 secret.data = &key_block[i];
5648 secret.len = effKeySize;
5650 crsr.data = crsrdata;
5651 crsr.len = sizeof crsrdata;
5652 keyblk.data = key_block2;
5653 keyblk.len = sizeof key_block2;
5654 status = TLS_PRF(&secret, "client write key", &crsr, &keyblk,
5656 if (status != SECSuccess) {
5657 goto key_and_mac_derive_fail;
5659 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2,
5660 keySize, &ssl3_keys_out->hClientKey);
5661 if (crv != CKR_OK) {
5662 goto key_and_mac_derive_fail;
5666 ** server_write_key[CipherSpec.key_material]
5667 ** final_server_write_key = PRF(server_write_key,
5668 ** "server write key",
5669 ** client_random + server_random);
5671 secret.data = &key_block[i];
5672 secret.len = effKeySize;
5674 keyblk.data = key_block2;
5675 keyblk.len = sizeof key_block2;
5676 status = TLS_PRF(&secret, "server write key", &crsr, &keyblk,
5678 if (status != SECSuccess) {
5679 goto key_and_mac_derive_fail;
5681 crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2,
5682 keySize, &ssl3_keys_out->hServerKey);
5683 if (crv != CKR_OK) {
5684 goto key_and_mac_derive_fail;
5688 ** iv_block = PRF("", "IV block",
5689 ** client_random + server_random);
5690 ** client_write_IV[SecurityParameters.IV_size]
5691 ** server_write_IV[SecurityParameters.IV_size]
5696 keyblk.data = &key_block[i];
5697 keyblk.len = 2 * IVSize;
5698 status = TLS_PRF(&secret, "IV block", &crsr, &keyblk,
5700 if (status != SECSuccess) {
5701 goto key_and_mac_derive_fail;
5703 PORT_Memcpy(ssl3_keys_out->pIVClient, keyblk.data, IVSize);
5704 PORT_Memcpy(ssl3_keys_out->pIVServer, keyblk.data + IVSize,
5713 key_and_mac_derive_fail:
5715 crv = CKR_FUNCTION_FAILED;
5716 sftk_freeSSLKeys(hSession, ssl3_keys_out);
5718 MD5_DestroyContext(md5, PR_TRUE);
5719 SHA1_DestroyContext(sha, PR_TRUE);
5720 sftk_FreeObject(key);
5725 case CKM_CONCATENATE_BASE_AND_KEY:
5729 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5730 if (crv != CKR_OK) break;
5732 session = sftk_SessionFromHandle(hSession);
5733 if (session == NULL) {
5734 crv = CKR_SESSION_HANDLE_INVALID;
5738 newKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
5739 pMechanism->pParameter,session);
5740 sftk_FreeSession(session);
5741 if ( newKey == NULL) {
5742 crv = CKR_KEY_HANDLE_INVALID;
5746 if (sftk_isTrue(newKey,CKA_SENSITIVE)) {
5747 crv = sftk_forceAttribute(newKey,CKA_SENSITIVE,&cktrue,
5749 if (crv != CKR_OK) {
5750 sftk_FreeObject(newKey);
5755 att2 = sftk_FindAttribute(newKey,CKA_VALUE);
5757 sftk_FreeObject(newKey);
5758 crv = CKR_KEY_HANDLE_INVALID;
5761 tmpKeySize = att->attrib.ulValueLen+att2->attrib.ulValueLen;
5762 if (keySize == 0) keySize = tmpKeySize;
5763 if (keySize > tmpKeySize) {
5764 sftk_FreeObject(newKey);
5765 sftk_FreeAttribute(att2);
5766 crv = CKR_TEMPLATE_INCONSISTENT;
5769 buf = (unsigned char*)PORT_Alloc(tmpKeySize);
5771 sftk_FreeAttribute(att2);
5772 sftk_FreeObject(newKey);
5773 crv = CKR_HOST_MEMORY;
5777 PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);
5778 PORT_Memcpy(buf+att->attrib.ulValueLen,
5779 att2->attrib.pValue,att2->attrib.ulValueLen);
5781 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
5782 PORT_ZFree(buf,tmpKeySize);
5783 sftk_FreeAttribute(att2);
5784 sftk_FreeObject(newKey);
5788 case CKM_CONCATENATE_BASE_AND_DATA:
5789 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5790 if (crv != CKR_OK) break;
5792 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;
5793 tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;
5794 if (keySize == 0) keySize = tmpKeySize;
5795 if (keySize > tmpKeySize) {
5796 crv = CKR_TEMPLATE_INCONSISTENT;
5799 buf = (unsigned char*)PORT_Alloc(tmpKeySize);
5801 crv = CKR_HOST_MEMORY;
5805 PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);
5806 PORT_Memcpy(buf+att->attrib.ulValueLen,stringPtr->pData,
5809 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
5810 PORT_ZFree(buf,tmpKeySize);
5812 case CKM_CONCATENATE_DATA_AND_BASE:
5813 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5814 if (crv != CKR_OK) break;
5816 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
5817 tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;
5818 if (keySize == 0) keySize = tmpKeySize;
5819 if (keySize > tmpKeySize) {
5820 crv = CKR_TEMPLATE_INCONSISTENT;
5823 buf = (unsigned char*)PORT_Alloc(tmpKeySize);
5825 crv = CKR_HOST_MEMORY;
5829 PORT_Memcpy(buf,stringPtr->pData,stringPtr->ulLen);
5830 PORT_Memcpy(buf+stringPtr->ulLen,att->attrib.pValue,
5831 att->attrib.ulValueLen);
5833 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
5834 PORT_ZFree(buf,tmpKeySize);
5836 case CKM_XOR_BASE_AND_DATA:
5837 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5838 if (crv != CKR_OK) break;
5840 stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
5841 tmpKeySize = PR_MIN(att->attrib.ulValueLen,stringPtr->ulLen);
5842 if (keySize == 0) keySize = tmpKeySize;
5843 if (keySize > tmpKeySize) {
5844 crv = CKR_TEMPLATE_INCONSISTENT;
5847 buf = (unsigned char*)PORT_Alloc(keySize);
5849 crv = CKR_HOST_MEMORY;
5854 PORT_Memcpy(buf,att->attrib.pValue,keySize);
5855 for (i=0; i < (int)keySize; i++) {
5856 buf[i] ^= stringPtr->pData[i];
5859 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
5860 PORT_ZFree(buf,keySize);
5863 case CKM_EXTRACT_KEY_FROM_KEY:
5865 /* the following assumes 8 bits per byte */
5866 CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
5867 CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
5868 CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
5870 crv = sftk_DeriveSensitiveCheck(sourceKey,key);
5871 if (crv != CKR_OK) break;
5874 crv = CKR_TEMPLATE_INCOMPLETE;
5877 /* make sure we have enough bits in the original key */
5878 if (att->attrib.ulValueLen <
5879 (offset + keySize + ((shift != 0)? 1 :0)) ) {
5880 crv = CKR_MECHANISM_PARAM_INVALID;
5883 buf = (unsigned char*)PORT_Alloc(keySize);
5885 crv = CKR_HOST_MEMORY;
5889 /* copy the bits we need into the new key */
5890 for (i=0; i < (int)keySize; i++) {
5891 unsigned char *value =
5892 ((unsigned char *)att->attrib.pValue)+offset+i;
5894 buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
5900 crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize);
5901 PORT_ZFree(buf,keySize);
5904 case CKM_MD2_KEY_DERIVATION:
5905 if (keySize == 0) keySize = MD2_LENGTH;
5906 if (keySize > MD2_LENGTH) {
5907 crv = CKR_TEMPLATE_INCONSISTENT;
5910 /* now allocate the hash contexts */
5911 md2 = MD2_NewContext();
5913 crv = CKR_HOST_MEMORY;
5917 MD2_Update(md2,(const unsigned char*)att->attrib.pValue,
5918 att->attrib.ulValueLen);
5919 MD2_End(md2,key_block,&outLen,MD2_LENGTH);
5920 MD2_DestroyContext(md2, PR_TRUE);
5922 crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize);
5924 case CKM_MD5_KEY_DERIVATION:
5925 if (keySize == 0) keySize = MD5_LENGTH;
5926 if (keySize > MD5_LENGTH) {
5927 crv = CKR_TEMPLATE_INCONSISTENT;
5930 /* now allocate the hash contexts */
5931 md5 = MD5_NewContext();
5933 crv = CKR_HOST_MEMORY;
5937 MD5_Update(md5,(const unsigned char*)att->attrib.pValue,
5938 att->attrib.ulValueLen);
5939 MD5_End(md5,key_block,&outLen,MD5_LENGTH);
5940 MD5_DestroyContext(md5, PR_TRUE);
5942 crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize);
5944 case CKM_SHA1_KEY_DERIVATION:
5945 if (keySize == 0) keySize = SHA1_LENGTH;
5946 if (keySize > SHA1_LENGTH) {
5947 crv = CKR_TEMPLATE_INCONSISTENT;
5950 /* now allocate the hash contexts */
5951 sha = SHA1_NewContext();
5953 crv = CKR_HOST_MEMORY;
5957 SHA1_Update(sha,(const unsigned char*)att->attrib.pValue,
5958 att->attrib.ulValueLen);
5959 SHA1_End(sha,key_block,&outLen,SHA1_LENGTH);
5960 SHA1_DestroyContext(sha, PR_TRUE);
5962 crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
5965 case CKM_DH_PKCS_DERIVE:
5967 SECItem derived, dhPublic;
5968 SECItem dhPrime, dhValue;
5969 /* sourceKey - values for the local existing low key */
5970 /* get prime and value attributes */
5971 crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
5972 if (crv != SECSuccess) break;
5973 crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
5974 if (crv != SECSuccess) {
5975 PORT_Free(dhPrime.data);
5979 dhPublic.data = pMechanism->pParameter;
5980 dhPublic.len = pMechanism->ulParameterLen;
5982 /* calculate private value - oct */
5983 rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
5985 PORT_Free(dhPrime.data);
5986 PORT_Free(dhValue.data);
5988 if (rv == SECSuccess) {
5989 sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
5990 PORT_ZFree(derived.data, derived.len);
5992 crv = CKR_HOST_MEMORY;
5997 #ifdef NSS_ENABLE_ECC
5998 case CKM_ECDH1_DERIVE:
5999 case CKM_ECDH1_COFACTOR_DERIVE:
6001 SECItem ecScalar, ecPoint;
6003 PRBool withCofactor = PR_FALSE;
6004 unsigned char secret_hash[20];
6005 unsigned char *secret;
6006 unsigned char *keyData = NULL;
6007 int secretlen, curveLen, pubKeyLen;
6008 CK_ECDH1_DERIVE_PARAMS *mechParams;
6009 NSSLOWKEYPrivateKey *privKey;
6010 PLArenaPool *arena = NULL;
6012 /* Check mechanism parameters */
6013 mechParams = (CK_ECDH1_DERIVE_PARAMS *) pMechanism->pParameter;
6014 if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) ||
6015 ((mechParams->kdf == CKD_NULL) &&
6016 ((mechParams->ulSharedDataLen != 0) ||
6017 (mechParams->pSharedData != NULL)))) {
6018 crv = CKR_MECHANISM_PARAM_INVALID;
6022 privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv);
6023 if (privKey == NULL) {
6027 /* Now we are working with a non-NULL private key */
6028 SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue);
6030 ecPoint.data = mechParams->pPublicData;
6031 ecPoint.len = mechParams->ulPublicDataLen;
6033 curveLen = (privKey->u.ec.ecParams.fieldID.size +7)/8;
6034 pubKeyLen = (2*curveLen) + 1;
6036 /* if the len is too small, can't be a valid point */
6037 if (ecPoint.len < pubKeyLen) {
6040 /* if the len is too large, must be an encoded point (length is
6041 * equal case just falls through */
6042 if (ecPoint.len > pubKeyLen) {
6045 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
6046 if (arena == NULL) {
6050 rv = SEC_QuickDERDecodeItem(arena, &newPoint,
6051 SEC_ASN1_GET(SEC_OctetStringTemplate),
6053 if (rv != SECSuccess) {
6059 if (pMechanism->mechanism == CKM_ECDH1_COFACTOR_DERIVE) {
6060 withCofactor = PR_TRUE;
6062 /* When not using cofactor derivation, one should
6063 * validate the public key to avoid small subgroup
6066 if (EC_ValidatePublicKey(&privKey->u.ec.ecParams, &ecPoint)
6072 rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
6073 withCofactor, &tmp);
6074 PORT_Free(ecScalar.data);
6075 ecScalar.data = NULL;
6076 if (privKey != sourceKey->objectInfo) {
6077 nsslowkey_DestroyPrivateKey(privKey);
6081 PORT_FreeArena(arena,PR_FALSE);
6085 if (rv != SECSuccess) {
6086 crv = sftk_MapCryptError(PORT_GetError());
6091 * tmp is the raw data created by ECDH_Derive,
6092 * secret and secretlen are the values we will eventually pass as our
6096 secretlen = tmp.len;
6099 * apply the kdf function.
6101 if (mechParams->kdf == CKD_SHA1_KDF) {
6102 /* Compute SHA1 hash */
6103 PORT_Memset(secret_hash, 0, 20);
6104 rv = SHA1_HashBuf(secret_hash, tmp.data, tmp.len);
6105 if (rv != SECSuccess) {
6106 PORT_ZFree(tmp.data, tmp.len);
6107 crv = CKR_HOST_MEMORY;
6110 secret = secret_hash;
6115 * if keySize is supplied, then we are generating a key of a specific
6116 * length. This is done by taking the least significant 'keySize'
6117 * bytes from the unsigned value calculated by ECDH. Note: this may
6118 * mean padding temp with extra leading zeros from what ECDH_Derive
6119 * already returned (which itself may contain leading zeros).
6122 if (secretlen < keySize) {
6123 keyData = PORT_ZAlloc(keySize);
6125 PORT_ZFree(tmp.data, tmp.len);
6126 crv = CKR_HOST_MEMORY;
6129 PORT_Memcpy(&keyData[keySize-secretlen],secret,secretlen);
6132 secret += (secretlen - keySize);
6134 secretlen = keySize;
6137 sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
6138 PORT_ZFree(tmp.data, tmp.len);
6140 PORT_ZFree(keyData, keySize);
6142 PORT_Memset(secret_hash, 0, 20);
6147 crv = CKR_ARGUMENTS_BAD;
6148 PORT_Free(ecScalar.data);
6149 if (privKey != sourceKey->objectInfo)
6150 nsslowkey_DestroyPrivateKey(privKey);
6152 PORT_FreeArena(arena, PR_FALSE);
6157 #endif /* NSS_ENABLE_ECC */
6159 /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */
6160 case CKM_NSS_HKDF_SHA1: hashType = HASH_AlgSHA1; goto hkdf;
6161 case CKM_NSS_HKDF_SHA256: hashType = HASH_AlgSHA256; goto hkdf;
6162 case CKM_NSS_HKDF_SHA384: hashType = HASH_AlgSHA384; goto hkdf;
6163 case CKM_NSS_HKDF_SHA512: hashType = HASH_AlgSHA512; goto hkdf;
6165 const CK_NSS_HKDFParams * params =
6166 (const CK_NSS_HKDFParams *) pMechanism->pParameter;
6167 const SECHashObject * rawHash;
6169 CK_BYTE buf[HASH_LENGTH_MAX];
6170 /* const */ CK_BYTE * prk; /* psuedo-random key */
6172 const CK_BYTE * okm; /* output keying material */
6174 rawHash = HASH_GetRawHashObject(hashType);
6175 if (rawHash == NULL || rawHash->length > sizeof buf) {
6176 crv = CKR_FUNCTION_FAILED;
6179 hashLen = rawHash->length;
6181 if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams) ||
6182 !params || (!params->bExpand && !params->bExtract) ||
6183 (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
6184 (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
6185 crv = CKR_MECHANISM_PARAM_INVALID;
6188 if (keySize == 0 || keySize > sizeof key_block ||
6189 (!params->bExpand && keySize > hashLen) ||
6190 (params->bExpand && keySize > 255 * hashLen)) {
6191 crv = CKR_TEMPLATE_INCONSISTENT;
6194 crv = sftk_DeriveSensitiveCheck(sourceKey, key);
6198 /* HKDF-Extract(salt, base key value) */
6199 if (params->bExtract) {
6203 unsigned int bufLen;
6205 salt = params->pSalt;
6206 saltLen = params->ulSaltLen;
6210 memset(salt, 0, saltLen);
6212 hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
6214 crv = CKR_HOST_MEMORY;
6218 HMAC_Update(hmac, (const unsigned char*) att->attrib.pValue,
6219 att->attrib.ulValueLen);
6220 HMAC_Finish(hmac, buf, &bufLen, sizeof(buf));
6221 HMAC_Destroy(hmac, PR_TRUE);
6222 PORT_Assert(bufLen == rawHash->length);
6226 /* PRK = base key value */
6227 prk = (CK_BYTE*) att->attrib.pValue;
6228 prkLen = att->attrib.ulValueLen;
6232 if (!params->bExpand) {
6235 /* T(1) = HMAC-Hash(prk, "" | info | 0x01)
6236 * T(n) = HMAC-Hash(prk, T(n-1) | info | n
6237 * key material = T(1) | ... | T(n)
6241 unsigned iterations = PR_ROUNDUP(keySize, hashLen) / hashLen;
6242 hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
6244 crv = CKR_HOST_MEMORY;
6247 for (i = 1; i <= iterations; ++i) {
6251 HMAC_Update(hmac, key_block + ((i-2) * hashLen), hashLen);
6253 if (params->ulInfoLen != 0) {
6254 HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
6256 HMAC_Update(hmac, &i, 1);
6257 HMAC_Finish(hmac, key_block + ((i-1) * hashLen), &len,
6259 PORT_Assert(len == hashLen);
6261 HMAC_Destroy(hmac, PR_TRUE);
6264 /* key material = prk */
6265 crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
6267 } /* end of CKM_NSS_HKDF_* */
6269 case CKM_NSS_JPAKE_ROUND2_SHA1: hashType = HASH_AlgSHA1; goto jpake2;
6270 case CKM_NSS_JPAKE_ROUND2_SHA256: hashType = HASH_AlgSHA256; goto jpake2;
6271 case CKM_NSS_JPAKE_ROUND2_SHA384: hashType = HASH_AlgSHA384; goto jpake2;
6272 case CKM_NSS_JPAKE_ROUND2_SHA512: hashType = HASH_AlgSHA512; goto jpake2;
6274 if (pMechanism->pParameter == NULL ||
6275 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params))
6276 crv = CKR_MECHANISM_PARAM_INVALID;
6277 if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN))
6278 crv = CKR_TEMPLATE_INCONSISTENT;
6280 crv = sftk_DeriveSensitiveCheck(sourceKey, key);
6282 crv = jpake_Round2(hashType,
6283 (CK_NSS_JPAKERound2Params *) pMechanism->pParameter,
6287 case CKM_NSS_JPAKE_FINAL_SHA1: hashType = HASH_AlgSHA1; goto jpakeFinal;
6288 case CKM_NSS_JPAKE_FINAL_SHA256: hashType = HASH_AlgSHA256; goto jpakeFinal;
6289 case CKM_NSS_JPAKE_FINAL_SHA384: hashType = HASH_AlgSHA384; goto jpakeFinal;
6290 case CKM_NSS_JPAKE_FINAL_SHA512: hashType = HASH_AlgSHA512; goto jpakeFinal;
6292 if (pMechanism->pParameter == NULL ||
6293 pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams))
6294 crv = CKR_MECHANISM_PARAM_INVALID;
6295 /* We purposely do not do the derive sensitivity check; we want to be
6296 able to derive non-sensitive keys while allowing the ROUND1 and
6297 ROUND2 keys to be sensitive (which they always are, since they are
6298 in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE
6299 in the template in order for the resultant keyblock key to be
6303 crv = jpake_Final(hashType,
6304 (CK_NSS_JPAKEFinalParams *) pMechanism->pParameter,
6309 crv = CKR_MECHANISM_INVALID;
6312 sftk_FreeAttribute(att);
6314 sftk_FreeObject(sourceKey);
6315 if (crv != CKR_OK) {
6316 if (key) sftk_FreeObject(key);
6320 /* link the key object into the list */
6322 SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
6323 PORT_Assert(sessKey);
6324 /* get the session */
6325 sessKey->wasDerived = PR_TRUE;
6326 session = sftk_SessionFromHandle(hSession);
6327 if (session == NULL) {
6328 sftk_FreeObject(key);
6329 return CKR_HOST_MEMORY;
6332 crv = sftk_handleObject(key,session);
6333 sftk_FreeSession(session);
6334 *phKey = key->handle;
6335 sftk_FreeObject(key);
6341 /* NSC_GetFunctionStatus obtains an updated status of a function running
6342 * in parallel with an application. */
6343 CK_RV NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
6347 return CKR_FUNCTION_NOT_PARALLEL;
6350 /* NSC_CancelFunction cancels a function running in parallel */
6351 CK_RV NSC_CancelFunction(CK_SESSION_HANDLE hSession)
6355 return CKR_FUNCTION_NOT_PARALLEL;
6358 /* NSC_GetOperationState saves the state of the cryptographic
6359 *operation in a session.
6360 * NOTE: This code only works for digest functions for now. eventually need
6361 * to add full flatten/resurect to our state stuff so that all types of state
6363 CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession,
6364 CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
6366 SFTKSessionContext *context;
6367 SFTKSession *session;
6369 CK_ULONG pOSLen = *pulOperationStateLen;
6373 /* make sure we're legal */
6374 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
6375 if (crv != CKR_OK) return crv;
6377 *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE)
6378 + sizeof(SFTKContextType);
6379 if (pOperationState == NULL) {
6380 sftk_FreeSession(session);
6383 if (pOSLen < *pulOperationStateLen) {
6384 return CKR_BUFFER_TOO_SMALL;
6387 PORT_Memcpy(pOperationState,&context->type,sizeof(SFTKContextType));
6388 pOperationState += sizeof(SFTKContextType);
6389 PORT_Memcpy(pOperationState,&context->currentMech,
6390 sizeof(CK_MECHANISM_TYPE));
6391 pOperationState += sizeof(CK_MECHANISM_TYPE);
6392 PORT_Memcpy(pOperationState,context->cipherInfo,context->cipherInfoLen);
6393 sftk_FreeSession(session);
6398 #define sftk_Decrement(stateSize,len) \
6399 stateSize = ((stateSize) > (CK_ULONG)(len)) ? \
6400 ((stateSize) - (CK_ULONG)(len)) : 0;
6402 /* NSC_SetOperationState restores the state of the cryptographic
6403 * operation in a session. This is coded like it can restore lots of
6404 * states, but it only works for truly flat cipher structures. */
6405 CK_RV NSC_SetOperationState(CK_SESSION_HANDLE hSession,
6406 CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
6407 CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
6409 SFTKSessionContext *context;
6410 SFTKSession *session;
6411 SFTKContextType type;
6417 while (ulOperationStateLen != 0) {
6418 /* get what type of state we're dealing with... */
6419 PORT_Memcpy(&type,pOperationState, sizeof(SFTKContextType));
6421 /* fix up session contexts based on type */
6422 session = sftk_SessionFromHandle(hSession);
6423 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6424 context = sftk_ReturnContextByType(session, type);
6425 sftk_SetContextByType(session, type, NULL);
6427 sftk_FreeContext(context);
6429 pOperationState += sizeof(SFTKContextType);
6430 sftk_Decrement(ulOperationStateLen,sizeof(SFTKContextType));
6433 /* get the mechanism structure */
6434 PORT_Memcpy(&mech.mechanism,pOperationState,sizeof(CK_MECHANISM_TYPE));
6435 pOperationState += sizeof(CK_MECHANISM_TYPE);
6436 sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
6437 /* should be filled in... but not necessary for hash */
6438 mech.pParameter = NULL;
6439 mech.ulParameterLen = 0;
6442 crv = NSC_DigestInit(hSession,&mech);
6443 if (crv != CKR_OK) break;
6444 crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE,
6446 if (crv != CKR_OK) break;
6447 PORT_Memcpy(context->cipherInfo,pOperationState,
6448 context->cipherInfoLen);
6449 pOperationState += context->cipherInfoLen;
6450 sftk_Decrement(ulOperationStateLen,context->cipherInfoLen);
6453 /* do sign/encrypt/decrypt later */
6454 crv = CKR_SAVED_STATE_INVALID;
6456 sftk_FreeSession(session);
6457 if (crv != CKR_OK) break;
6462 /* Dual-function cryptographic operations */
6464 /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
6466 CK_RV NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
6467 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
6468 CK_ULONG_PTR pulEncryptedPartLen)
6474 crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart,
6475 pulEncryptedPartLen);
6476 if (crv != CKR_OK) return crv;
6477 crv = NSC_DigestUpdate(hSession,pPart,ulPartLen);
6483 /* NSC_DecryptDigestUpdate continues a multiple-part decryption and
6484 * digesting operation. */
6485 CK_RV NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
6486 CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
6487 CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
6493 crv = NSC_DecryptUpdate(hSession,pEncryptedPart, ulEncryptedPartLen,
6495 if (crv != CKR_OK) return crv;
6496 crv = NSC_DigestUpdate(hSession,pPart,*pulPartLen);
6502 /* NSC_SignEncryptUpdate continues a multiple-part signing and
6503 * encryption operation. */
6504 CK_RV NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
6505 CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
6506 CK_ULONG_PTR pulEncryptedPartLen)
6512 crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart,
6513 pulEncryptedPartLen);
6514 if (crv != CKR_OK) return crv;
6515 crv = NSC_SignUpdate(hSession,pPart,ulPartLen);
6521 /* NSC_DecryptVerifyUpdate continues a multiple-part decryption
6522 * and verify operation. */
6523 CK_RV NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
6524 CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
6525 CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
6531 crv = NSC_DecryptUpdate(hSession,pEncryptedData, ulEncryptedDataLen,
6533 if (crv != CKR_OK) return crv;
6534 crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
6539 /* NSC_DigestKey continues a multi-part message-digesting operation,
6540 * by digesting the value of a secret key as part of the data already digested.
6542 CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
6544 SFTKSession *session = NULL;
6545 SFTKObject *key = NULL;
6551 session = sftk_SessionFromHandle(hSession);
6552 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6554 key = sftk_ObjectFromHandle(hKey,session);
6555 sftk_FreeSession(session);
6556 if (key == NULL) return CKR_KEY_HANDLE_INVALID;
6558 /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
6560 /* make sure it's a valid key for this operation */
6561 if (key->objclass != CKO_SECRET_KEY) {
6562 sftk_FreeObject(key);
6563 return CKR_KEY_TYPE_INCONSISTENT;
6565 /* get the key value */
6566 att = sftk_FindAttribute(key,CKA_VALUE);
6567 sftk_FreeObject(key);
6569 return CKR_KEY_HANDLE_INVALID;
6571 crv = NSC_DigestUpdate(hSession,(CK_BYTE_PTR)att->attrib.pValue,
6572 att->attrib.ulValueLen);
6573 sftk_FreeAttribute(att);