security/nss/lib/softoken/pkcs11c.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial