1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/softoken/pkcs11c.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,7301 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * This file implements PKCS 11 on top of our existing security modules 1.9 + * 1.10 + * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. 1.11 + * This implementation has two slots: 1.12 + * slot 1 is our generic crypto support. It does not require login. 1.13 + * It supports Public Key ops, and all they bulk ciphers and hashes. 1.14 + * It can also support Private Key ops for imported Private keys. It does 1.15 + * not have any token storage. 1.16 + * slot 2 is our private key support. It requires a login before use. It 1.17 + * can store Private Keys and Certs as token objects. Currently only private 1.18 + * keys and their associated Certificates are saved on the token. 1.19 + * 1.20 + * In this implementation, session objects are only visible to the session 1.21 + * that created or generated them. 1.22 + */ 1.23 +#include "seccomon.h" 1.24 +#include "secitem.h" 1.25 +#include "secport.h" 1.26 +#include "blapi.h" 1.27 +#include "pkcs11.h" 1.28 +#include "pkcs11i.h" 1.29 +#include "pkcs1sig.h" 1.30 +#include "lowkeyi.h" 1.31 +#include "secder.h" 1.32 +#include "secdig.h" 1.33 +#include "lowpbe.h" /* We do PBE below */ 1.34 +#include "pkcs11t.h" 1.35 +#include "secoid.h" 1.36 +#include "alghmac.h" 1.37 +#include "softoken.h" 1.38 +#include "secasn1.h" 1.39 +#include "secerr.h" 1.40 + 1.41 +#include "prprf.h" 1.42 + 1.43 +#define __PASTE(x,y) x##y 1.44 + 1.45 +/* 1.46 + * we renamed all our internal functions, get the correct 1.47 + * definitions for them... 1.48 + */ 1.49 +#undef CK_PKCS11_FUNCTION_INFO 1.50 +#undef CK_NEED_ARG_LIST 1.51 + 1.52 +#define CK_EXTERN extern 1.53 +#define CK_PKCS11_FUNCTION_INFO(func) \ 1.54 + CK_RV __PASTE(NS,func) 1.55 +#define CK_NEED_ARG_LIST 1 1.56 + 1.57 +#include "pkcs11f.h" 1.58 + 1.59 +typedef struct { 1.60 + PRUint8 client_version[2]; 1.61 + PRUint8 random[46]; 1.62 +} SSL3RSAPreMasterSecret; 1.63 + 1.64 +static void sftk_Null(void *data, PRBool freeit) 1.65 +{ 1.66 + return; 1.67 +} 1.68 + 1.69 +#ifndef NSS_DISABLE_ECC 1.70 +#ifdef EC_DEBUG 1.71 +#define SEC_PRINT(str1, str2, num, sitem) \ 1.72 + printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \ 1.73 + str1, str2, num, sitem->len); \ 1.74 + for (i = 0; i < sitem->len; i++) { \ 1.75 + printf("%02x:", sitem->data[i]); \ 1.76 + } \ 1.77 + printf("\n") 1.78 +#else 1.79 +#define SEC_PRINT(a, b, c, d) 1.80 +#endif 1.81 +#endif /* NSS_DISABLE_ECC */ 1.82 + 1.83 +/* 1.84 + * free routines.... Free local type allocated data, and convert 1.85 + * other free routines to the destroy signature. 1.86 + */ 1.87 +static void 1.88 +sftk_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit) 1.89 +{ 1.90 + nsslowkey_DestroyPrivateKey(key); 1.91 +} 1.92 + 1.93 +static void 1.94 +sftk_Space(void *data, PRBool freeit) 1.95 +{ 1.96 + PORT_Free(data); 1.97 +} 1.98 + 1.99 +/* 1.100 + * map all the SEC_ERROR_xxx error codes that may be returned by freebl 1.101 + * functions to CKR_xxx. return CKR_DEVICE_ERROR by default for backward 1.102 + * compatibility. 1.103 + */ 1.104 +static CK_RV 1.105 +sftk_MapCryptError(int error) 1.106 +{ 1.107 + switch (error) { 1.108 + case SEC_ERROR_INVALID_ARGS: 1.109 + case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */ 1.110 + return CKR_ARGUMENTS_BAD; 1.111 + case SEC_ERROR_INPUT_LEN: 1.112 + return CKR_DATA_LEN_RANGE; 1.113 + case SEC_ERROR_OUTPUT_LEN: 1.114 + return CKR_BUFFER_TOO_SMALL; 1.115 + case SEC_ERROR_LIBRARY_FAILURE: 1.116 + return CKR_GENERAL_ERROR; 1.117 + case SEC_ERROR_NO_MEMORY: 1.118 + return CKR_HOST_MEMORY; 1.119 + case SEC_ERROR_BAD_SIGNATURE: 1.120 + return CKR_SIGNATURE_INVALID; 1.121 + case SEC_ERROR_INVALID_KEY: 1.122 + return CKR_KEY_SIZE_RANGE; 1.123 + case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */ 1.124 + return CKR_KEY_SIZE_RANGE; /* the closest error code */ 1.125 + case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM: 1.126 + return CKR_TEMPLATE_INCONSISTENT; 1.127 + /* EC functions set this error if NSS_DISABLE_ECC is defined */ 1.128 + case SEC_ERROR_UNSUPPORTED_KEYALG: 1.129 + return CKR_MECHANISM_INVALID; 1.130 + case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE: 1.131 + return CKR_DOMAIN_PARAMS_INVALID; 1.132 + /* key pair generation failed after max number of attempts */ 1.133 + case SEC_ERROR_NEED_RANDOM: 1.134 + return CKR_FUNCTION_FAILED; 1.135 + } 1.136 + return CKR_DEVICE_ERROR; 1.137 +} 1.138 + 1.139 +/* used by Decrypt and UnwrapKey (indirectly) */ 1.140 +static CK_RV 1.141 +sftk_MapDecryptError(int error) 1.142 +{ 1.143 + switch (error) { 1.144 + case SEC_ERROR_BAD_DATA: 1.145 + return CKR_ENCRYPTED_DATA_INVALID; 1.146 + default: 1.147 + return sftk_MapCryptError(error); 1.148 + } 1.149 +} 1.150 + 1.151 +/* 1.152 + * return CKR_SIGNATURE_INVALID instead of CKR_DEVICE_ERROR by default for 1.153 + * backward compatibilty. 1.154 + */ 1.155 +static CK_RV 1.156 +sftk_MapVerifyError(int error) 1.157 +{ 1.158 + CK_RV crv = sftk_MapCryptError(error); 1.159 + if (crv == CKR_DEVICE_ERROR) 1.160 + crv = CKR_SIGNATURE_INVALID; 1.161 + return crv; 1.162 +} 1.163 + 1.164 + 1.165 +/* 1.166 + * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by 1.167 + * Deprecating a full des key to 40 bit key strenth. 1.168 + */ 1.169 +static CK_RV 1.170 +sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey) 1.171 +{ 1.172 + unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae }; 1.173 + unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 }; 1.174 + unsigned char enc_src[8]; 1.175 + unsigned char enc_dest[8]; 1.176 + unsigned int leng,i; 1.177 + DESContext *descx; 1.178 + SECStatus rv; 1.179 + 1.180 + 1.181 + /* zero the parity bits */ 1.182 + for (i=0; i < 8; i++) { 1.183 + enc_src[i] = cdmfkey[i] & 0xfe; 1.184 + } 1.185 + 1.186 + /* encrypt with key 1 */ 1.187 + descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE); 1.188 + if (descx == NULL) return CKR_HOST_MEMORY; 1.189 + rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8); 1.190 + DES_DestroyContext(descx,PR_TRUE); 1.191 + if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError()); 1.192 + 1.193 + /* xor source with des, zero the parity bits and deprecate the key*/ 1.194 + for (i=0; i < 8; i++) { 1.195 + if (i & 1) { 1.196 + enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe; 1.197 + } else { 1.198 + enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e; 1.199 + } 1.200 + } 1.201 + 1.202 + /* encrypt with key 2 */ 1.203 + descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE); 1.204 + if (descx == NULL) return CKR_HOST_MEMORY; 1.205 + rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8); 1.206 + DES_DestroyContext(descx,PR_TRUE); 1.207 + if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError()); 1.208 + 1.209 + /* set the corret parity on our new des key */ 1.210 + sftk_FormatDESKey(deskey, 8); 1.211 + return CKR_OK; 1.212 +} 1.213 + 1.214 + 1.215 +/* NSC_DestroyObject destroys an object. */ 1.216 +CK_RV 1.217 +NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) 1.218 +{ 1.219 + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 1.220 + SFTKSession *session; 1.221 + SFTKObject *object; 1.222 + SFTKFreeStatus status; 1.223 + 1.224 + CHECK_FORK(); 1.225 + 1.226 + if (slot == NULL) { 1.227 + return CKR_SESSION_HANDLE_INVALID; 1.228 + } 1.229 + /* 1.230 + * This whole block just makes sure we really can destroy the 1.231 + * requested object. 1.232 + */ 1.233 + session = sftk_SessionFromHandle(hSession); 1.234 + if (session == NULL) { 1.235 + return CKR_SESSION_HANDLE_INVALID; 1.236 + } 1.237 + 1.238 + object = sftk_ObjectFromHandle(hObject,session); 1.239 + if (object == NULL) { 1.240 + sftk_FreeSession(session); 1.241 + return CKR_OBJECT_HANDLE_INVALID; 1.242 + } 1.243 + 1.244 + /* don't destroy a private object if we aren't logged in */ 1.245 + if ((!slot->isLoggedIn) && (slot->needLogin) && 1.246 + (sftk_isTrue(object,CKA_PRIVATE))) { 1.247 + sftk_FreeSession(session); 1.248 + sftk_FreeObject(object); 1.249 + return CKR_USER_NOT_LOGGED_IN; 1.250 + } 1.251 + 1.252 + /* don't destroy a token object if we aren't in a rw session */ 1.253 + 1.254 + if (((session->info.flags & CKF_RW_SESSION) == 0) && 1.255 + (sftk_isTrue(object,CKA_TOKEN))) { 1.256 + sftk_FreeSession(session); 1.257 + sftk_FreeObject(object); 1.258 + return CKR_SESSION_READ_ONLY; 1.259 + } 1.260 + 1.261 + sftk_DeleteObject(session,object); 1.262 + 1.263 + sftk_FreeSession(session); 1.264 + 1.265 + /* 1.266 + * get some indication if the object is destroyed. Note: this is not 1.267 + * 100%. Someone may have an object reference outstanding (though that 1.268 + * should not be the case by here. Also note that the object is "half" 1.269 + * destroyed. Our internal representation is destroyed, but it may still 1.270 + * be in the data base. 1.271 + */ 1.272 + status = sftk_FreeObject(object); 1.273 + 1.274 + return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR; 1.275 +} 1.276 + 1.277 + 1.278 +/* 1.279 + ************** Crypto Functions: Utilities ************************ 1.280 + */ 1.281 +/* 1.282 + * Utility function for converting PSS/OAEP parameter types into 1.283 + * HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447. 1.284 + */ 1.285 +static HASH_HashType 1.286 +GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech) 1.287 +{ 1.288 + switch (mech) { 1.289 + case CKM_SHA_1: 1.290 + case CKG_MGF1_SHA1: 1.291 + return HASH_AlgSHA1; 1.292 + case CKM_SHA224: 1.293 + case CKG_MGF1_SHA224: 1.294 + return HASH_AlgSHA224; 1.295 + case CKM_SHA256: 1.296 + case CKG_MGF1_SHA256: 1.297 + return HASH_AlgSHA256; 1.298 + case CKM_SHA384: 1.299 + case CKG_MGF1_SHA384: 1.300 + return HASH_AlgSHA384; 1.301 + case CKM_SHA512: 1.302 + case CKG_MGF1_SHA512: 1.303 + return HASH_AlgSHA512; 1.304 + default: 1.305 + return HASH_AlgNULL; 1.306 + } 1.307 +} 1.308 + 1.309 +/* 1.310 + * Returns true if "params" contains a valid set of PSS parameters 1.311 + */ 1.312 +static PRBool 1.313 +sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params) 1.314 +{ 1.315 + if (!params) { 1.316 + return PR_FALSE; 1.317 + } 1.318 + if (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL || 1.319 + GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) { 1.320 + return PR_FALSE; 1.321 + } 1.322 + return PR_TRUE; 1.323 +} 1.324 + 1.325 +/* 1.326 + * Returns true if "params" contains a valid set of OAEP parameters 1.327 + */ 1.328 +static PRBool 1.329 +sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params) 1.330 +{ 1.331 + if (!params) { 1.332 + return PR_FALSE; 1.333 + } 1.334 + /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which 1.335 + * state: 1.336 + * If the parameter is empty, pSourceData must be NULL and 1.337 + * ulSourceDataLen must be zero. 1.338 + */ 1.339 + if (params->source != CKZ_DATA_SPECIFIED || 1.340 + (GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) || 1.341 + (GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) || 1.342 + (params->ulSourceDataLen == 0 && params->pSourceData != NULL) || 1.343 + (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) { 1.344 + return PR_FALSE; 1.345 + } 1.346 + return PR_TRUE; 1.347 +} 1.348 + 1.349 +/* 1.350 + * return a context based on the SFTKContext type. 1.351 + */ 1.352 +SFTKSessionContext * 1.353 +sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type) 1.354 +{ 1.355 + switch (type) { 1.356 + case SFTK_ENCRYPT: 1.357 + case SFTK_DECRYPT: 1.358 + return session->enc_context; 1.359 + case SFTK_HASH: 1.360 + return session->hash_context; 1.361 + case SFTK_SIGN: 1.362 + case SFTK_SIGN_RECOVER: 1.363 + case SFTK_VERIFY: 1.364 + case SFTK_VERIFY_RECOVER: 1.365 + return session->hash_context; 1.366 + } 1.367 + return NULL; 1.368 +} 1.369 + 1.370 +/* 1.371 + * change a context based on the SFTKContext type. 1.372 + */ 1.373 +void 1.374 +sftk_SetContextByType(SFTKSession *session, SFTKContextType type, 1.375 + SFTKSessionContext *context) 1.376 +{ 1.377 + switch (type) { 1.378 + case SFTK_ENCRYPT: 1.379 + case SFTK_DECRYPT: 1.380 + session->enc_context = context; 1.381 + break; 1.382 + case SFTK_HASH: 1.383 + session->hash_context = context; 1.384 + break; 1.385 + case SFTK_SIGN: 1.386 + case SFTK_SIGN_RECOVER: 1.387 + case SFTK_VERIFY: 1.388 + case SFTK_VERIFY_RECOVER: 1.389 + session->hash_context = context; 1.390 + break; 1.391 + } 1.392 + return; 1.393 +} 1.394 + 1.395 +/* 1.396 + * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal, 1.397 + * and C_XXX function. The function takes a session handle, the context type, 1.398 + * and wether or not the session needs to be multipart. It returns the context, 1.399 + * and optionally returns the session pointer (if sessionPtr != NULL) if session 1.400 + * pointer is returned, the caller is responsible for freeing it. 1.401 + */ 1.402 +static CK_RV 1.403 +sftk_GetContext(CK_SESSION_HANDLE handle,SFTKSessionContext **contextPtr, 1.404 + SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr) 1.405 +{ 1.406 + SFTKSession *session; 1.407 + SFTKSessionContext *context; 1.408 + 1.409 + session = sftk_SessionFromHandle(handle); 1.410 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.411 + context = sftk_ReturnContextByType(session,type); 1.412 + /* make sure the context is valid */ 1.413 + if((context==NULL)||(context->type!=type)||(needMulti&&!(context->multi))){ 1.414 + sftk_FreeSession(session); 1.415 + return CKR_OPERATION_NOT_INITIALIZED; 1.416 + } 1.417 + *contextPtr = context; 1.418 + if (sessionPtr != NULL) { 1.419 + *sessionPtr = session; 1.420 + } else { 1.421 + sftk_FreeSession(session); 1.422 + } 1.423 + return CKR_OK; 1.424 +} 1.425 + 1.426 +/** Terminate operation (in the PKCS#11 spec sense). 1.427 + * Intuitive name for FreeContext/SetNullContext pair. 1.428 + */ 1.429 +static void 1.430 +sftk_TerminateOp( SFTKSession *session, SFTKContextType ctype, 1.431 + SFTKSessionContext *context ) 1.432 +{ 1.433 + sftk_FreeContext( context ); 1.434 + sftk_SetContextByType( session, ctype, NULL ); 1.435 +} 1.436 + 1.437 +/* 1.438 + ************** Crypto Functions: Encrypt ************************ 1.439 + */ 1.440 + 1.441 +/* 1.442 + * All the NSC_InitXXX functions have a set of common checks and processing they 1.443 + * all need to do at the beginning. This is done here. 1.444 + */ 1.445 +static CK_RV 1.446 +sftk_InitGeneric(SFTKSession *session,SFTKSessionContext **contextPtr, 1.447 + SFTKContextType ctype,SFTKObject **keyPtr, 1.448 + CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr, 1.449 + CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation) 1.450 +{ 1.451 + SFTKObject *key = NULL; 1.452 + SFTKAttribute *att; 1.453 + SFTKSessionContext *context; 1.454 + 1.455 + /* We can only init if there is not current context active */ 1.456 + if (sftk_ReturnContextByType(session,ctype) != NULL) { 1.457 + return CKR_OPERATION_ACTIVE; 1.458 + } 1.459 + 1.460 + /* find the key */ 1.461 + if (keyPtr) { 1.462 + key = sftk_ObjectFromHandle(hKey,session); 1.463 + if (key == NULL) { 1.464 + return CKR_KEY_HANDLE_INVALID; 1.465 + } 1.466 + 1.467 + /* make sure it's a valid key for this operation */ 1.468 + if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType)) 1.469 + || !sftk_isTrue(key,operation)) { 1.470 + sftk_FreeObject(key); 1.471 + return CKR_KEY_TYPE_INCONSISTENT; 1.472 + } 1.473 + /* get the key type */ 1.474 + att = sftk_FindAttribute(key,CKA_KEY_TYPE); 1.475 + if (att == NULL) { 1.476 + sftk_FreeObject(key); 1.477 + return CKR_KEY_TYPE_INCONSISTENT; 1.478 + } 1.479 + PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE)); 1.480 + if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) { 1.481 + sftk_FreeAttribute(att); 1.482 + sftk_FreeObject(key); 1.483 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.484 + } 1.485 + PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE)); 1.486 + sftk_FreeAttribute(att); 1.487 + *keyPtr = key; 1.488 + } 1.489 + 1.490 + /* allocate the context structure */ 1.491 + context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext)); 1.492 + if (context == NULL) { 1.493 + if (key) sftk_FreeObject(key); 1.494 + return CKR_HOST_MEMORY; 1.495 + } 1.496 + context->type = ctype; 1.497 + context->multi = PR_TRUE; 1.498 + context->rsa = PR_FALSE; 1.499 + context->cipherInfo = NULL; 1.500 + context->hashInfo = NULL; 1.501 + context->doPad = PR_FALSE; 1.502 + context->padDataLength = 0; 1.503 + context->key = key; 1.504 + context->blockSize = 0; 1.505 + context->maxLen = 0; 1.506 + 1.507 + *contextPtr = context; 1.508 + return CKR_OK; 1.509 +} 1.510 + 1.511 +static int 1.512 +sftk_aes_mode(CK_MECHANISM_TYPE mechanism) 1.513 +{ 1.514 + switch (mechanism) { 1.515 + case CKM_AES_CBC_PAD: 1.516 + case CKM_AES_CBC: 1.517 + return NSS_AES_CBC; 1.518 + case CKM_AES_ECB: 1.519 + return NSS_AES; 1.520 + case CKM_AES_CTS: 1.521 + return NSS_AES_CTS; 1.522 + case CKM_AES_CTR: 1.523 + return NSS_AES_CTR; 1.524 + case CKM_AES_GCM: 1.525 + return NSS_AES_GCM; 1.526 + } 1.527 + return -1; 1.528 +} 1.529 + 1.530 +static SECStatus 1.531 +sftk_RSAEncryptRaw(NSSLOWKEYPublicKey *key, unsigned char *output, 1.532 + unsigned int *outputLen, unsigned int maxLen, 1.533 + const unsigned char *input, unsigned int inputLen) 1.534 +{ 1.535 + SECStatus rv = SECFailure; 1.536 + 1.537 + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); 1.538 + if (key->keyType != NSSLOWKEYRSAKey) { 1.539 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.540 + return SECFailure; 1.541 + } 1.542 + 1.543 + rv = RSA_EncryptRaw(&key->u.rsa, output, outputLen, maxLen, input, 1.544 + inputLen); 1.545 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.546 + sftk_fatalError = PR_TRUE; 1.547 + } 1.548 + 1.549 + return rv; 1.550 +} 1.551 + 1.552 +static SECStatus 1.553 +sftk_RSADecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output, 1.554 + unsigned int *outputLen, unsigned int maxLen, 1.555 + const unsigned char *input, unsigned int inputLen) 1.556 +{ 1.557 + SECStatus rv = SECFailure; 1.558 + 1.559 + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); 1.560 + if (key->keyType != NSSLOWKEYRSAKey) { 1.561 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.562 + return SECFailure; 1.563 + } 1.564 + 1.565 + rv = RSA_DecryptRaw(&key->u.rsa, output, outputLen, maxLen, input, 1.566 + inputLen); 1.567 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.568 + sftk_fatalError = PR_TRUE; 1.569 + } 1.570 + 1.571 + return rv; 1.572 +} 1.573 + 1.574 +static SECStatus 1.575 +sftk_RSAEncrypt(NSSLOWKEYPublicKey *key, unsigned char *output, 1.576 + unsigned int *outputLen, unsigned int maxLen, 1.577 + const unsigned char *input, unsigned int inputLen) 1.578 +{ 1.579 + SECStatus rv = SECFailure; 1.580 + 1.581 + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); 1.582 + if (key->keyType != NSSLOWKEYRSAKey) { 1.583 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.584 + return SECFailure; 1.585 + } 1.586 + 1.587 + rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input, 1.588 + inputLen); 1.589 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.590 + sftk_fatalError = PR_TRUE; 1.591 + } 1.592 + 1.593 + return rv; 1.594 +} 1.595 + 1.596 +static SECStatus 1.597 +sftk_RSADecrypt(NSSLOWKEYPrivateKey *key, unsigned char *output, 1.598 + unsigned int *outputLen, unsigned int maxLen, 1.599 + const unsigned char *input, unsigned int inputLen) 1.600 +{ 1.601 + SECStatus rv = SECFailure; 1.602 + 1.603 + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); 1.604 + if (key->keyType != NSSLOWKEYRSAKey) { 1.605 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.606 + return SECFailure; 1.607 + } 1.608 + 1.609 + rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input, 1.610 + inputLen); 1.611 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.612 + sftk_fatalError = PR_TRUE; 1.613 + } 1.614 + 1.615 + return rv; 1.616 +} 1.617 + 1.618 +static SECStatus 1.619 +sftk_RSAEncryptOAEP(SFTKOAEPEncryptInfo *info, unsigned char *output, 1.620 + unsigned int *outputLen, unsigned int maxLen, 1.621 + const unsigned char *input, unsigned int inputLen) 1.622 +{ 1.623 + HASH_HashType hashAlg; 1.624 + HASH_HashType maskHashAlg; 1.625 + 1.626 + PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); 1.627 + if (info->key->keyType != NSSLOWKEYRSAKey) { 1.628 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.629 + return SECFailure; 1.630 + } 1.631 + 1.632 + hashAlg = GetHashTypeFromMechanism(info->params->hashAlg); 1.633 + maskHashAlg = GetHashTypeFromMechanism(info->params->mgf); 1.634 + 1.635 + return RSA_EncryptOAEP(&info->key->u.rsa, hashAlg, maskHashAlg, 1.636 + (const unsigned char*)info->params->pSourceData, 1.637 + info->params->ulSourceDataLen, NULL, 0, 1.638 + output, outputLen, maxLen, input, inputLen); 1.639 +} 1.640 + 1.641 +static SECStatus 1.642 +sftk_RSADecryptOAEP(SFTKOAEPDecryptInfo *info, unsigned char *output, 1.643 + unsigned int *outputLen, unsigned int maxLen, 1.644 + const unsigned char *input, unsigned int inputLen) 1.645 +{ 1.646 + SECStatus rv = SECFailure; 1.647 + HASH_HashType hashAlg; 1.648 + HASH_HashType maskHashAlg; 1.649 + 1.650 + PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); 1.651 + if (info->key->keyType != NSSLOWKEYRSAKey) { 1.652 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.653 + return SECFailure; 1.654 + } 1.655 + 1.656 + hashAlg = GetHashTypeFromMechanism(info->params->hashAlg); 1.657 + maskHashAlg = GetHashTypeFromMechanism(info->params->mgf); 1.658 + 1.659 + rv = RSA_DecryptOAEP(&info->key->u.rsa, hashAlg, maskHashAlg, 1.660 + (const unsigned char*)info->params->pSourceData, 1.661 + info->params->ulSourceDataLen, 1.662 + output, outputLen, maxLen, input, inputLen); 1.663 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.664 + sftk_fatalError = PR_TRUE; 1.665 + } 1.666 + return rv; 1.667 +} 1.668 + 1.669 +/** NSC_CryptInit initializes an encryption/Decryption operation. 1.670 + * 1.671 + * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey. 1.672 + * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block 1.673 + * ciphers MAC'ing. 1.674 + */ 1.675 +static CK_RV 1.676 +sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 1.677 + CK_OBJECT_HANDLE hKey, 1.678 + CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage, 1.679 + SFTKContextType contextType, PRBool isEncrypt) 1.680 +{ 1.681 + SFTKSession *session; 1.682 + SFTKObject *key; 1.683 + SFTKSessionContext *context; 1.684 + SFTKAttribute *att; 1.685 + CK_RC2_CBC_PARAMS *rc2_param; 1.686 +#if NSS_SOFTOKEN_DOES_RC5 1.687 + CK_RC5_CBC_PARAMS *rc5_param; 1.688 + SECItem rc5Key; 1.689 +#endif 1.690 + CK_KEY_TYPE key_type; 1.691 + CK_RV crv = CKR_OK; 1.692 + unsigned effectiveKeyLength; 1.693 + unsigned char newdeskey[24]; 1.694 + PRBool useNewKey=PR_FALSE; 1.695 + int t; 1.696 + 1.697 + crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage ); 1.698 + if (crv != CKR_OK) 1.699 + return crv; 1.700 + 1.701 + session = sftk_SessionFromHandle(hSession); 1.702 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.703 + 1.704 + crv = sftk_InitGeneric(session,&context,contextType,&key,hKey,&key_type, 1.705 + isEncrypt ?CKO_PUBLIC_KEY:CKO_PRIVATE_KEY, keyUsage); 1.706 + 1.707 + if (crv != CKR_OK) { 1.708 + sftk_FreeSession(session); 1.709 + return crv; 1.710 + } 1.711 + 1.712 + context->doPad = PR_FALSE; 1.713 + switch(pMechanism->mechanism) { 1.714 + case CKM_RSA_PKCS: 1.715 + case CKM_RSA_X_509: 1.716 + if (key_type != CKK_RSA) { 1.717 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.718 + break; 1.719 + } 1.720 + context->multi = PR_FALSE; 1.721 + context->rsa = PR_TRUE; 1.722 + if (isEncrypt) { 1.723 + NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); 1.724 + if (pubKey == NULL) { 1.725 + crv = CKR_KEY_HANDLE_INVALID; 1.726 + break; 1.727 + } 1.728 + context->maxLen = nsslowkey_PublicModulusLen(pubKey); 1.729 + context->cipherInfo = (void *)pubKey; 1.730 + context->update = (SFTKCipher) 1.731 + (pMechanism->mechanism == CKM_RSA_X_509 1.732 + ? sftk_RSAEncryptRaw : sftk_RSAEncrypt); 1.733 + } else { 1.734 + NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key,CKK_RSA,&crv); 1.735 + if (privKey == NULL) { 1.736 + crv = CKR_KEY_HANDLE_INVALID; 1.737 + break; 1.738 + } 1.739 + context->maxLen = nsslowkey_PrivateModulusLen(privKey); 1.740 + context->cipherInfo = (void *)privKey; 1.741 + context->update = (SFTKCipher) 1.742 + (pMechanism->mechanism == CKM_RSA_X_509 1.743 + ? sftk_RSADecryptRaw : sftk_RSADecrypt); 1.744 + } 1.745 + context->destroy = sftk_Null; 1.746 + break; 1.747 + case CKM_RSA_PKCS_OAEP: 1.748 + if (key_type != CKK_RSA) { 1.749 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.750 + break; 1.751 + } 1.752 + if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) || 1.753 + !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter)) { 1.754 + crv = CKR_MECHANISM_PARAM_INVALID; 1.755 + break; 1.756 + } 1.757 + context->multi = PR_FALSE; 1.758 + context->rsa = PR_TRUE; 1.759 + if (isEncrypt) { 1.760 + SFTKOAEPEncryptInfo *info = PORT_New(SFTKOAEPEncryptInfo); 1.761 + if (info == NULL) { 1.762 + crv = CKR_HOST_MEMORY; 1.763 + break; 1.764 + } 1.765 + info->params = pMechanism->pParameter; 1.766 + info->key = sftk_GetPubKey(key, CKK_RSA, &crv); 1.767 + if (info->key == NULL) { 1.768 + PORT_Free(info); 1.769 + crv = CKR_KEY_HANDLE_INVALID; 1.770 + break; 1.771 + } 1.772 + context->update = (SFTKCipher) sftk_RSAEncryptOAEP; 1.773 + context->maxLen = nsslowkey_PublicModulusLen(info->key); 1.774 + context->cipherInfo = info; 1.775 + } else { 1.776 + SFTKOAEPDecryptInfo *info = PORT_New(SFTKOAEPDecryptInfo); 1.777 + if (info == NULL) { 1.778 + crv = CKR_HOST_MEMORY; 1.779 + break; 1.780 + } 1.781 + info->params = pMechanism->pParameter; 1.782 + info->key = sftk_GetPrivKey(key, CKK_RSA, &crv); 1.783 + if (info->key == NULL) { 1.784 + PORT_Free(info); 1.785 + crv = CKR_KEY_HANDLE_INVALID; 1.786 + break; 1.787 + } 1.788 + context->update = (SFTKCipher) sftk_RSADecryptOAEP; 1.789 + context->maxLen = nsslowkey_PrivateModulusLen(info->key); 1.790 + context->cipherInfo = info; 1.791 + } 1.792 + context->destroy = (SFTKDestroy) sftk_Space; 1.793 + break; 1.794 + case CKM_RC2_CBC_PAD: 1.795 + context->doPad = PR_TRUE; 1.796 + /* fall thru */ 1.797 + case CKM_RC2_ECB: 1.798 + case CKM_RC2_CBC: 1.799 + context->blockSize = 8; 1.800 + if (key_type != CKK_RC2) { 1.801 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.802 + break; 1.803 + } 1.804 + att = sftk_FindAttribute(key,CKA_VALUE); 1.805 + if (att == NULL) { 1.806 + crv = CKR_KEY_HANDLE_INVALID; 1.807 + break; 1.808 + } 1.809 + rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter; 1.810 + effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8; 1.811 + context->cipherInfo = 1.812 + RC2_CreateContext((unsigned char*)att->attrib.pValue, 1.813 + att->attrib.ulValueLen, rc2_param->iv, 1.814 + pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : 1.815 + NSS_RC2_CBC,effectiveKeyLength); 1.816 + sftk_FreeAttribute(att); 1.817 + if (context->cipherInfo == NULL) { 1.818 + crv = CKR_HOST_MEMORY; 1.819 + break; 1.820 + } 1.821 + context->update = (SFTKCipher) (isEncrypt ? RC2_Encrypt : RC2_Decrypt); 1.822 + context->destroy = (SFTKDestroy) RC2_DestroyContext; 1.823 + break; 1.824 +#if NSS_SOFTOKEN_DOES_RC5 1.825 + case CKM_RC5_CBC_PAD: 1.826 + context->doPad = PR_TRUE; 1.827 + /* fall thru */ 1.828 + case CKM_RC5_ECB: 1.829 + case CKM_RC5_CBC: 1.830 + if (key_type != CKK_RC5) { 1.831 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.832 + break; 1.833 + } 1.834 + att = sftk_FindAttribute(key,CKA_VALUE); 1.835 + if (att == NULL) { 1.836 + crv = CKR_KEY_HANDLE_INVALID; 1.837 + break; 1.838 + } 1.839 + rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter; 1.840 + context->blockSize = rc5_param->ulWordsize*2; 1.841 + rc5Key.data = (unsigned char*)att->attrib.pValue; 1.842 + rc5Key.len = att->attrib.ulValueLen; 1.843 + context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds, 1.844 + rc5_param->ulWordsize,rc5_param->pIv, 1.845 + pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC); 1.846 + sftk_FreeAttribute(att); 1.847 + if (context->cipherInfo == NULL) { 1.848 + crv = CKR_HOST_MEMORY; 1.849 + break; 1.850 + } 1.851 + context->update = (SFTKCipher) (isEncrypt ? RC5_Encrypt : RC5_Decrypt); 1.852 + context->destroy = (SFTKDestroy) RC5_DestroyContext; 1.853 + break; 1.854 +#endif 1.855 + case CKM_RC4: 1.856 + if (key_type != CKK_RC4) { 1.857 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.858 + break; 1.859 + } 1.860 + att = sftk_FindAttribute(key,CKA_VALUE); 1.861 + if (att == NULL) { 1.862 + crv = CKR_KEY_HANDLE_INVALID; 1.863 + break; 1.864 + } 1.865 + context->cipherInfo = 1.866 + RC4_CreateContext((unsigned char*)att->attrib.pValue, 1.867 + att->attrib.ulValueLen); 1.868 + sftk_FreeAttribute(att); 1.869 + if (context->cipherInfo == NULL) { 1.870 + crv = CKR_HOST_MEMORY; /* WRONG !!! */ 1.871 + break; 1.872 + } 1.873 + context->update = (SFTKCipher) (isEncrypt ? RC4_Encrypt : RC4_Decrypt); 1.874 + context->destroy = (SFTKDestroy) RC4_DestroyContext; 1.875 + break; 1.876 + case CKM_CDMF_CBC_PAD: 1.877 + context->doPad = PR_TRUE; 1.878 + /* fall thru */ 1.879 + case CKM_CDMF_ECB: 1.880 + case CKM_CDMF_CBC: 1.881 + if (key_type != CKK_CDMF) { 1.882 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.883 + break; 1.884 + } 1.885 + t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC; 1.886 + if (crv != CKR_OK) break; 1.887 + goto finish_des; 1.888 + case CKM_DES_ECB: 1.889 + if (key_type != CKK_DES) { 1.890 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.891 + break; 1.892 + } 1.893 + t = NSS_DES; 1.894 + goto finish_des; 1.895 + case CKM_DES_CBC_PAD: 1.896 + context->doPad = PR_TRUE; 1.897 + /* fall thru */ 1.898 + case CKM_DES_CBC: 1.899 + if (key_type != CKK_DES) { 1.900 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.901 + break; 1.902 + } 1.903 + t = NSS_DES_CBC; 1.904 + goto finish_des; 1.905 + case CKM_DES3_ECB: 1.906 + if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { 1.907 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.908 + break; 1.909 + } 1.910 + t = NSS_DES_EDE3; 1.911 + goto finish_des; 1.912 + case CKM_DES3_CBC_PAD: 1.913 + context->doPad = PR_TRUE; 1.914 + /* fall thru */ 1.915 + case CKM_DES3_CBC: 1.916 + if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { 1.917 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.918 + break; 1.919 + } 1.920 + t = NSS_DES_EDE3_CBC; 1.921 +finish_des: 1.922 + context->blockSize = 8; 1.923 + att = sftk_FindAttribute(key,CKA_VALUE); 1.924 + if (att == NULL) { 1.925 + crv = CKR_KEY_HANDLE_INVALID; 1.926 + break; 1.927 + } 1.928 + if (key_type == CKK_DES2 && 1.929 + (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) { 1.930 + /* extend DES2 key to DES3 key. */ 1.931 + memcpy(newdeskey, att->attrib.pValue, 16); 1.932 + memcpy(newdeskey + 16, newdeskey, 8); 1.933 + useNewKey=PR_TRUE; 1.934 + } else if (key_type == CKK_CDMF) { 1.935 + crv = sftk_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey); 1.936 + if (crv != CKR_OK) { 1.937 + sftk_FreeAttribute(att); 1.938 + break; 1.939 + } 1.940 + useNewKey=PR_TRUE; 1.941 + } 1.942 + context->cipherInfo = DES_CreateContext( 1.943 + useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue, 1.944 + (unsigned char*)pMechanism->pParameter,t, isEncrypt); 1.945 + if (useNewKey) 1.946 + memset(newdeskey, 0, sizeof newdeskey); 1.947 + sftk_FreeAttribute(att); 1.948 + if (context->cipherInfo == NULL) { 1.949 + crv = CKR_HOST_MEMORY; 1.950 + break; 1.951 + } 1.952 + context->update = (SFTKCipher) (isEncrypt ? DES_Encrypt : DES_Decrypt); 1.953 + context->destroy = (SFTKDestroy) DES_DestroyContext; 1.954 + break; 1.955 + case CKM_SEED_CBC_PAD: 1.956 + context->doPad = PR_TRUE; 1.957 + /* fall thru */ 1.958 + case CKM_SEED_CBC: 1.959 + if (!pMechanism->pParameter || 1.960 + pMechanism->ulParameterLen != 16) { 1.961 + crv = CKR_MECHANISM_PARAM_INVALID; 1.962 + break; 1.963 + } 1.964 + /* fall thru */ 1.965 + case CKM_SEED_ECB: 1.966 + context->blockSize = 16; 1.967 + if (key_type != CKK_SEED) { 1.968 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.969 + break; 1.970 + } 1.971 + att = sftk_FindAttribute(key,CKA_VALUE); 1.972 + if (att == NULL) { 1.973 + crv = CKR_KEY_HANDLE_INVALID; 1.974 + break; 1.975 + } 1.976 + context->cipherInfo = SEED_CreateContext( 1.977 + (unsigned char*)att->attrib.pValue, 1.978 + (unsigned char*)pMechanism->pParameter, 1.979 + pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC, 1.980 + isEncrypt); 1.981 + sftk_FreeAttribute(att); 1.982 + if (context->cipherInfo == NULL) { 1.983 + crv = CKR_HOST_MEMORY; 1.984 + break; 1.985 + } 1.986 + context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt); 1.987 + context->destroy = (SFTKDestroy) SEED_DestroyContext; 1.988 + break; 1.989 + 1.990 + case CKM_CAMELLIA_CBC_PAD: 1.991 + context->doPad = PR_TRUE; 1.992 + /* fall thru */ 1.993 + case CKM_CAMELLIA_CBC: 1.994 + if (!pMechanism->pParameter || 1.995 + pMechanism->ulParameterLen != 16) { 1.996 + crv = CKR_MECHANISM_PARAM_INVALID; 1.997 + break; 1.998 + } 1.999 + /* fall thru */ 1.1000 + case CKM_CAMELLIA_ECB: 1.1001 + context->blockSize = 16; 1.1002 + if (key_type != CKK_CAMELLIA) { 1.1003 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.1004 + break; 1.1005 + } 1.1006 + att = sftk_FindAttribute(key,CKA_VALUE); 1.1007 + if (att == NULL) { 1.1008 + crv = CKR_KEY_HANDLE_INVALID; 1.1009 + break; 1.1010 + } 1.1011 + context->cipherInfo = Camellia_CreateContext( 1.1012 + (unsigned char*)att->attrib.pValue, 1.1013 + (unsigned char*)pMechanism->pParameter, 1.1014 + pMechanism->mechanism == 1.1015 + CKM_CAMELLIA_ECB ? NSS_CAMELLIA : NSS_CAMELLIA_CBC, 1.1016 + isEncrypt, att->attrib.ulValueLen); 1.1017 + sftk_FreeAttribute(att); 1.1018 + if (context->cipherInfo == NULL) { 1.1019 + crv = CKR_HOST_MEMORY; 1.1020 + break; 1.1021 + } 1.1022 + context->update = (SFTKCipher) (isEncrypt ? 1.1023 + Camellia_Encrypt : Camellia_Decrypt); 1.1024 + context->destroy = (SFTKDestroy) Camellia_DestroyContext; 1.1025 + break; 1.1026 + 1.1027 + case CKM_AES_CBC_PAD: 1.1028 + context->doPad = PR_TRUE; 1.1029 + /* fall thru */ 1.1030 + case CKM_AES_ECB: 1.1031 + case CKM_AES_CBC: 1.1032 + context->blockSize = 16; 1.1033 + case CKM_AES_CTS: 1.1034 + case CKM_AES_CTR: 1.1035 + case CKM_AES_GCM: 1.1036 + if (pMechanism->mechanism == CKM_AES_GCM) { 1.1037 + context->multi = PR_FALSE; 1.1038 + } 1.1039 + if (key_type != CKK_AES) { 1.1040 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.1041 + break; 1.1042 + } 1.1043 + att = sftk_FindAttribute(key,CKA_VALUE); 1.1044 + if (att == NULL) { 1.1045 + crv = CKR_KEY_HANDLE_INVALID; 1.1046 + break; 1.1047 + } 1.1048 + context->cipherInfo = AES_CreateContext( 1.1049 + (unsigned char*)att->attrib.pValue, 1.1050 + (unsigned char*)pMechanism->pParameter, 1.1051 + sftk_aes_mode(pMechanism->mechanism), 1.1052 + isEncrypt, att->attrib.ulValueLen, 16); 1.1053 + sftk_FreeAttribute(att); 1.1054 + if (context->cipherInfo == NULL) { 1.1055 + crv = CKR_HOST_MEMORY; 1.1056 + break; 1.1057 + } 1.1058 + context->update = (SFTKCipher) (isEncrypt ? AES_Encrypt : AES_Decrypt); 1.1059 + context->destroy = (SFTKDestroy) AES_DestroyContext; 1.1060 + break; 1.1061 + 1.1062 + case CKM_NETSCAPE_AES_KEY_WRAP_PAD: 1.1063 + context->doPad = PR_TRUE; 1.1064 + /* fall thru */ 1.1065 + case CKM_NETSCAPE_AES_KEY_WRAP: 1.1066 + context->multi = PR_FALSE; 1.1067 + context->blockSize = 8; 1.1068 + if (key_type != CKK_AES) { 1.1069 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.1070 + break; 1.1071 + } 1.1072 + att = sftk_FindAttribute(key,CKA_VALUE); 1.1073 + if (att == NULL) { 1.1074 + crv = CKR_KEY_HANDLE_INVALID; 1.1075 + break; 1.1076 + } 1.1077 + context->cipherInfo = AESKeyWrap_CreateContext( 1.1078 + (unsigned char*)att->attrib.pValue, 1.1079 + (unsigned char*)pMechanism->pParameter, 1.1080 + isEncrypt, att->attrib.ulValueLen); 1.1081 + sftk_FreeAttribute(att); 1.1082 + if (context->cipherInfo == NULL) { 1.1083 + crv = CKR_HOST_MEMORY; 1.1084 + break; 1.1085 + } 1.1086 + context->update = (SFTKCipher) (isEncrypt ? AESKeyWrap_Encrypt 1.1087 + : AESKeyWrap_Decrypt); 1.1088 + context->destroy = (SFTKDestroy) AESKeyWrap_DestroyContext; 1.1089 + break; 1.1090 + 1.1091 + default: 1.1092 + crv = CKR_MECHANISM_INVALID; 1.1093 + break; 1.1094 + } 1.1095 + 1.1096 + if (crv != CKR_OK) { 1.1097 + sftk_FreeContext(context); 1.1098 + sftk_FreeSession(session); 1.1099 + return crv; 1.1100 + } 1.1101 + sftk_SetContextByType(session, contextType, context); 1.1102 + sftk_FreeSession(session); 1.1103 + return CKR_OK; 1.1104 +} 1.1105 + 1.1106 +/* NSC_EncryptInit initializes an encryption operation. */ 1.1107 +CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession, 1.1108 + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) 1.1109 +{ 1.1110 + CHECK_FORK(); 1.1111 + return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT, 1.1112 + SFTK_ENCRYPT, PR_TRUE); 1.1113 +} 1.1114 + 1.1115 +/* NSC_EncryptUpdate continues a multiple-part encryption operation. */ 1.1116 +CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession, 1.1117 + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, 1.1118 + CK_ULONG_PTR pulEncryptedPartLen) 1.1119 +{ 1.1120 + SFTKSessionContext *context; 1.1121 + unsigned int outlen,i; 1.1122 + unsigned int padoutlen = 0; 1.1123 + unsigned int maxout = *pulEncryptedPartLen; 1.1124 + CK_RV crv; 1.1125 + SECStatus rv; 1.1126 + 1.1127 + CHECK_FORK(); 1.1128 + 1.1129 + /* make sure we're legal */ 1.1130 + crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,NULL); 1.1131 + if (crv != CKR_OK) return crv; 1.1132 + 1.1133 + if (!pEncryptedPart) { 1.1134 + if (context->doPad) { 1.1135 + CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength; 1.1136 + CK_ULONG blocksToSend = totalDataAvailable/context->blockSize; 1.1137 + 1.1138 + *pulEncryptedPartLen = blocksToSend * context->blockSize; 1.1139 + return CKR_OK; 1.1140 + } 1.1141 + *pulEncryptedPartLen = ulPartLen; 1.1142 + return CKR_OK; 1.1143 + } 1.1144 + 1.1145 + /* do padding */ 1.1146 + if (context->doPad) { 1.1147 + /* deal with previous buffered data */ 1.1148 + if (context->padDataLength != 0) { 1.1149 + /* fill in the padded to a full block size */ 1.1150 + for (i=context->padDataLength; 1.1151 + (ulPartLen != 0) && i < context->blockSize; i++) { 1.1152 + context->padBuf[i] = *pPart++; 1.1153 + ulPartLen--; 1.1154 + context->padDataLength++; 1.1155 + } 1.1156 + 1.1157 + /* not enough data to encrypt yet? then return */ 1.1158 + if (context->padDataLength != context->blockSize) { 1.1159 + *pulEncryptedPartLen = 0; 1.1160 + return CKR_OK; 1.1161 + } 1.1162 + /* encrypt the current padded data */ 1.1163 + rv = (*context->update)(context->cipherInfo, pEncryptedPart, 1.1164 + &padoutlen, context->blockSize, context->padBuf, 1.1165 + context->blockSize); 1.1166 + if (rv != SECSuccess) { 1.1167 + return sftk_MapCryptError(PORT_GetError()); 1.1168 + } 1.1169 + pEncryptedPart += padoutlen; 1.1170 + maxout -= padoutlen; 1.1171 + } 1.1172 + /* save the residual */ 1.1173 + context->padDataLength = ulPartLen % context->blockSize; 1.1174 + if (context->padDataLength) { 1.1175 + PORT_Memcpy(context->padBuf, 1.1176 + &pPart[ulPartLen-context->padDataLength], 1.1177 + context->padDataLength); 1.1178 + ulPartLen -= context->padDataLength; 1.1179 + } 1.1180 + /* if we've exhausted our new buffer, we're done */ 1.1181 + if (ulPartLen == 0) { 1.1182 + *pulEncryptedPartLen = padoutlen; 1.1183 + return CKR_OK; 1.1184 + } 1.1185 + } 1.1186 + 1.1187 + 1.1188 + /* do it: NOTE: this assumes buf size in is >= buf size out! */ 1.1189 + rv = (*context->update)(context->cipherInfo,pEncryptedPart, 1.1190 + &outlen, maxout, pPart, ulPartLen); 1.1191 + *pulEncryptedPartLen = (CK_ULONG) (outlen + padoutlen); 1.1192 + return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); 1.1193 +} 1.1194 + 1.1195 + 1.1196 +/* NSC_EncryptFinal finishes a multiple-part encryption operation. */ 1.1197 +CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession, 1.1198 + CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) 1.1199 +{ 1.1200 + SFTKSession *session; 1.1201 + SFTKSessionContext *context; 1.1202 + unsigned int outlen,i; 1.1203 + unsigned int maxout = *pulLastEncryptedPartLen; 1.1204 + CK_RV crv; 1.1205 + SECStatus rv = SECSuccess; 1.1206 + PRBool contextFinished = PR_TRUE; 1.1207 + 1.1208 + CHECK_FORK(); 1.1209 + 1.1210 + /* make sure we're legal */ 1.1211 + crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,&session); 1.1212 + if (crv != CKR_OK) return crv; 1.1213 + 1.1214 + *pulLastEncryptedPartLen = 0; 1.1215 + if (!pLastEncryptedPart) { 1.1216 + /* caller is checking the amount of remaining data */ 1.1217 + if (context->blockSize > 0 && context->doPad) { 1.1218 + *pulLastEncryptedPartLen = context->blockSize; 1.1219 + contextFinished = PR_FALSE; /* still have padding to go */ 1.1220 + } 1.1221 + goto finish; 1.1222 + } 1.1223 + 1.1224 + /* do padding */ 1.1225 + if (context->doPad) { 1.1226 + unsigned char padbyte = (unsigned char) 1.1227 + (context->blockSize - context->padDataLength); 1.1228 + /* fill out rest of pad buffer with pad magic*/ 1.1229 + for (i=context->padDataLength; i < context->blockSize; i++) { 1.1230 + context->padBuf[i] = padbyte; 1.1231 + } 1.1232 + rv = (*context->update)(context->cipherInfo,pLastEncryptedPart, 1.1233 + &outlen, maxout, context->padBuf, context->blockSize); 1.1234 + if (rv == SECSuccess) *pulLastEncryptedPartLen = (CK_ULONG) outlen; 1.1235 + } 1.1236 + 1.1237 +finish: 1.1238 + if (contextFinished) 1.1239 + sftk_TerminateOp( session, SFTK_ENCRYPT, context ); 1.1240 + sftk_FreeSession(session); 1.1241 + return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); 1.1242 +} 1.1243 + 1.1244 +/* NSC_Encrypt encrypts single-part data. */ 1.1245 +CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, 1.1246 + CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, 1.1247 + CK_ULONG_PTR pulEncryptedDataLen) 1.1248 +{ 1.1249 + SFTKSession *session; 1.1250 + SFTKSessionContext *context; 1.1251 + unsigned int outlen; 1.1252 + unsigned int maxoutlen = *pulEncryptedDataLen; 1.1253 + CK_RV crv; 1.1254 + CK_RV crv2; 1.1255 + SECStatus rv = SECSuccess; 1.1256 + SECItem pText; 1.1257 + 1.1258 + pText.type = siBuffer; 1.1259 + pText.data = pData; 1.1260 + pText.len = ulDataLen; 1.1261 + 1.1262 + CHECK_FORK(); 1.1263 + 1.1264 + /* make sure we're legal */ 1.1265 + crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,&session); 1.1266 + if (crv != CKR_OK) return crv; 1.1267 + 1.1268 + if (!pEncryptedData) { 1.1269 + *pulEncryptedDataLen = context->rsa ? context->maxLen : 1.1270 + ulDataLen + 2 * context->blockSize; 1.1271 + goto finish; 1.1272 + } 1.1273 + 1.1274 + if (context->doPad) { 1.1275 + if (context->multi) { 1.1276 + CK_ULONG finalLen; 1.1277 + /* padding is fairly complicated, have the update and final 1.1278 + * code deal with it */ 1.1279 + sftk_FreeSession(session); 1.1280 + crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData, 1.1281 + pulEncryptedDataLen); 1.1282 + if (crv != CKR_OK) 1.1283 + *pulEncryptedDataLen = 0; 1.1284 + maxoutlen -= *pulEncryptedDataLen; 1.1285 + pEncryptedData += *pulEncryptedDataLen; 1.1286 + finalLen = maxoutlen; 1.1287 + crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen); 1.1288 + if (crv2 == CKR_OK) 1.1289 + *pulEncryptedDataLen += finalLen; 1.1290 + return crv == CKR_OK ? crv2 : crv; 1.1291 + } 1.1292 + /* doPad without multi means that padding must be done on the first 1.1293 + ** and only update. There will be no final. 1.1294 + */ 1.1295 + PORT_Assert(context->blockSize > 1); 1.1296 + if (context->blockSize > 1) { 1.1297 + CK_ULONG remainder = ulDataLen % context->blockSize; 1.1298 + CK_ULONG padding = context->blockSize - remainder; 1.1299 + pText.len += padding; 1.1300 + pText.data = PORT_ZAlloc(pText.len); 1.1301 + if (pText.data) { 1.1302 + memcpy(pText.data, pData, ulDataLen); 1.1303 + memset(pText.data + ulDataLen, padding, padding); 1.1304 + } else { 1.1305 + crv = CKR_HOST_MEMORY; 1.1306 + goto fail; 1.1307 + } 1.1308 + } 1.1309 + } 1.1310 + 1.1311 + /* do it: NOTE: this assumes buf size is big enough. */ 1.1312 + rv = (*context->update)(context->cipherInfo, pEncryptedData, 1.1313 + &outlen, maxoutlen, pText.data, pText.len); 1.1314 + crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); 1.1315 + *pulEncryptedDataLen = (CK_ULONG) outlen; 1.1316 + if (pText.data != pData) 1.1317 + PORT_ZFree(pText.data, pText.len); 1.1318 +fail: 1.1319 + sftk_TerminateOp( session, SFTK_ENCRYPT, context ); 1.1320 +finish: 1.1321 + sftk_FreeSession(session); 1.1322 + 1.1323 + return crv; 1.1324 +} 1.1325 + 1.1326 + 1.1327 +/* 1.1328 + ************** Crypto Functions: Decrypt ************************ 1.1329 + */ 1.1330 + 1.1331 +/* NSC_DecryptInit initializes a decryption operation. */ 1.1332 +CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession, 1.1333 + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) 1.1334 +{ 1.1335 + CHECK_FORK(); 1.1336 + return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT, 1.1337 + SFTK_DECRYPT, PR_FALSE); 1.1338 +} 1.1339 + 1.1340 +/* NSC_DecryptUpdate continues a multiple-part decryption operation. */ 1.1341 +CK_RV NSC_DecryptUpdate(CK_SESSION_HANDLE hSession, 1.1342 + CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, 1.1343 + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) 1.1344 +{ 1.1345 + SFTKSessionContext *context; 1.1346 + unsigned int padoutlen = 0; 1.1347 + unsigned int outlen; 1.1348 + unsigned int maxout = *pulPartLen; 1.1349 + CK_RV crv; 1.1350 + SECStatus rv; 1.1351 + 1.1352 + CHECK_FORK(); 1.1353 + 1.1354 + /* make sure we're legal */ 1.1355 + crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,NULL); 1.1356 + if (crv != CKR_OK) return crv; 1.1357 + 1.1358 + /* this can only happen on an NSS programming error */ 1.1359 + PORT_Assert((context->padDataLength == 0) 1.1360 + || context->padDataLength == context->blockSize); 1.1361 + 1.1362 + 1.1363 + if (context->doPad) { 1.1364 + /* Check the data length for block ciphers. If we are padding, 1.1365 + * then we must be using a block cipher. In the non-padding case 1.1366 + * the error will be returned by the underlying decryption 1.1367 + * function when we do the actual decrypt. We need to do the 1.1368 + * check here to avoid returning a negative length to the caller 1.1369 + * or reading before the beginning of the pEncryptedPart buffer. 1.1370 + */ 1.1371 + if ((ulEncryptedPartLen == 0) || 1.1372 + (ulEncryptedPartLen % context->blockSize) != 0) { 1.1373 + return CKR_ENCRYPTED_DATA_LEN_RANGE; 1.1374 + } 1.1375 + } 1.1376 + 1.1377 + if (!pPart) { 1.1378 + if (context->doPad) { 1.1379 + *pulPartLen = 1.1380 + ulEncryptedPartLen + context->padDataLength - context->blockSize; 1.1381 + return CKR_OK; 1.1382 + } 1.1383 + /* for stream ciphers there is are no constraints on ulEncryptedPartLen. 1.1384 + * for block ciphers, it must be a multiple of blockSize. The error is 1.1385 + * detected when this function is called again do decrypt the output. 1.1386 + */ 1.1387 + *pulPartLen = ulEncryptedPartLen; 1.1388 + return CKR_OK; 1.1389 + } 1.1390 + 1.1391 + if (context->doPad) { 1.1392 + /* first decrypt our saved buffer */ 1.1393 + if (context->padDataLength != 0) { 1.1394 + rv = (*context->update)(context->cipherInfo, pPart, &padoutlen, 1.1395 + maxout, context->padBuf, context->blockSize); 1.1396 + if (rv != SECSuccess) return sftk_MapDecryptError(PORT_GetError()); 1.1397 + pPart += padoutlen; 1.1398 + maxout -= padoutlen; 1.1399 + } 1.1400 + /* now save the final block for the next decrypt or the final */ 1.1401 + PORT_Memcpy(context->padBuf,&pEncryptedPart[ulEncryptedPartLen - 1.1402 + context->blockSize], context->blockSize); 1.1403 + context->padDataLength = context->blockSize; 1.1404 + ulEncryptedPartLen -= context->padDataLength; 1.1405 + } 1.1406 + 1.1407 + /* do it: NOTE: this assumes buf size in is >= buf size out! */ 1.1408 + rv = (*context->update)(context->cipherInfo,pPart, &outlen, 1.1409 + maxout, pEncryptedPart, ulEncryptedPartLen); 1.1410 + *pulPartLen = (CK_ULONG) (outlen + padoutlen); 1.1411 + return (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); 1.1412 +} 1.1413 + 1.1414 + 1.1415 +/* NSC_DecryptFinal finishes a multiple-part decryption operation. */ 1.1416 +CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession, 1.1417 + CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) 1.1418 +{ 1.1419 + SFTKSession *session; 1.1420 + SFTKSessionContext *context; 1.1421 + unsigned int outlen; 1.1422 + unsigned int maxout = *pulLastPartLen; 1.1423 + CK_RV crv; 1.1424 + SECStatus rv = SECSuccess; 1.1425 + 1.1426 + CHECK_FORK(); 1.1427 + 1.1428 + /* make sure we're legal */ 1.1429 + crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,&session); 1.1430 + if (crv != CKR_OK) return crv; 1.1431 + 1.1432 + *pulLastPartLen = 0; 1.1433 + if (!pLastPart) { 1.1434 + /* caller is checking the amount of remaining data */ 1.1435 + if (context->padDataLength > 0) { 1.1436 + *pulLastPartLen = context->padDataLength; 1.1437 + } 1.1438 + goto finish; 1.1439 + } 1.1440 + 1.1441 + if (context->doPad) { 1.1442 + /* decrypt our saved buffer */ 1.1443 + if (context->padDataLength != 0) { 1.1444 + /* this assumes that pLastPart is big enough to hold the *whole* 1.1445 + * buffer!!! */ 1.1446 + rv = (*context->update)(context->cipherInfo, pLastPart, &outlen, 1.1447 + maxout, context->padBuf, context->blockSize); 1.1448 + if (rv != SECSuccess) { 1.1449 + crv = sftk_MapDecryptError(PORT_GetError()); 1.1450 + } else { 1.1451 + unsigned int padSize = 1.1452 + (unsigned int) pLastPart[context->blockSize-1]; 1.1453 + if ((padSize > context->blockSize) || (padSize == 0)) { 1.1454 + crv = CKR_ENCRYPTED_DATA_INVALID; 1.1455 + } else { 1.1456 + unsigned int i; 1.1457 + unsigned int badPadding = 0; /* used as a boolean */ 1.1458 + for (i = 0; i < padSize; i++) { 1.1459 + badPadding |= 1.1460 + (unsigned int) pLastPart[context->blockSize-1-i] ^ 1.1461 + padSize; 1.1462 + } 1.1463 + if (badPadding) { 1.1464 + crv = CKR_ENCRYPTED_DATA_INVALID; 1.1465 + } else { 1.1466 + *pulLastPartLen = outlen - padSize; 1.1467 + } 1.1468 + } 1.1469 + } 1.1470 + } 1.1471 + } 1.1472 + 1.1473 + sftk_TerminateOp( session, SFTK_DECRYPT, context ); 1.1474 +finish: 1.1475 + sftk_FreeSession(session); 1.1476 + return crv; 1.1477 +} 1.1478 + 1.1479 +/* NSC_Decrypt decrypts encrypted data in a single part. */ 1.1480 +CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession, 1.1481 + CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData, 1.1482 + CK_ULONG_PTR pulDataLen) 1.1483 +{ 1.1484 + SFTKSession *session; 1.1485 + SFTKSessionContext *context; 1.1486 + unsigned int outlen; 1.1487 + unsigned int maxoutlen = *pulDataLen; 1.1488 + CK_RV crv; 1.1489 + CK_RV crv2; 1.1490 + SECStatus rv = SECSuccess; 1.1491 + 1.1492 + CHECK_FORK(); 1.1493 + 1.1494 + /* make sure we're legal */ 1.1495 + crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_FALSE,&session); 1.1496 + if (crv != CKR_OK) return crv; 1.1497 + 1.1498 + if (!pData) { 1.1499 + *pulDataLen = ulEncryptedDataLen + context->blockSize; 1.1500 + goto finish; 1.1501 + } 1.1502 + 1.1503 + if (context->doPad && context->multi) { 1.1504 + CK_ULONG finalLen; 1.1505 + /* padding is fairly complicated, have the update and final 1.1506 + * code deal with it */ 1.1507 + sftk_FreeSession(session); 1.1508 + crv = NSC_DecryptUpdate(hSession,pEncryptedData,ulEncryptedDataLen, 1.1509 + pData, pulDataLen); 1.1510 + if (crv != CKR_OK) 1.1511 + *pulDataLen = 0; 1.1512 + maxoutlen -= *pulDataLen; 1.1513 + pData += *pulDataLen; 1.1514 + finalLen = maxoutlen; 1.1515 + crv2 = NSC_DecryptFinal(hSession, pData, &finalLen); 1.1516 + if (crv2 == CKR_OK) 1.1517 + *pulDataLen += finalLen; 1.1518 + return crv == CKR_OK ? crv2 : crv; 1.1519 + } 1.1520 + 1.1521 + rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, 1.1522 + pEncryptedData, ulEncryptedDataLen); 1.1523 + /* XXX need to do MUCH better error mapping than this. */ 1.1524 + crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); 1.1525 + if (rv == SECSuccess && context->doPad) { 1.1526 + unsigned int padding = pData[outlen - 1]; 1.1527 + if (padding > context->blockSize || !padding) { 1.1528 + crv = CKR_ENCRYPTED_DATA_INVALID; 1.1529 + } else { 1.1530 + unsigned int i; 1.1531 + unsigned int badPadding = 0; /* used as a boolean */ 1.1532 + for (i = 0; i < padding; i++) { 1.1533 + badPadding |= (unsigned int) pData[outlen - 1 - i] ^ padding; 1.1534 + } 1.1535 + if (badPadding) { 1.1536 + crv = CKR_ENCRYPTED_DATA_INVALID; 1.1537 + } else { 1.1538 + outlen -= padding; 1.1539 + } 1.1540 + } 1.1541 + } 1.1542 + *pulDataLen = (CK_ULONG) outlen; 1.1543 + sftk_TerminateOp( session, SFTK_DECRYPT, context ); 1.1544 +finish: 1.1545 + sftk_FreeSession(session); 1.1546 + return crv; 1.1547 +} 1.1548 + 1.1549 + 1.1550 + 1.1551 +/* 1.1552 + ************** Crypto Functions: Digest (HASH) ************************ 1.1553 + */ 1.1554 + 1.1555 +/* NSC_DigestInit initializes a message-digesting operation. */ 1.1556 +CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession, 1.1557 + CK_MECHANISM_PTR pMechanism) 1.1558 +{ 1.1559 + SFTKSession *session; 1.1560 + SFTKSessionContext *context; 1.1561 + CK_RV crv = CKR_OK; 1.1562 + 1.1563 + CHECK_FORK(); 1.1564 + 1.1565 + session = sftk_SessionFromHandle(hSession); 1.1566 + if (session == NULL) 1.1567 + return CKR_SESSION_HANDLE_INVALID; 1.1568 + crv = sftk_InitGeneric(session,&context,SFTK_HASH,NULL,0,NULL, 0, 0); 1.1569 + if (crv != CKR_OK) { 1.1570 + sftk_FreeSession(session); 1.1571 + return crv; 1.1572 + } 1.1573 + 1.1574 + 1.1575 +#define INIT_MECH(mech,mmm) \ 1.1576 + case mech: { \ 1.1577 + mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \ 1.1578 + context->cipherInfo = (void *)mmm ## _ctx; \ 1.1579 + context->cipherInfoLen = mmm ## _FlattenSize(mmm ## _ctx); \ 1.1580 + context->currentMech = mech; \ 1.1581 + context->hashUpdate = (SFTKHash) mmm ## _Update; \ 1.1582 + context->end = (SFTKEnd) mmm ## _End; \ 1.1583 + context->destroy = (SFTKDestroy) mmm ## _DestroyContext; \ 1.1584 + context->maxLen = mmm ## _LENGTH; \ 1.1585 + if (mmm ## _ctx) \ 1.1586 + mmm ## _Begin(mmm ## _ctx); \ 1.1587 + else \ 1.1588 + crv = CKR_HOST_MEMORY; \ 1.1589 + break; \ 1.1590 + } 1.1591 + 1.1592 + switch(pMechanism->mechanism) { 1.1593 + INIT_MECH(CKM_MD2, MD2) 1.1594 + INIT_MECH(CKM_MD5, MD5) 1.1595 + INIT_MECH(CKM_SHA_1, SHA1) 1.1596 + INIT_MECH(CKM_SHA224, SHA224) 1.1597 + INIT_MECH(CKM_SHA256, SHA256) 1.1598 + INIT_MECH(CKM_SHA384, SHA384) 1.1599 + INIT_MECH(CKM_SHA512, SHA512) 1.1600 + 1.1601 + default: 1.1602 + crv = CKR_MECHANISM_INVALID; 1.1603 + break; 1.1604 + } 1.1605 + 1.1606 + if (crv != CKR_OK) { 1.1607 + sftk_FreeContext(context); 1.1608 + sftk_FreeSession(session); 1.1609 + return crv; 1.1610 + } 1.1611 + sftk_SetContextByType(session, SFTK_HASH, context); 1.1612 + sftk_FreeSession(session); 1.1613 + return CKR_OK; 1.1614 +} 1.1615 + 1.1616 + 1.1617 +/* NSC_Digest digests data in a single part. */ 1.1618 +CK_RV NSC_Digest(CK_SESSION_HANDLE hSession, 1.1619 + CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, 1.1620 + CK_ULONG_PTR pulDigestLen) 1.1621 +{ 1.1622 + SFTKSession *session; 1.1623 + SFTKSessionContext *context; 1.1624 + unsigned int digestLen; 1.1625 + unsigned int maxout = *pulDigestLen; 1.1626 + CK_RV crv; 1.1627 + 1.1628 + CHECK_FORK(); 1.1629 + 1.1630 + /* make sure we're legal */ 1.1631 + crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_FALSE,&session); 1.1632 + if (crv != CKR_OK) return crv; 1.1633 + 1.1634 + if (pDigest == NULL) { 1.1635 + *pulDigestLen = context->maxLen; 1.1636 + goto finish; 1.1637 + } 1.1638 + 1.1639 + /* do it: */ 1.1640 + (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen); 1.1641 + /* NOTE: this assumes buf size is bigenough for the algorithm */ 1.1642 + (*context->end)(context->cipherInfo, pDigest, &digestLen,maxout); 1.1643 + *pulDigestLen = digestLen; 1.1644 + 1.1645 + sftk_TerminateOp( session, SFTK_HASH, context ); 1.1646 +finish: 1.1647 + sftk_FreeSession(session); 1.1648 + return CKR_OK; 1.1649 +} 1.1650 + 1.1651 + 1.1652 +/* NSC_DigestUpdate continues a multiple-part message-digesting operation. */ 1.1653 +CK_RV NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, 1.1654 + CK_ULONG ulPartLen) 1.1655 +{ 1.1656 + SFTKSessionContext *context; 1.1657 + CK_RV crv; 1.1658 + 1.1659 + CHECK_FORK(); 1.1660 + 1.1661 + /* make sure we're legal */ 1.1662 + crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_TRUE,NULL); 1.1663 + if (crv != CKR_OK) return crv; 1.1664 + /* do it: */ 1.1665 + (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen); 1.1666 + return CKR_OK; 1.1667 +} 1.1668 + 1.1669 + 1.1670 +/* NSC_DigestFinal finishes a multiple-part message-digesting operation. */ 1.1671 +CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest, 1.1672 + CK_ULONG_PTR pulDigestLen) 1.1673 +{ 1.1674 + SFTKSession *session; 1.1675 + SFTKSessionContext *context; 1.1676 + unsigned int maxout = *pulDigestLen; 1.1677 + unsigned int digestLen; 1.1678 + CK_RV crv; 1.1679 + 1.1680 + CHECK_FORK(); 1.1681 + 1.1682 + /* make sure we're legal */ 1.1683 + crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); 1.1684 + if (crv != CKR_OK) return crv; 1.1685 + 1.1686 + if (pDigest != NULL) { 1.1687 + (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); 1.1688 + *pulDigestLen = digestLen; 1.1689 + sftk_TerminateOp( session, SFTK_HASH, context ); 1.1690 + } else { 1.1691 + *pulDigestLen = context->maxLen; 1.1692 + } 1.1693 + 1.1694 + sftk_FreeSession(session); 1.1695 + return CKR_OK; 1.1696 +} 1.1697 + 1.1698 +/* 1.1699 + * these helper functions are used by Generic Macing and Signing functions 1.1700 + * that use hashes as part of their operations. 1.1701 + */ 1.1702 +#define DOSUB(mmm) \ 1.1703 +static CK_RV \ 1.1704 +sftk_doSub ## mmm(SFTKSessionContext *context) { \ 1.1705 + mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \ 1.1706 + context->hashInfo = (void *) mmm ## _ctx; \ 1.1707 + context->hashUpdate = (SFTKHash) mmm ## _Update; \ 1.1708 + context->end = (SFTKEnd) mmm ## _End; \ 1.1709 + context->hashdestroy = (SFTKDestroy) mmm ## _DestroyContext; \ 1.1710 + if (!context->hashInfo) { \ 1.1711 + return CKR_HOST_MEMORY; \ 1.1712 + } \ 1.1713 + mmm ## _Begin( mmm ## _ctx ); \ 1.1714 + return CKR_OK; \ 1.1715 +} 1.1716 + 1.1717 +DOSUB(MD2) 1.1718 +DOSUB(MD5) 1.1719 +DOSUB(SHA1) 1.1720 +DOSUB(SHA224) 1.1721 +DOSUB(SHA256) 1.1722 +DOSUB(SHA384) 1.1723 +DOSUB(SHA512) 1.1724 + 1.1725 +static SECStatus 1.1726 +sftk_SignCopy( 1.1727 + CK_ULONG *copyLen, 1.1728 + void *out, unsigned int *outLength, 1.1729 + unsigned int maxLength, 1.1730 + const unsigned char *hashResult, 1.1731 + unsigned int hashResultLength) 1.1732 +{ 1.1733 + unsigned int toCopy = *copyLen; 1.1734 + if (toCopy > maxLength) { 1.1735 + toCopy = maxLength; 1.1736 + } 1.1737 + if (toCopy > hashResultLength) { 1.1738 + toCopy = hashResultLength; 1.1739 + } 1.1740 + memcpy(out, hashResult, toCopy); 1.1741 + if (outLength) { 1.1742 + *outLength = toCopy; 1.1743 + } 1.1744 + return SECSuccess; 1.1745 +} 1.1746 + 1.1747 +/* Verify is just a compare for HMAC */ 1.1748 +static SECStatus 1.1749 +sftk_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen, 1.1750 + unsigned char *hash, unsigned int hashLen) 1.1751 +{ 1.1752 + return (PORT_Memcmp(sig,hash,*copyLen) == 0) ? SECSuccess : SECFailure ; 1.1753 +} 1.1754 + 1.1755 +/* 1.1756 + * common HMAC initalization routine 1.1757 + */ 1.1758 +static CK_RV 1.1759 +sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash, 1.1760 + SFTKObject *key, CK_ULONG mac_size) 1.1761 +{ 1.1762 + SFTKAttribute *keyval; 1.1763 + HMACContext *HMACcontext; 1.1764 + CK_ULONG *intpointer; 1.1765 + const SECHashObject *hashObj = HASH_GetRawHashObject(hash); 1.1766 + PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID); 1.1767 + 1.1768 + /* required by FIPS 198 Section 4 */ 1.1769 + if (isFIPS && (mac_size < 4 || mac_size < hashObj->length/2)) { 1.1770 + return CKR_BUFFER_TOO_SMALL; 1.1771 + } 1.1772 + 1.1773 + keyval = sftk_FindAttribute(key,CKA_VALUE); 1.1774 + if (keyval == NULL) return CKR_KEY_SIZE_RANGE; 1.1775 + 1.1776 + HMACcontext = HMAC_Create(hashObj, 1.1777 + (const unsigned char*)keyval->attrib.pValue, 1.1778 + keyval->attrib.ulValueLen, isFIPS); 1.1779 + context->hashInfo = HMACcontext; 1.1780 + context->multi = PR_TRUE; 1.1781 + sftk_FreeAttribute(keyval); 1.1782 + if (context->hashInfo == NULL) { 1.1783 + if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) { 1.1784 + return CKR_KEY_SIZE_RANGE; 1.1785 + } 1.1786 + return CKR_HOST_MEMORY; 1.1787 + } 1.1788 + context->hashUpdate = (SFTKHash) HMAC_Update; 1.1789 + context->end = (SFTKEnd) HMAC_Finish; 1.1790 + 1.1791 + context->hashdestroy = (SFTKDestroy) HMAC_Destroy; 1.1792 + intpointer = PORT_New(CK_ULONG); 1.1793 + if (intpointer == NULL) { 1.1794 + return CKR_HOST_MEMORY; 1.1795 + } 1.1796 + *intpointer = mac_size; 1.1797 + context->cipherInfo = intpointer; 1.1798 + context->destroy = (SFTKDestroy) sftk_Space; 1.1799 + context->update = (SFTKCipher) sftk_SignCopy; 1.1800 + context->verify = (SFTKVerify) sftk_HMACCmp; 1.1801 + context->maxLen = hashObj->length; 1.1802 + HMAC_Begin(HMACcontext); 1.1803 + return CKR_OK; 1.1804 +} 1.1805 + 1.1806 +/* 1.1807 + * SSL Macing support. SSL Macs are inited, then update with the base 1.1808 + * hashing algorithm, then finalized in sign and verify 1.1809 + */ 1.1810 + 1.1811 +/* 1.1812 + * FROM SSL: 1.1813 + * 60 bytes is 3 times the maximum length MAC size that is supported. 1.1814 + * We probably should have one copy of this table. We still need this table 1.1815 + * in ssl to 'sign' the handshake hashes. 1.1816 + */ 1.1817 +static unsigned char ssl_pad_1 [60] = { 1.1818 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 1.1819 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 1.1820 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 1.1821 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 1.1822 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 1.1823 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 1.1824 + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 1.1825 + 0x36, 0x36, 0x36, 0x36 1.1826 +}; 1.1827 +static unsigned char ssl_pad_2 [60] = { 1.1828 + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 1.1829 + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 1.1830 + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 1.1831 + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 1.1832 + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 1.1833 + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 1.1834 + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 1.1835 + 0x5c, 0x5c, 0x5c, 0x5c 1.1836 +}; 1.1837 + 1.1838 +static SECStatus 1.1839 +sftk_SSLMACSign(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int *sigLen, 1.1840 + unsigned int maxLen,unsigned char *hash, unsigned int hashLen) 1.1841 +{ 1.1842 + unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; 1.1843 + unsigned int out; 1.1844 + 1.1845 + info->begin(info->hashContext); 1.1846 + info->update(info->hashContext,info->key,info->keySize); 1.1847 + info->update(info->hashContext,ssl_pad_2,info->padSize); 1.1848 + info->update(info->hashContext,hash,hashLen); 1.1849 + info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH); 1.1850 + PORT_Memcpy(sig,tmpBuf,info->macSize); 1.1851 + *sigLen = info->macSize; 1.1852 + return SECSuccess; 1.1853 +} 1.1854 + 1.1855 +static SECStatus 1.1856 +sftk_SSLMACVerify(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int sigLen, 1.1857 + unsigned char *hash, unsigned int hashLen) 1.1858 +{ 1.1859 + unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; 1.1860 + unsigned int out; 1.1861 + 1.1862 + info->begin(info->hashContext); 1.1863 + info->update(info->hashContext,info->key,info->keySize); 1.1864 + info->update(info->hashContext,ssl_pad_2,info->padSize); 1.1865 + info->update(info->hashContext,hash,hashLen); 1.1866 + info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH); 1.1867 + return (PORT_Memcmp(sig,tmpBuf,info->macSize) == 0) ? 1.1868 + SECSuccess : SECFailure; 1.1869 +} 1.1870 + 1.1871 +/* 1.1872 + * common HMAC initalization routine 1.1873 + */ 1.1874 +static CK_RV 1.1875 +sftk_doSSLMACInit(SFTKSessionContext *context,SECOidTag oid, 1.1876 + SFTKObject *key, CK_ULONG mac_size) 1.1877 +{ 1.1878 + SFTKAttribute *keyval; 1.1879 + SFTKBegin begin; 1.1880 + int padSize; 1.1881 + SFTKSSLMACInfo *sslmacinfo; 1.1882 + CK_RV crv = CKR_MECHANISM_INVALID; 1.1883 + 1.1884 + if (oid == SEC_OID_SHA1) { 1.1885 + crv = sftk_doSubSHA1(context); 1.1886 + if (crv != CKR_OK) return crv; 1.1887 + begin = (SFTKBegin) SHA1_Begin; 1.1888 + padSize = 40; 1.1889 + } else { 1.1890 + crv = sftk_doSubMD5(context); 1.1891 + if (crv != CKR_OK) return crv; 1.1892 + begin = (SFTKBegin) MD5_Begin; 1.1893 + padSize = 48; 1.1894 + } 1.1895 + context->multi = PR_TRUE; 1.1896 + 1.1897 + keyval = sftk_FindAttribute(key,CKA_VALUE); 1.1898 + if (keyval == NULL) return CKR_KEY_SIZE_RANGE; 1.1899 + 1.1900 + context->hashUpdate(context->hashInfo,keyval->attrib.pValue, 1.1901 + keyval->attrib.ulValueLen); 1.1902 + context->hashUpdate(context->hashInfo,ssl_pad_1,padSize); 1.1903 + sslmacinfo = (SFTKSSLMACInfo *) PORT_Alloc(sizeof(SFTKSSLMACInfo)); 1.1904 + if (sslmacinfo == NULL) { 1.1905 + sftk_FreeAttribute(keyval); 1.1906 + return CKR_HOST_MEMORY; 1.1907 + } 1.1908 + sslmacinfo->macSize = mac_size; 1.1909 + sslmacinfo->hashContext = context->hashInfo; 1.1910 + PORT_Memcpy(sslmacinfo->key,keyval->attrib.pValue, 1.1911 + keyval->attrib.ulValueLen); 1.1912 + sslmacinfo->keySize = keyval->attrib.ulValueLen; 1.1913 + sslmacinfo->begin = begin; 1.1914 + sslmacinfo->end = context->end; 1.1915 + sslmacinfo->update = context->hashUpdate; 1.1916 + sslmacinfo->padSize = padSize; 1.1917 + sftk_FreeAttribute(keyval); 1.1918 + context->cipherInfo = (void *) sslmacinfo; 1.1919 + context->destroy = (SFTKDestroy) sftk_Space; 1.1920 + context->update = (SFTKCipher) sftk_SSLMACSign; 1.1921 + context->verify = (SFTKVerify) sftk_SSLMACVerify; 1.1922 + context->maxLen = mac_size; 1.1923 + return CKR_OK; 1.1924 +} 1.1925 + 1.1926 +/* 1.1927 + ************** Crypto Functions: Sign ************************ 1.1928 + */ 1.1929 + 1.1930 +/** 1.1931 + * Check if We're using CBCMacing and initialize the session context if we are. 1.1932 + * @param contextType SFTK_SIGN or SFTK_VERIFY 1.1933 + * @param keyUsage check whether key allows this usage 1.1934 + */ 1.1935 +static CK_RV 1.1936 +sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 1.1937 + CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage, 1.1938 + SFTKContextType contextType) 1.1939 + 1.1940 +{ 1.1941 + CK_MECHANISM cbc_mechanism; 1.1942 + CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE; 1.1943 + CK_RC2_CBC_PARAMS rc2_params; 1.1944 +#if NSS_SOFTOKEN_DOES_RC5 1.1945 + CK_RC5_CBC_PARAMS rc5_params; 1.1946 + CK_RC5_MAC_GENERAL_PARAMS *rc5_mac; 1.1947 +#endif 1.1948 + unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE]; 1.1949 + SFTKSessionContext *context; 1.1950 + CK_RV crv; 1.1951 + unsigned int blockSize; 1.1952 + 1.1953 + switch (pMechanism->mechanism) { 1.1954 + case CKM_RC2_MAC_GENERAL: 1.1955 + mac_bytes = 1.1956 + ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; 1.1957 + /* fall through */ 1.1958 + case CKM_RC2_MAC: 1.1959 + /* this works because ulEffectiveBits is in the same place in both the 1.1960 + * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */ 1.1961 + rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *) 1.1962 + pMechanism->pParameter)->ulEffectiveBits; 1.1963 + PORT_Memset(rc2_params.iv,0,sizeof(rc2_params.iv)); 1.1964 + cbc_mechanism.mechanism = CKM_RC2_CBC; 1.1965 + cbc_mechanism.pParameter = &rc2_params; 1.1966 + cbc_mechanism.ulParameterLen = sizeof(rc2_params); 1.1967 + blockSize = 8; 1.1968 + break; 1.1969 +#if NSS_SOFTOKEN_DOES_RC5 1.1970 + case CKM_RC5_MAC_GENERAL: 1.1971 + mac_bytes = 1.1972 + ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; 1.1973 + /* fall through */ 1.1974 + case CKM_RC5_MAC: 1.1975 + /* this works because ulEffectiveBits is in the same place in both the 1.1976 + * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */ 1.1977 + rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter; 1.1978 + rc5_params.ulWordsize = rc5_mac->ulWordsize; 1.1979 + rc5_params.ulRounds = rc5_mac->ulRounds; 1.1980 + rc5_params.pIv = ivBlock; 1.1981 + if( (blockSize = rc5_mac->ulWordsize*2) > SFTK_MAX_BLOCK_SIZE ) 1.1982 + return CKR_MECHANISM_PARAM_INVALID; 1.1983 + rc5_params.ulIvLen = blockSize; 1.1984 + PORT_Memset(ivBlock,0,blockSize); 1.1985 + cbc_mechanism.mechanism = CKM_RC5_CBC; 1.1986 + cbc_mechanism.pParameter = &rc5_params; 1.1987 + cbc_mechanism.ulParameterLen = sizeof(rc5_params); 1.1988 + break; 1.1989 +#endif 1.1990 + /* add cast and idea later */ 1.1991 + case CKM_DES_MAC_GENERAL: 1.1992 + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; 1.1993 + /* fall through */ 1.1994 + case CKM_DES_MAC: 1.1995 + blockSize = 8; 1.1996 + PORT_Memset(ivBlock,0,blockSize); 1.1997 + cbc_mechanism.mechanism = CKM_DES_CBC; 1.1998 + cbc_mechanism.pParameter = &ivBlock; 1.1999 + cbc_mechanism.ulParameterLen = blockSize; 1.2000 + break; 1.2001 + case CKM_DES3_MAC_GENERAL: 1.2002 + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; 1.2003 + /* fall through */ 1.2004 + case CKM_DES3_MAC: 1.2005 + blockSize = 8; 1.2006 + PORT_Memset(ivBlock,0,blockSize); 1.2007 + cbc_mechanism.mechanism = CKM_DES3_CBC; 1.2008 + cbc_mechanism.pParameter = &ivBlock; 1.2009 + cbc_mechanism.ulParameterLen = blockSize; 1.2010 + break; 1.2011 + case CKM_CDMF_MAC_GENERAL: 1.2012 + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; 1.2013 + /* fall through */ 1.2014 + case CKM_CDMF_MAC: 1.2015 + blockSize = 8; 1.2016 + PORT_Memset(ivBlock,0,blockSize); 1.2017 + cbc_mechanism.mechanism = CKM_CDMF_CBC; 1.2018 + cbc_mechanism.pParameter = &ivBlock; 1.2019 + cbc_mechanism.ulParameterLen = blockSize; 1.2020 + break; 1.2021 + case CKM_SEED_MAC_GENERAL: 1.2022 + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; 1.2023 + /* fall through */ 1.2024 + case CKM_SEED_MAC: 1.2025 + blockSize = 16; 1.2026 + PORT_Memset(ivBlock,0,blockSize); 1.2027 + cbc_mechanism.mechanism = CKM_SEED_CBC; 1.2028 + cbc_mechanism.pParameter = &ivBlock; 1.2029 + cbc_mechanism.ulParameterLen = blockSize; 1.2030 + break; 1.2031 + case CKM_CAMELLIA_MAC_GENERAL: 1.2032 + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; 1.2033 + /* fall through */ 1.2034 + case CKM_CAMELLIA_MAC: 1.2035 + blockSize = 16; 1.2036 + PORT_Memset(ivBlock,0,blockSize); 1.2037 + cbc_mechanism.mechanism = CKM_CAMELLIA_CBC; 1.2038 + cbc_mechanism.pParameter = &ivBlock; 1.2039 + cbc_mechanism.ulParameterLen = blockSize; 1.2040 + break; 1.2041 + case CKM_AES_MAC_GENERAL: 1.2042 + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; 1.2043 + /* fall through */ 1.2044 + case CKM_AES_MAC: 1.2045 + blockSize = 16; 1.2046 + PORT_Memset(ivBlock,0,blockSize); 1.2047 + cbc_mechanism.mechanism = CKM_AES_CBC; 1.2048 + cbc_mechanism.pParameter = &ivBlock; 1.2049 + cbc_mechanism.ulParameterLen = blockSize; 1.2050 + break; 1.2051 + default: 1.2052 + return CKR_FUNCTION_NOT_SUPPORTED; 1.2053 + } 1.2054 + 1.2055 + /* if MAC size is externally supplied, it should be checked. 1.2056 + */ 1.2057 + if (mac_bytes == SFTK_INVALID_MAC_SIZE) 1.2058 + mac_bytes = blockSize >> 1; 1.2059 + else { 1.2060 + if( mac_bytes > blockSize ) 1.2061 + return CKR_MECHANISM_PARAM_INVALID; 1.2062 + } 1.2063 + 1.2064 + crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey, 1.2065 + CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */ 1.2066 + keyUsage, contextType, PR_TRUE ); 1.2067 + if (crv != CKR_OK) return crv; 1.2068 + crv = sftk_GetContext(hSession,&context,contextType,PR_TRUE,NULL); 1.2069 + 1.2070 + /* this shouldn't happen! */ 1.2071 + PORT_Assert(crv == CKR_OK); 1.2072 + if (crv != CKR_OK) return crv; 1.2073 + context->blockSize = blockSize; 1.2074 + context->macSize = mac_bytes; 1.2075 + return CKR_OK; 1.2076 +} 1.2077 + 1.2078 +/* 1.2079 + * encode RSA PKCS #1 Signature data before signing... 1.2080 + */ 1.2081 +static SECStatus 1.2082 +sftk_RSAHashSign(SFTKHashSignInfo *info, unsigned char *sig, 1.2083 + unsigned int *sigLen, unsigned int maxLen, 1.2084 + const unsigned char *hash, unsigned int hashLen) 1.2085 +{ 1.2086 + PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); 1.2087 + if (info->key->keyType != NSSLOWKEYRSAKey) { 1.2088 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.2089 + return SECFailure; 1.2090 + } 1.2091 + 1.2092 + return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen, 1.2093 + hash, hashLen); 1.2094 +} 1.2095 + 1.2096 +/* XXX Old template; want to expunge it eventually. */ 1.2097 +static DERTemplate SECAlgorithmIDTemplate[] = { 1.2098 + { DER_SEQUENCE, 1.2099 + 0, NULL, sizeof(SECAlgorithmID) }, 1.2100 + { DER_OBJECT_ID, 1.2101 + offsetof(SECAlgorithmID,algorithm), }, 1.2102 + { DER_OPTIONAL | DER_ANY, 1.2103 + offsetof(SECAlgorithmID,parameters), }, 1.2104 + { 0, } 1.2105 +}; 1.2106 + 1.2107 +/* 1.2108 + * XXX OLD Template. Once all uses have been switched over to new one, 1.2109 + * remove this. 1.2110 + */ 1.2111 +static DERTemplate SGNDigestInfoTemplate[] = { 1.2112 + { DER_SEQUENCE, 1.2113 + 0, NULL, sizeof(SGNDigestInfo) }, 1.2114 + { DER_INLINE, 1.2115 + offsetof(SGNDigestInfo,digestAlgorithm), 1.2116 + SECAlgorithmIDTemplate, }, 1.2117 + { DER_OCTET_STRING, 1.2118 + offsetof(SGNDigestInfo,digest), }, 1.2119 + { 0, } 1.2120 +}; 1.2121 + 1.2122 +/* 1.2123 + * encode RSA PKCS #1 Signature data before signing... 1.2124 + */ 1.2125 +SECStatus 1.2126 +RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, 1.2127 + unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, 1.2128 + const unsigned char *hash, unsigned int hashLen) 1.2129 +{ 1.2130 + SECStatus rv = SECFailure; 1.2131 + SECItem digder; 1.2132 + PLArenaPool *arena = NULL; 1.2133 + SGNDigestInfo *di = NULL; 1.2134 + 1.2135 + digder.data = NULL; 1.2136 + 1.2137 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.2138 + if (!arena) { 1.2139 + goto loser; 1.2140 + } 1.2141 + 1.2142 + /* Construct digest info */ 1.2143 + di = SGN_CreateDigestInfo(hashOid, hash, hashLen); 1.2144 + if (!di) { 1.2145 + goto loser; 1.2146 + } 1.2147 + 1.2148 + /* Der encode the digest as a DigestInfo */ 1.2149 + rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); 1.2150 + if (rv != SECSuccess) { 1.2151 + goto loser; 1.2152 + } 1.2153 + 1.2154 + /* 1.2155 + ** Encrypt signature after constructing appropriate PKCS#1 signature 1.2156 + ** block 1.2157 + */ 1.2158 + rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data, 1.2159 + digder.len); 1.2160 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.2161 + sftk_fatalError = PR_TRUE; 1.2162 + } 1.2163 + 1.2164 + loser: 1.2165 + SGN_DestroyDigestInfo(di); 1.2166 + if (arena != NULL) { 1.2167 + PORT_FreeArena(arena, PR_FALSE); 1.2168 + } 1.2169 + return rv; 1.2170 +} 1.2171 + 1.2172 +static SECStatus 1.2173 +sftk_RSASign(NSSLOWKEYPrivateKey *key, unsigned char *output, 1.2174 + unsigned int *outputLen, unsigned int maxOutputLen, 1.2175 + const unsigned char *input, unsigned int inputLen) 1.2176 +{ 1.2177 + SECStatus rv = SECFailure; 1.2178 + 1.2179 + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); 1.2180 + if (key->keyType != NSSLOWKEYRSAKey) { 1.2181 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.2182 + return SECFailure; 1.2183 + } 1.2184 + 1.2185 + rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input, 1.2186 + inputLen); 1.2187 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.2188 + sftk_fatalError = PR_TRUE; 1.2189 + } 1.2190 + return rv; 1.2191 +} 1.2192 + 1.2193 +static SECStatus 1.2194 +sftk_RSASignRaw(NSSLOWKEYPrivateKey *key, unsigned char *output, 1.2195 + unsigned int *outputLen, unsigned int maxOutputLen, 1.2196 + const unsigned char *input, unsigned int inputLen) 1.2197 +{ 1.2198 + SECStatus rv = SECFailure; 1.2199 + 1.2200 + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); 1.2201 + if (key->keyType != NSSLOWKEYRSAKey) { 1.2202 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.2203 + return SECFailure; 1.2204 + } 1.2205 + 1.2206 + rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input, 1.2207 + inputLen); 1.2208 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.2209 + sftk_fatalError = PR_TRUE; 1.2210 + } 1.2211 + return rv; 1.2212 + 1.2213 +} 1.2214 + 1.2215 +static SECStatus 1.2216 +sftk_RSASignPSS(SFTKHashSignInfo *info, unsigned char *sig, 1.2217 + unsigned int *sigLen, unsigned int maxLen, 1.2218 + const unsigned char *hash, unsigned int hashLen) 1.2219 +{ 1.2220 + SECStatus rv = SECFailure; 1.2221 + HASH_HashType hashAlg; 1.2222 + HASH_HashType maskHashAlg; 1.2223 + CK_RSA_PKCS_PSS_PARAMS *params = (CK_RSA_PKCS_PSS_PARAMS *)info->params; 1.2224 + 1.2225 + PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); 1.2226 + if (info->key->keyType != NSSLOWKEYRSAKey) { 1.2227 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.2228 + return SECFailure; 1.2229 + } 1.2230 + 1.2231 + hashAlg = GetHashTypeFromMechanism(params->hashAlg); 1.2232 + maskHashAlg = GetHashTypeFromMechanism(params->mgf); 1.2233 + 1.2234 + rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL, 1.2235 + params->sLen, sig, sigLen, maxLen, hash, hashLen); 1.2236 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.2237 + sftk_fatalError = PR_TRUE; 1.2238 + } 1.2239 + return rv; 1.2240 +} 1.2241 + 1.2242 +static SECStatus 1.2243 +nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen, 1.2244 + void *dataBuf, unsigned int dataLen) 1.2245 +{ 1.2246 + SECItem signature, digest; 1.2247 + NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx; 1.2248 + 1.2249 + signature.data = (unsigned char *)sigBuf; 1.2250 + signature.len = sigLen; 1.2251 + digest.data = (unsigned char *)dataBuf; 1.2252 + digest.len = dataLen; 1.2253 + return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest); 1.2254 +} 1.2255 + 1.2256 +static SECStatus 1.2257 +nsc_DSA_Sign_Stub(void *ctx, void *sigBuf, 1.2258 + unsigned int *sigLen, unsigned int maxSigLen, 1.2259 + void *dataBuf, unsigned int dataLen) 1.2260 +{ 1.2261 + SECItem signature, digest; 1.2262 + SECStatus rv; 1.2263 + NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx; 1.2264 + 1.2265 + signature.data = (unsigned char *)sigBuf; 1.2266 + signature.len = maxSigLen; 1.2267 + digest.data = (unsigned char *)dataBuf; 1.2268 + digest.len = dataLen; 1.2269 + rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest); 1.2270 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.2271 + sftk_fatalError = PR_TRUE; 1.2272 + } 1.2273 + *sigLen = signature.len; 1.2274 + return rv; 1.2275 +} 1.2276 + 1.2277 +#ifndef NSS_DISABLE_ECC 1.2278 +static SECStatus 1.2279 +nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen, 1.2280 + void *dataBuf, unsigned int dataLen) 1.2281 +{ 1.2282 + SECItem signature, digest; 1.2283 + NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx; 1.2284 + 1.2285 + signature.data = (unsigned char *)sigBuf; 1.2286 + signature.len = sigLen; 1.2287 + digest.data = (unsigned char *)dataBuf; 1.2288 + digest.len = dataLen; 1.2289 + return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest); 1.2290 +} 1.2291 + 1.2292 +static SECStatus 1.2293 +nsc_ECDSASignStub(void *ctx, void *sigBuf, 1.2294 + unsigned int *sigLen, unsigned int maxSigLen, 1.2295 + void *dataBuf, unsigned int dataLen) 1.2296 +{ 1.2297 + SECItem signature, digest; 1.2298 + SECStatus rv; 1.2299 + NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx; 1.2300 + 1.2301 + signature.data = (unsigned char *)sigBuf; 1.2302 + signature.len = maxSigLen; 1.2303 + digest.data = (unsigned char *)dataBuf; 1.2304 + digest.len = dataLen; 1.2305 + rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest); 1.2306 + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.2307 + sftk_fatalError = PR_TRUE; 1.2308 + } 1.2309 + *sigLen = signature.len; 1.2310 + return rv; 1.2311 +} 1.2312 +#endif /* NSS_DISABLE_ECC */ 1.2313 + 1.2314 +/* NSC_SignInit setups up the signing operations. There are three basic 1.2315 + * types of signing: 1.2316 + * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied 1.2317 + * to data in a single Sign operation (which often looks a lot like an 1.2318 + * encrypt, with data coming in and data going out). 1.2319 + * (2) Hash based signing, where we continually hash the data, then apply 1.2320 + * some sort of signature to the end. 1.2321 + * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key, 1.2322 + * and only the final block is part of the mac. 1.2323 + * 1.2324 + * For case number 3, we initialize a context much like the Encryption Context 1.2325 + * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and 1.2326 + * C_Final by the following method... if it's not multi-part, and it's doesn't 1.2327 + * have a hash context, it must be a block Encryption CBC MAC. 1.2328 + * 1.2329 + * For case number 2, we initialize a hash structure, as well as make it 1.2330 + * multi-part. Updates are simple calls to the hash update function. Final 1.2331 + * calls the hashend, then passes the result to the 'update' function (which 1.2332 + * operates as a final signature function). In some hash based MAC'ing (as 1.2333 + * opposed to hash base signatures), the update function is can be simply a 1.2334 + * copy (as is the case with HMAC). 1.2335 + */ 1.2336 +CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession, 1.2337 + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) 1.2338 +{ 1.2339 + SFTKSession *session; 1.2340 + SFTKObject *key; 1.2341 + SFTKSessionContext *context; 1.2342 + CK_KEY_TYPE key_type; 1.2343 + CK_RV crv = CKR_OK; 1.2344 + NSSLOWKEYPrivateKey *privKey; 1.2345 + SFTKHashSignInfo *info = NULL; 1.2346 + 1.2347 + CHECK_FORK(); 1.2348 + 1.2349 + /* Block Cipher MACing Algorithms use a different Context init method..*/ 1.2350 + crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN); 1.2351 + if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv; 1.2352 + 1.2353 + /* we're not using a block cipher mac */ 1.2354 + session = sftk_SessionFromHandle(hSession); 1.2355 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.2356 + crv = sftk_InitGeneric(session,&context,SFTK_SIGN,&key,hKey,&key_type, 1.2357 + CKO_PRIVATE_KEY,CKA_SIGN); 1.2358 + if (crv != CKR_OK) { 1.2359 + sftk_FreeSession(session); 1.2360 + return crv; 1.2361 + } 1.2362 + 1.2363 + context->multi = PR_FALSE; 1.2364 + 1.2365 +#define INIT_RSA_SIGN_MECH(mmm) \ 1.2366 + case CKM_ ## mmm ## _RSA_PKCS: \ 1.2367 + context->multi = PR_TRUE; \ 1.2368 + crv = sftk_doSub ## mmm (context); \ 1.2369 + if (crv != CKR_OK) break; \ 1.2370 + context->update = (SFTKCipher) sftk_RSAHashSign; \ 1.2371 + info = PORT_New(SFTKHashSignInfo); \ 1.2372 + if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \ 1.2373 + info->hashOid = SEC_OID_ ## mmm ; \ 1.2374 + goto finish_rsa; 1.2375 + 1.2376 + switch(pMechanism->mechanism) { 1.2377 + INIT_RSA_SIGN_MECH(MD5) 1.2378 + INIT_RSA_SIGN_MECH(MD2) 1.2379 + INIT_RSA_SIGN_MECH(SHA1) 1.2380 + INIT_RSA_SIGN_MECH(SHA224) 1.2381 + INIT_RSA_SIGN_MECH(SHA256) 1.2382 + INIT_RSA_SIGN_MECH(SHA384) 1.2383 + INIT_RSA_SIGN_MECH(SHA512) 1.2384 + 1.2385 + case CKM_RSA_PKCS: 1.2386 + context->update = (SFTKCipher) sftk_RSASign; 1.2387 + goto finish_rsa; 1.2388 + case CKM_RSA_X_509: 1.2389 + context->update = (SFTKCipher) sftk_RSASignRaw; 1.2390 +finish_rsa: 1.2391 + if (key_type != CKK_RSA) { 1.2392 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.2393 + break; 1.2394 + } 1.2395 + context->rsa = PR_TRUE; 1.2396 + privKey = sftk_GetPrivKey(key,CKK_RSA,&crv); 1.2397 + if (privKey == NULL) { 1.2398 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.2399 + break; 1.2400 + } 1.2401 + /* OK, info is allocated only if we're doing hash and sign mechanism. 1.2402 + * It's necessary to be able to set the correct OID in the final 1.2403 + * signature. 1.2404 + */ 1.2405 + if (info) { 1.2406 + info->key = privKey; 1.2407 + context->cipherInfo = info; 1.2408 + context->destroy = (SFTKDestroy)sftk_Space; 1.2409 + } else { 1.2410 + context->cipherInfo = privKey; 1.2411 + context->destroy = (SFTKDestroy)sftk_Null; 1.2412 + } 1.2413 + context->maxLen = nsslowkey_PrivateModulusLen(privKey); 1.2414 + break; 1.2415 + case CKM_RSA_PKCS_PSS: 1.2416 + if (key_type != CKK_RSA) { 1.2417 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.2418 + break; 1.2419 + } 1.2420 + context->rsa = PR_TRUE; 1.2421 + if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || 1.2422 + !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)) { 1.2423 + crv = CKR_MECHANISM_PARAM_INVALID; 1.2424 + break; 1.2425 + } 1.2426 + info = PORT_New(SFTKHashSignInfo); 1.2427 + if (info == NULL) { 1.2428 + crv = CKR_HOST_MEMORY; 1.2429 + break; 1.2430 + } 1.2431 + info->params = pMechanism->pParameter; 1.2432 + info->key = sftk_GetPrivKey(key,CKK_RSA,&crv); 1.2433 + if (info->key == NULL) { 1.2434 + PORT_Free(info); 1.2435 + break; 1.2436 + } 1.2437 + context->cipherInfo = info; 1.2438 + context->destroy = (SFTKDestroy) sftk_Space; 1.2439 + context->update = (SFTKCipher) sftk_RSASignPSS; 1.2440 + context->maxLen = nsslowkey_PrivateModulusLen(info->key); 1.2441 + break; 1.2442 + 1.2443 + case CKM_DSA_SHA1: 1.2444 + context->multi = PR_TRUE; 1.2445 + crv = sftk_doSubSHA1(context); 1.2446 + if (crv != CKR_OK) break; 1.2447 + /* fall through */ 1.2448 + case CKM_DSA: 1.2449 + if (key_type != CKK_DSA) { 1.2450 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.2451 + break; 1.2452 + } 1.2453 + privKey = sftk_GetPrivKey(key,CKK_DSA,&crv); 1.2454 + if (privKey == NULL) { 1.2455 + break; 1.2456 + } 1.2457 + context->cipherInfo = privKey; 1.2458 + context->update = (SFTKCipher) nsc_DSA_Sign_Stub; 1.2459 + context->destroy = (privKey == key->objectInfo) ? 1.2460 + (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey; 1.2461 + context->maxLen = DSA_MAX_SIGNATURE_LEN; 1.2462 + 1.2463 + break; 1.2464 + 1.2465 +#ifndef NSS_DISABLE_ECC 1.2466 + case CKM_ECDSA_SHA1: 1.2467 + context->multi = PR_TRUE; 1.2468 + crv = sftk_doSubSHA1(context); 1.2469 + if (crv != CKR_OK) break; 1.2470 + /* fall through */ 1.2471 + case CKM_ECDSA: 1.2472 + if (key_type != CKK_EC) { 1.2473 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.2474 + break; 1.2475 + } 1.2476 + privKey = sftk_GetPrivKey(key,CKK_EC,&crv); 1.2477 + if (privKey == NULL) { 1.2478 + crv = CKR_HOST_MEMORY; 1.2479 + break; 1.2480 + } 1.2481 + context->cipherInfo = privKey; 1.2482 + context->update = (SFTKCipher) nsc_ECDSASignStub; 1.2483 + context->destroy = (privKey == key->objectInfo) ? 1.2484 + (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey; 1.2485 + context->maxLen = MAX_ECKEY_LEN * 2; 1.2486 + 1.2487 + break; 1.2488 +#endif /* NSS_DISABLE_ECC */ 1.2489 + 1.2490 +#define INIT_HMAC_MECH(mmm) \ 1.2491 + case CKM_ ## mmm ## _HMAC_GENERAL: \ 1.2492 + crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, \ 1.2493 + *(CK_ULONG *)pMechanism->pParameter); \ 1.2494 + break; \ 1.2495 + case CKM_ ## mmm ## _HMAC: \ 1.2496 + crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, mmm ## _LENGTH); \ 1.2497 + break; 1.2498 + 1.2499 + INIT_HMAC_MECH(MD2) 1.2500 + INIT_HMAC_MECH(MD5) 1.2501 + INIT_HMAC_MECH(SHA224) 1.2502 + INIT_HMAC_MECH(SHA256) 1.2503 + INIT_HMAC_MECH(SHA384) 1.2504 + INIT_HMAC_MECH(SHA512) 1.2505 + 1.2506 + case CKM_SHA_1_HMAC_GENERAL: 1.2507 + crv = sftk_doHMACInit(context,HASH_AlgSHA1,key, 1.2508 + *(CK_ULONG *)pMechanism->pParameter); 1.2509 + break; 1.2510 + case CKM_SHA_1_HMAC: 1.2511 + crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH); 1.2512 + break; 1.2513 + 1.2514 + case CKM_SSL3_MD5_MAC: 1.2515 + crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key, 1.2516 + *(CK_ULONG *)pMechanism->pParameter); 1.2517 + break; 1.2518 + case CKM_SSL3_SHA1_MAC: 1.2519 + crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key, 1.2520 + *(CK_ULONG *)pMechanism->pParameter); 1.2521 + break; 1.2522 + case CKM_TLS_PRF_GENERAL: 1.2523 + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL); 1.2524 + break; 1.2525 + case CKM_NSS_TLS_PRF_GENERAL_SHA256: 1.2526 + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256); 1.2527 + break; 1.2528 + 1.2529 + case CKM_NSS_HMAC_CONSTANT_TIME: { 1.2530 + sftk_MACConstantTimeCtx *ctx = 1.2531 + sftk_HMACConstantTime_New(pMechanism,key); 1.2532 + CK_ULONG *intpointer; 1.2533 + 1.2534 + if (ctx == NULL) { 1.2535 + crv = CKR_ARGUMENTS_BAD; 1.2536 + break; 1.2537 + } 1.2538 + intpointer = PORT_New(CK_ULONG); 1.2539 + if (intpointer == NULL) { 1.2540 + crv = CKR_HOST_MEMORY; 1.2541 + break; 1.2542 + } 1.2543 + *intpointer = ctx->hash->length; 1.2544 + 1.2545 + context->cipherInfo = intpointer; 1.2546 + context->hashInfo = ctx; 1.2547 + context->currentMech = pMechanism->mechanism; 1.2548 + context->hashUpdate = sftk_HMACConstantTime_Update; 1.2549 + context->hashdestroy = sftk_MACConstantTime_DestroyContext; 1.2550 + context->end = sftk_MACConstantTime_EndHash; 1.2551 + context->update = (SFTKCipher) sftk_SignCopy; 1.2552 + context->destroy = sftk_Space; 1.2553 + context->maxLen = 64; 1.2554 + context->multi = PR_TRUE; 1.2555 + break; 1.2556 + } 1.2557 + 1.2558 + case CKM_NSS_SSL3_MAC_CONSTANT_TIME: { 1.2559 + sftk_MACConstantTimeCtx *ctx = 1.2560 + sftk_SSLv3MACConstantTime_New(pMechanism,key); 1.2561 + CK_ULONG *intpointer; 1.2562 + 1.2563 + if (ctx == NULL) { 1.2564 + crv = CKR_ARGUMENTS_BAD; 1.2565 + break; 1.2566 + } 1.2567 + intpointer = PORT_New(CK_ULONG); 1.2568 + if (intpointer == NULL) { 1.2569 + crv = CKR_HOST_MEMORY; 1.2570 + break; 1.2571 + } 1.2572 + *intpointer = ctx->hash->length; 1.2573 + 1.2574 + context->cipherInfo = intpointer; 1.2575 + context->hashInfo = ctx; 1.2576 + context->currentMech = pMechanism->mechanism; 1.2577 + context->hashUpdate = sftk_SSLv3MACConstantTime_Update; 1.2578 + context->hashdestroy = sftk_MACConstantTime_DestroyContext; 1.2579 + context->end = sftk_MACConstantTime_EndHash; 1.2580 + context->update = (SFTKCipher) sftk_SignCopy; 1.2581 + context->destroy = sftk_Space; 1.2582 + context->maxLen = 64; 1.2583 + context->multi = PR_TRUE; 1.2584 + break; 1.2585 + } 1.2586 + 1.2587 + default: 1.2588 + crv = CKR_MECHANISM_INVALID; 1.2589 + break; 1.2590 + } 1.2591 + 1.2592 + if (crv != CKR_OK) { 1.2593 + if (info) PORT_Free(info); 1.2594 + sftk_FreeContext(context); 1.2595 + sftk_FreeSession(session); 1.2596 + return crv; 1.2597 + } 1.2598 + sftk_SetContextByType(session, SFTK_SIGN, context); 1.2599 + sftk_FreeSession(session); 1.2600 + return CKR_OK; 1.2601 +} 1.2602 + 1.2603 +/** MAC one block of data by block cipher 1.2604 + */ 1.2605 +static CK_RV 1.2606 +sftk_MACBlock( SFTKSessionContext *ctx, void *blk ) 1.2607 +{ 1.2608 + unsigned int outlen; 1.2609 + return ( SECSuccess == (ctx->update)( ctx->cipherInfo, ctx->macBuf, &outlen, 1.2610 + SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize )) 1.2611 + ? CKR_OK : sftk_MapCryptError(PORT_GetError()); 1.2612 +} 1.2613 + 1.2614 +/** MAC last (incomplete) block of data by block cipher 1.2615 + * 1.2616 + * Call once, then terminate MACing operation. 1.2617 + */ 1.2618 +static CK_RV 1.2619 +sftk_MACFinal( SFTKSessionContext *ctx ) 1.2620 +{ 1.2621 + unsigned int padLen = ctx->padDataLength; 1.2622 + /* pad and proceed the residual */ 1.2623 + if( padLen ) { 1.2624 + /* shd clr ctx->padLen to make sftk_MACFinal idempotent */ 1.2625 + PORT_Memset( ctx->padBuf + padLen, 0, ctx->blockSize - padLen ); 1.2626 + return sftk_MACBlock( ctx, ctx->padBuf ); 1.2627 + } else 1.2628 + return CKR_OK; 1.2629 +} 1.2630 + 1.2631 +/** The common implementation for {Sign,Verify}Update. (S/V only vary in their 1.2632 + * setup and final operations). 1.2633 + * 1.2634 + * A call which results in an error terminates the operation [PKCS#11,v2.11] 1.2635 + */ 1.2636 +static CK_RV 1.2637 +sftk_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, 1.2638 + CK_ULONG ulPartLen,SFTKContextType type) 1.2639 +{ 1.2640 + SFTKSession *session; 1.2641 + SFTKSessionContext *context; 1.2642 + CK_RV crv; 1.2643 + 1.2644 + /* make sure we're legal */ 1.2645 + crv = sftk_GetContext(hSession,&context,type, PR_TRUE, &session ); 1.2646 + if (crv != CKR_OK) return crv; 1.2647 + 1.2648 + if (context->hashInfo) { 1.2649 + (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen); 1.2650 + } else { 1.2651 + /* must be block cipher MACing */ 1.2652 + 1.2653 + unsigned int blkSize = context->blockSize; 1.2654 + unsigned char *residual = /* free room in context->padBuf */ 1.2655 + context->padBuf + context->padDataLength; 1.2656 + unsigned int minInput = /* min input for MACing at least one block */ 1.2657 + blkSize - context->padDataLength; 1.2658 + 1.2659 + /* not enough data even for one block */ 1.2660 + if( ulPartLen < minInput ) { 1.2661 + PORT_Memcpy( residual, pPart, ulPartLen ); 1.2662 + context->padDataLength += ulPartLen; 1.2663 + goto cleanup; 1.2664 + } 1.2665 + /* MACing residual */ 1.2666 + if( context->padDataLength ) { 1.2667 + PORT_Memcpy( residual, pPart, minInput ); 1.2668 + ulPartLen -= minInput; 1.2669 + pPart += minInput; 1.2670 + if( CKR_OK != (crv = sftk_MACBlock( context, context->padBuf )) ) 1.2671 + goto terminate; 1.2672 + } 1.2673 + /* MACing full blocks */ 1.2674 + while( ulPartLen >= blkSize ) 1.2675 + { 1.2676 + if( CKR_OK != (crv = sftk_MACBlock( context, pPart )) ) 1.2677 + goto terminate; 1.2678 + ulPartLen -= blkSize; 1.2679 + pPart += blkSize; 1.2680 + } 1.2681 + /* save the residual */ 1.2682 + if( (context->padDataLength = ulPartLen) ) 1.2683 + PORT_Memcpy( context->padBuf, pPart, ulPartLen ); 1.2684 + } /* blk cipher MACing */ 1.2685 + 1.2686 + goto cleanup; 1.2687 + 1.2688 +terminate: 1.2689 + sftk_TerminateOp( session, type, context ); 1.2690 +cleanup: 1.2691 + sftk_FreeSession(session); 1.2692 + return crv; 1.2693 +} 1.2694 + 1.2695 +/* NSC_SignUpdate continues a multiple-part signature operation, 1.2696 + * where the signature is (will be) an appendix to the data, 1.2697 + * and plaintext cannot be recovered from the signature 1.2698 + * 1.2699 + * A call which results in an error terminates the operation [PKCS#11,v2.11] 1.2700 + */ 1.2701 +CK_RV NSC_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, 1.2702 + CK_ULONG ulPartLen) 1.2703 +{ 1.2704 + CHECK_FORK(); 1.2705 + return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN); 1.2706 +} 1.2707 + 1.2708 + 1.2709 +/* NSC_SignFinal finishes a multiple-part signature operation, 1.2710 + * returning the signature. */ 1.2711 +CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature, 1.2712 + CK_ULONG_PTR pulSignatureLen) 1.2713 +{ 1.2714 + SFTKSession *session; 1.2715 + SFTKSessionContext *context; 1.2716 + unsigned int outlen; 1.2717 + unsigned int maxoutlen = *pulSignatureLen; 1.2718 + CK_RV crv; 1.2719 + 1.2720 + CHECK_FORK(); 1.2721 + 1.2722 + /* make sure we're legal */ 1.2723 + crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_TRUE,&session); 1.2724 + if (crv != CKR_OK) return crv; 1.2725 + 1.2726 + if (context->hashInfo) { 1.2727 + unsigned int digestLen; 1.2728 + unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; 1.2729 + 1.2730 + if( !pSignature ) { 1.2731 + outlen = context->maxLen; goto finish; 1.2732 + } 1.2733 + (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); 1.2734 + if( SECSuccess != (context->update)(context->cipherInfo, pSignature, 1.2735 + &outlen, maxoutlen, tmpbuf, digestLen)) 1.2736 + crv = sftk_MapCryptError(PORT_GetError()); 1.2737 + /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate. 1.2738 + * Keeping "too small" CK_RV intact is a standard violation, but allows 1.2739 + * application read EXACT signature length */ 1.2740 + } else { 1.2741 + /* must be block cipher MACing */ 1.2742 + outlen = context->macSize; 1.2743 + /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/ 1.2744 + if( !pSignature || maxoutlen < outlen ) { 1.2745 + if( pSignature ) crv = CKR_BUFFER_TOO_SMALL; 1.2746 + goto finish; 1.2747 + } 1.2748 + if( CKR_OK == (crv = sftk_MACFinal( context )) ) 1.2749 + PORT_Memcpy(pSignature, context->macBuf, outlen ); 1.2750 + } 1.2751 + 1.2752 + sftk_TerminateOp( session, SFTK_SIGN, context ); 1.2753 +finish: 1.2754 + *pulSignatureLen = outlen; 1.2755 + sftk_FreeSession(session); 1.2756 + return crv; 1.2757 +} 1.2758 + 1.2759 +/* NSC_Sign signs (encrypts with private key) data in a single part, 1.2760 + * where the signature is (will be) an appendix to the data, 1.2761 + * and plaintext cannot be recovered from the signature */ 1.2762 +CK_RV NSC_Sign(CK_SESSION_HANDLE hSession, 1.2763 + CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature, 1.2764 + CK_ULONG_PTR pulSignatureLen) 1.2765 +{ 1.2766 + SFTKSession *session; 1.2767 + SFTKSessionContext *context; 1.2768 + CK_RV crv; 1.2769 + 1.2770 + CHECK_FORK(); 1.2771 + 1.2772 + /* make sure we're legal */ 1.2773 + crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_FALSE,&session); 1.2774 + if (crv != CKR_OK) return crv; 1.2775 + 1.2776 + if (!pSignature) { 1.2777 + /* see also how C_SignUpdate implements this */ 1.2778 + *pulSignatureLen = (!context->multi || context->hashInfo) 1.2779 + ? context->maxLen 1.2780 + : context->macSize; /* must be block cipher MACing */ 1.2781 + goto finish; 1.2782 + } 1.2783 + 1.2784 + /* multi part Signing are completely implemented by SignUpdate and 1.2785 + * sign Final */ 1.2786 + if (context->multi) { 1.2787 + /* SignFinal can't follow failed SignUpdate */ 1.2788 + if( CKR_OK == (crv = NSC_SignUpdate(hSession,pData,ulDataLen) )) 1.2789 + crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen); 1.2790 + } else { 1.2791 + /* single-part PKC signature (e.g. CKM_ECDSA) */ 1.2792 + unsigned int outlen; 1.2793 + unsigned int maxoutlen = *pulSignatureLen; 1.2794 + if( SECSuccess != (*context->update)(context->cipherInfo, pSignature, 1.2795 + &outlen, maxoutlen, pData, ulDataLen)) 1.2796 + crv = sftk_MapCryptError(PORT_GetError()); 1.2797 + *pulSignatureLen = (CK_ULONG) outlen; 1.2798 + /* "too small" here is certainly continuable */ 1.2799 + if( crv != CKR_BUFFER_TOO_SMALL ) 1.2800 + sftk_TerminateOp(session, SFTK_SIGN, context); 1.2801 + } /* single-part */ 1.2802 + 1.2803 +finish: 1.2804 + sftk_FreeSession(session); 1.2805 + return crv; 1.2806 +} 1.2807 + 1.2808 + 1.2809 +/* 1.2810 + ************** Crypto Functions: Sign Recover ************************ 1.2811 + */ 1.2812 +/* NSC_SignRecoverInit initializes a signature operation, 1.2813 + * where the (digest) data can be recovered from the signature. 1.2814 + * E.g. encryption with the user's private key */ 1.2815 +CK_RV NSC_SignRecoverInit(CK_SESSION_HANDLE hSession, 1.2816 + CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) 1.2817 +{ 1.2818 + CHECK_FORK(); 1.2819 + 1.2820 + switch (pMechanism->mechanism) { 1.2821 + case CKM_RSA_PKCS: 1.2822 + case CKM_RSA_X_509: 1.2823 + return NSC_SignInit(hSession,pMechanism,hKey); 1.2824 + default: 1.2825 + break; 1.2826 + } 1.2827 + return CKR_MECHANISM_INVALID; 1.2828 +} 1.2829 + 1.2830 + 1.2831 +/* NSC_SignRecover signs data in a single operation 1.2832 + * where the (digest) data can be recovered from the signature. 1.2833 + * E.g. encryption with the user's private key */ 1.2834 +CK_RV NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, 1.2835 + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) 1.2836 +{ 1.2837 + CHECK_FORK(); 1.2838 + 1.2839 + return NSC_Sign(hSession,pData,ulDataLen,pSignature,pulSignatureLen); 1.2840 +} 1.2841 + 1.2842 +/* 1.2843 + ************** Crypto Functions: verify ************************ 1.2844 + */ 1.2845 + 1.2846 +/* Handle RSA Signature formatting */ 1.2847 +static SECStatus 1.2848 +sftk_hashCheckSign(SFTKHashVerifyInfo *info, const unsigned char *sig, 1.2849 + unsigned int sigLen, const unsigned char *digest, 1.2850 + unsigned int digestLen) 1.2851 +{ 1.2852 + PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); 1.2853 + if (info->key->keyType != NSSLOWKEYRSAKey) { 1.2854 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.2855 + return SECFailure; 1.2856 + } 1.2857 + 1.2858 + return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest, 1.2859 + digestLen); 1.2860 +} 1.2861 + 1.2862 +SECStatus 1.2863 +RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key, 1.2864 + const unsigned char *sig, unsigned int sigLen, 1.2865 + const unsigned char *digestData, unsigned int digestLen) 1.2866 +{ 1.2867 + unsigned char *pkcs1DigestInfoData; 1.2868 + SECItem pkcs1DigestInfo; 1.2869 + SECItem digest; 1.2870 + unsigned int bufferSize; 1.2871 + SECStatus rv; 1.2872 + 1.2873 + /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */ 1.2874 + bufferSize = key->u.rsa.modulus.len; 1.2875 + pkcs1DigestInfoData = PORT_ZAlloc(bufferSize); 1.2876 + if (!pkcs1DigestInfoData) { 1.2877 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.2878 + return SECFailure; 1.2879 + } 1.2880 + 1.2881 + pkcs1DigestInfo.data = pkcs1DigestInfoData; 1.2882 + pkcs1DigestInfo.len = bufferSize; 1.2883 + 1.2884 + /* decrypt the block */ 1.2885 + rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data, 1.2886 + &pkcs1DigestInfo.len, pkcs1DigestInfo.len, 1.2887 + sig, sigLen); 1.2888 + if (rv != SECSuccess) { 1.2889 + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 1.2890 + } else { 1.2891 + digest.data = (PRUint8*) digestData; 1.2892 + digest.len = digestLen; 1.2893 + rv = _SGN_VerifyPKCS1DigestInfo( 1.2894 + digestOid, &digest, &pkcs1DigestInfo, 1.2895 + PR_TRUE /*XXX: unsafeAllowMissingParameters*/); 1.2896 + } 1.2897 + 1.2898 + PORT_Free(pkcs1DigestInfoData); 1.2899 + return rv; 1.2900 +} 1.2901 + 1.2902 +static SECStatus 1.2903 +sftk_RSACheckSign(NSSLOWKEYPublicKey *key, const unsigned char *sig, 1.2904 + unsigned int sigLen, const unsigned char *digest, 1.2905 + unsigned int digestLen) 1.2906 +{ 1.2907 + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); 1.2908 + if (key->keyType != NSSLOWKEYRSAKey) { 1.2909 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.2910 + return SECFailure; 1.2911 + } 1.2912 + 1.2913 + return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen); 1.2914 +} 1.2915 + 1.2916 +static SECStatus 1.2917 +sftk_RSACheckSignRaw(NSSLOWKEYPublicKey *key, const unsigned char *sig, 1.2918 + unsigned int sigLen, const unsigned char *digest, 1.2919 + unsigned int digestLen) 1.2920 +{ 1.2921 + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); 1.2922 + if (key->keyType != NSSLOWKEYRSAKey) { 1.2923 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.2924 + return SECFailure; 1.2925 + } 1.2926 + 1.2927 + return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen); 1.2928 +} 1.2929 + 1.2930 +static SECStatus 1.2931 +sftk_RSACheckSignPSS(SFTKHashVerifyInfo *info, const unsigned char *sig, 1.2932 + unsigned int sigLen, const unsigned char *digest, 1.2933 + unsigned int digestLen) 1.2934 +{ 1.2935 + HASH_HashType hashAlg; 1.2936 + HASH_HashType maskHashAlg; 1.2937 + CK_RSA_PKCS_PSS_PARAMS *params = (CK_RSA_PKCS_PSS_PARAMS *)info->params; 1.2938 + 1.2939 + PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); 1.2940 + if (info->key->keyType != NSSLOWKEYRSAKey) { 1.2941 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.2942 + return SECFailure; 1.2943 + } 1.2944 + 1.2945 + hashAlg = GetHashTypeFromMechanism(params->hashAlg); 1.2946 + maskHashAlg = GetHashTypeFromMechanism(params->mgf); 1.2947 + 1.2948 + return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, 1.2949 + params->sLen, sig, sigLen, digest, digestLen); 1.2950 +} 1.2951 + 1.2952 +/* NSC_VerifyInit initializes a verification operation, 1.2953 + * where the signature is an appendix to the data, 1.2954 + * and plaintext cannot be recovered from the signature (e.g. DSA) */ 1.2955 +CK_RV NSC_VerifyInit(CK_SESSION_HANDLE hSession, 1.2956 + CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) 1.2957 +{ 1.2958 + SFTKSession *session; 1.2959 + SFTKObject *key; 1.2960 + SFTKSessionContext *context; 1.2961 + CK_KEY_TYPE key_type; 1.2962 + CK_RV crv = CKR_OK; 1.2963 + NSSLOWKEYPublicKey *pubKey; 1.2964 + SFTKHashVerifyInfo *info = NULL; 1.2965 + 1.2966 + CHECK_FORK(); 1.2967 + 1.2968 + /* Block Cipher MACing Algorithms use a different Context init method..*/ 1.2969 + crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY); 1.2970 + if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv; 1.2971 + 1.2972 + session = sftk_SessionFromHandle(hSession); 1.2973 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.2974 + crv = sftk_InitGeneric(session,&context,SFTK_VERIFY,&key,hKey,&key_type, 1.2975 + CKO_PUBLIC_KEY,CKA_VERIFY); 1.2976 + if (crv != CKR_OK) { 1.2977 + sftk_FreeSession(session); 1.2978 + return crv; 1.2979 + } 1.2980 + 1.2981 + context->multi = PR_FALSE; 1.2982 + 1.2983 +#define INIT_RSA_VFY_MECH(mmm) \ 1.2984 + case CKM_ ## mmm ## _RSA_PKCS: \ 1.2985 + context->multi = PR_TRUE; \ 1.2986 + crv = sftk_doSub ## mmm (context); \ 1.2987 + if (crv != CKR_OK) break; \ 1.2988 + context->verify = (SFTKVerify) sftk_hashCheckSign; \ 1.2989 + info = PORT_New(SFTKHashVerifyInfo); \ 1.2990 + if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \ 1.2991 + info->hashOid = SEC_OID_ ## mmm ; \ 1.2992 + goto finish_rsa; 1.2993 + 1.2994 + switch(pMechanism->mechanism) { 1.2995 + INIT_RSA_VFY_MECH(MD5) 1.2996 + INIT_RSA_VFY_MECH(MD2) 1.2997 + INIT_RSA_VFY_MECH(SHA1) 1.2998 + INIT_RSA_VFY_MECH(SHA224) 1.2999 + INIT_RSA_VFY_MECH(SHA256) 1.3000 + INIT_RSA_VFY_MECH(SHA384) 1.3001 + INIT_RSA_VFY_MECH(SHA512) 1.3002 + 1.3003 + case CKM_RSA_PKCS: 1.3004 + context->verify = (SFTKVerify) sftk_RSACheckSign; 1.3005 + goto finish_rsa; 1.3006 + case CKM_RSA_X_509: 1.3007 + context->verify = (SFTKVerify) sftk_RSACheckSignRaw; 1.3008 +finish_rsa: 1.3009 + if (key_type != CKK_RSA) { 1.3010 + if (info) PORT_Free(info); 1.3011 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.3012 + break; 1.3013 + } 1.3014 + context->rsa = PR_TRUE; 1.3015 + pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); 1.3016 + if (pubKey == NULL) { 1.3017 + if (info) PORT_Free(info); 1.3018 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.3019 + break; 1.3020 + } 1.3021 + if (info) { 1.3022 + info->key = pubKey; 1.3023 + context->cipherInfo = info; 1.3024 + context->destroy = sftk_Space; 1.3025 + } else { 1.3026 + context->cipherInfo = pubKey; 1.3027 + context->destroy = sftk_Null; 1.3028 + } 1.3029 + break; 1.3030 + case CKM_RSA_PKCS_PSS: 1.3031 + if (key_type != CKK_RSA) { 1.3032 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.3033 + break; 1.3034 + } 1.3035 + context->rsa = PR_TRUE; 1.3036 + if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || 1.3037 + !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)) { 1.3038 + crv = CKR_MECHANISM_PARAM_INVALID; 1.3039 + break; 1.3040 + } 1.3041 + info = PORT_New(SFTKHashVerifyInfo); 1.3042 + if (info == NULL) { 1.3043 + crv = CKR_HOST_MEMORY; 1.3044 + break; 1.3045 + } 1.3046 + info->params = pMechanism->pParameter; 1.3047 + info->key = sftk_GetPubKey(key,CKK_RSA,&crv); 1.3048 + if (info->key == NULL) { 1.3049 + PORT_Free(info); 1.3050 + break; 1.3051 + } 1.3052 + context->cipherInfo = info; 1.3053 + context->destroy = (SFTKDestroy) sftk_Space; 1.3054 + context->verify = (SFTKVerify) sftk_RSACheckSignPSS; 1.3055 + break; 1.3056 + case CKM_DSA_SHA1: 1.3057 + context->multi = PR_TRUE; 1.3058 + crv = sftk_doSubSHA1(context); 1.3059 + if (crv != CKR_OK) break; 1.3060 + /* fall through */ 1.3061 + case CKM_DSA: 1.3062 + if (key_type != CKK_DSA) { 1.3063 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.3064 + break; 1.3065 + } 1.3066 + pubKey = sftk_GetPubKey(key,CKK_DSA,&crv); 1.3067 + if (pubKey == NULL) { 1.3068 + break; 1.3069 + } 1.3070 + context->cipherInfo = pubKey; 1.3071 + context->verify = (SFTKVerify) nsc_DSA_Verify_Stub; 1.3072 + context->destroy = sftk_Null; 1.3073 + break; 1.3074 +#ifndef NSS_DISABLE_ECC 1.3075 + case CKM_ECDSA_SHA1: 1.3076 + context->multi = PR_TRUE; 1.3077 + crv = sftk_doSubSHA1(context); 1.3078 + if (crv != CKR_OK) break; 1.3079 + /* fall through */ 1.3080 + case CKM_ECDSA: 1.3081 + if (key_type != CKK_EC) { 1.3082 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.3083 + break; 1.3084 + } 1.3085 + pubKey = sftk_GetPubKey(key,CKK_EC,&crv); 1.3086 + if (pubKey == NULL) { 1.3087 + crv = CKR_HOST_MEMORY; 1.3088 + break; 1.3089 + } 1.3090 + context->cipherInfo = pubKey; 1.3091 + context->verify = (SFTKVerify) nsc_ECDSAVerifyStub; 1.3092 + context->destroy = sftk_Null; 1.3093 + break; 1.3094 +#endif /* NSS_DISABLE_ECC */ 1.3095 + 1.3096 + INIT_HMAC_MECH(MD2) 1.3097 + INIT_HMAC_MECH(MD5) 1.3098 + INIT_HMAC_MECH(SHA224) 1.3099 + INIT_HMAC_MECH(SHA256) 1.3100 + INIT_HMAC_MECH(SHA384) 1.3101 + INIT_HMAC_MECH(SHA512) 1.3102 + 1.3103 + case CKM_SHA_1_HMAC_GENERAL: 1.3104 + crv = sftk_doHMACInit(context,HASH_AlgSHA1,key, 1.3105 + *(CK_ULONG *)pMechanism->pParameter); 1.3106 + break; 1.3107 + case CKM_SHA_1_HMAC: 1.3108 + crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH); 1.3109 + break; 1.3110 + 1.3111 + case CKM_SSL3_MD5_MAC: 1.3112 + crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key, 1.3113 + *(CK_ULONG *)pMechanism->pParameter); 1.3114 + break; 1.3115 + case CKM_SSL3_SHA1_MAC: 1.3116 + crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key, 1.3117 + *(CK_ULONG *)pMechanism->pParameter); 1.3118 + break; 1.3119 + case CKM_TLS_PRF_GENERAL: 1.3120 + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL); 1.3121 + break; 1.3122 + case CKM_NSS_TLS_PRF_GENERAL_SHA256: 1.3123 + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256); 1.3124 + break; 1.3125 + 1.3126 + default: 1.3127 + crv = CKR_MECHANISM_INVALID; 1.3128 + break; 1.3129 + } 1.3130 + 1.3131 + if (crv != CKR_OK) { 1.3132 + if (info) PORT_Free(info); 1.3133 + sftk_FreeContext(context); 1.3134 + sftk_FreeSession(session); 1.3135 + return crv; 1.3136 + } 1.3137 + sftk_SetContextByType(session, SFTK_VERIFY, context); 1.3138 + sftk_FreeSession(session); 1.3139 + return CKR_OK; 1.3140 +} 1.3141 + 1.3142 +/* NSC_Verify verifies a signature in a single-part operation, 1.3143 + * where the signature is an appendix to the data, 1.3144 + * and plaintext cannot be recovered from the signature */ 1.3145 +CK_RV NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, 1.3146 + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) 1.3147 +{ 1.3148 + SFTKSession *session; 1.3149 + SFTKSessionContext *context; 1.3150 + CK_RV crv; 1.3151 + 1.3152 + CHECK_FORK(); 1.3153 + 1.3154 + /* make sure we're legal */ 1.3155 + crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_FALSE,&session); 1.3156 + if (crv != CKR_OK) return crv; 1.3157 + 1.3158 + /* multi part Verifying are completely implemented by VerifyUpdate and 1.3159 + * VerifyFinal */ 1.3160 + if (context->multi) { 1.3161 + /* VerifyFinal can't follow failed VerifyUpdate */ 1.3162 + if( CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen))) 1.3163 + crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen); 1.3164 + } else { 1.3165 + if (SECSuccess != (*context->verify)(context->cipherInfo,pSignature, 1.3166 + ulSignatureLen, pData, ulDataLen)) 1.3167 + crv = sftk_MapCryptError(PORT_GetError()); 1.3168 + 1.3169 + sftk_TerminateOp( session, SFTK_VERIFY, context ); 1.3170 + } 1.3171 + sftk_FreeSession(session); 1.3172 + return crv; 1.3173 +} 1.3174 + 1.3175 + 1.3176 +/* NSC_VerifyUpdate continues a multiple-part verification operation, 1.3177 + * where the signature is an appendix to the data, 1.3178 + * and plaintext cannot be recovered from the signature 1.3179 + * 1.3180 + * A call which results in an error terminates the operation [PKCS#11,v2.11] 1.3181 + */ 1.3182 +CK_RV NSC_VerifyUpdate( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 1.3183 + CK_ULONG ulPartLen) 1.3184 +{ 1.3185 + CHECK_FORK(); 1.3186 + return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY); 1.3187 +} 1.3188 + 1.3189 + 1.3190 +/* NSC_VerifyFinal finishes a multiple-part verification operation, 1.3191 + * checking the signature. */ 1.3192 +CK_RV NSC_VerifyFinal(CK_SESSION_HANDLE hSession, 1.3193 + CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen) 1.3194 +{ 1.3195 + SFTKSession *session; 1.3196 + SFTKSessionContext *context; 1.3197 + CK_RV crv; 1.3198 + 1.3199 + CHECK_FORK(); 1.3200 + 1.3201 + if (!pSignature) 1.3202 + return CKR_ARGUMENTS_BAD; 1.3203 + 1.3204 + /* make sure we're legal */ 1.3205 + crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_TRUE,&session); 1.3206 + if (crv != CKR_OK) 1.3207 + return crv; 1.3208 + 1.3209 + if (context->hashInfo) { 1.3210 + unsigned int digestLen; 1.3211 + unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; 1.3212 + 1.3213 + (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); 1.3214 + if( SECSuccess != (context->verify)(context->cipherInfo, pSignature, 1.3215 + ulSignatureLen, tmpbuf, digestLen)) 1.3216 + crv = sftk_MapCryptError(PORT_GetError()); 1.3217 + } else if (ulSignatureLen != context->macSize) { 1.3218 + /* must be block cipher MACing */ 1.3219 + crv = CKR_SIGNATURE_LEN_RANGE; 1.3220 + } else if (CKR_OK == (crv = sftk_MACFinal(context))) { 1.3221 + if (PORT_Memcmp(pSignature, context->macBuf, ulSignatureLen)) 1.3222 + crv = CKR_SIGNATURE_INVALID; 1.3223 + } 1.3224 + 1.3225 + sftk_TerminateOp( session, SFTK_VERIFY, context ); 1.3226 + sftk_FreeSession(session); 1.3227 + return crv; 1.3228 + 1.3229 +} 1.3230 + 1.3231 +/* 1.3232 + ************** Crypto Functions: Verify Recover ************************ 1.3233 + */ 1.3234 +static SECStatus 1.3235 +sftk_RSACheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char *data, 1.3236 + unsigned int *dataLen, unsigned int maxDataLen, 1.3237 + const unsigned char *sig, unsigned int sigLen) 1.3238 +{ 1.3239 + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); 1.3240 + if (key->keyType != NSSLOWKEYRSAKey) { 1.3241 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.3242 + return SECFailure; 1.3243 + } 1.3244 + 1.3245 + return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen, 1.3246 + sig, sigLen); 1.3247 +} 1.3248 + 1.3249 +static SECStatus 1.3250 +sftk_RSACheckSignRecoverRaw(NSSLOWKEYPublicKey *key, unsigned char *data, 1.3251 + unsigned int *dataLen, unsigned int maxDataLen, 1.3252 + const unsigned char *sig, unsigned int sigLen) 1.3253 +{ 1.3254 + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); 1.3255 + if (key->keyType != NSSLOWKEYRSAKey) { 1.3256 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.3257 + return SECFailure; 1.3258 + } 1.3259 + 1.3260 + return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen, 1.3261 + sig, sigLen); 1.3262 +} 1.3263 + 1.3264 +/* NSC_VerifyRecoverInit initializes a signature verification operation, 1.3265 + * where the data is recovered from the signature. 1.3266 + * E.g. Decryption with the user's public key */ 1.3267 +CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, 1.3268 + CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) 1.3269 +{ 1.3270 + SFTKSession *session; 1.3271 + SFTKObject *key; 1.3272 + SFTKSessionContext *context; 1.3273 + CK_KEY_TYPE key_type; 1.3274 + CK_RV crv = CKR_OK; 1.3275 + NSSLOWKEYPublicKey *pubKey; 1.3276 + 1.3277 + CHECK_FORK(); 1.3278 + 1.3279 + session = sftk_SessionFromHandle(hSession); 1.3280 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.3281 + crv = sftk_InitGeneric(session,&context,SFTK_VERIFY_RECOVER, 1.3282 + &key,hKey,&key_type,CKO_PUBLIC_KEY,CKA_VERIFY_RECOVER); 1.3283 + if (crv != CKR_OK) { 1.3284 + sftk_FreeSession(session); 1.3285 + return crv; 1.3286 + } 1.3287 + 1.3288 + context->multi = PR_TRUE; 1.3289 + 1.3290 + switch(pMechanism->mechanism) { 1.3291 + case CKM_RSA_PKCS: 1.3292 + case CKM_RSA_X_509: 1.3293 + if (key_type != CKK_RSA) { 1.3294 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.3295 + break; 1.3296 + } 1.3297 + context->multi = PR_FALSE; 1.3298 + context->rsa = PR_TRUE; 1.3299 + pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); 1.3300 + if (pubKey == NULL) { 1.3301 + break; 1.3302 + } 1.3303 + context->cipherInfo = pubKey; 1.3304 + context->update = (SFTKCipher) (pMechanism->mechanism == CKM_RSA_X_509 1.3305 + ? sftk_RSACheckSignRecoverRaw : sftk_RSACheckSignRecover); 1.3306 + context->destroy = sftk_Null; 1.3307 + break; 1.3308 + default: 1.3309 + crv = CKR_MECHANISM_INVALID; 1.3310 + break; 1.3311 + } 1.3312 + 1.3313 + if (crv != CKR_OK) { 1.3314 + PORT_Free(context); 1.3315 + sftk_FreeSession(session); 1.3316 + return crv; 1.3317 + } 1.3318 + sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context); 1.3319 + sftk_FreeSession(session); 1.3320 + return CKR_OK; 1.3321 +} 1.3322 + 1.3323 + 1.3324 +/* NSC_VerifyRecover verifies a signature in a single-part operation, 1.3325 + * where the data is recovered from the signature. 1.3326 + * E.g. Decryption with the user's public key */ 1.3327 +CK_RV NSC_VerifyRecover(CK_SESSION_HANDLE hSession, 1.3328 + CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen, 1.3329 + CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen) 1.3330 +{ 1.3331 + SFTKSession *session; 1.3332 + SFTKSessionContext *context; 1.3333 + unsigned int outlen; 1.3334 + unsigned int maxoutlen = *pulDataLen; 1.3335 + CK_RV crv; 1.3336 + SECStatus rv; 1.3337 + 1.3338 + CHECK_FORK(); 1.3339 + 1.3340 + /* make sure we're legal */ 1.3341 + crv = sftk_GetContext(hSession,&context,SFTK_VERIFY_RECOVER, 1.3342 + PR_FALSE,&session); 1.3343 + if (crv != CKR_OK) return crv; 1.3344 + if (pData == NULL) { 1.3345 + /* to return the actual size, we need to do the decrypt, just return 1.3346 + * the max size, which is the size of the input signature. */ 1.3347 + *pulDataLen = ulSignatureLen; 1.3348 + rv = SECSuccess; 1.3349 + goto finish; 1.3350 + } 1.3351 + 1.3352 + rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, 1.3353 + pSignature, ulSignatureLen); 1.3354 + *pulDataLen = (CK_ULONG) outlen; 1.3355 + 1.3356 + sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context); 1.3357 +finish: 1.3358 + sftk_FreeSession(session); 1.3359 + return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError()); 1.3360 +} 1.3361 + 1.3362 +/* 1.3363 + **************************** Random Functions: ************************ 1.3364 + */ 1.3365 + 1.3366 +/* NSC_SeedRandom mixes additional seed material into the token's random number 1.3367 + * generator. */ 1.3368 +CK_RV NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, 1.3369 + CK_ULONG ulSeedLen) 1.3370 +{ 1.3371 + SECStatus rv; 1.3372 + 1.3373 + CHECK_FORK(); 1.3374 + 1.3375 + rv = RNG_RandomUpdate(pSeed, ulSeedLen); 1.3376 + return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); 1.3377 +} 1.3378 + 1.3379 +/* NSC_GenerateRandom generates random data. */ 1.3380 +CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession, 1.3381 + CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) 1.3382 +{ 1.3383 + SECStatus rv; 1.3384 + 1.3385 + CHECK_FORK(); 1.3386 + 1.3387 + rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen); 1.3388 + /* 1.3389 + * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't 1.3390 + * seeded with enough entropy. 1.3391 + */ 1.3392 + return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); 1.3393 +} 1.3394 + 1.3395 +/* 1.3396 + **************************** Key Functions: ************************ 1.3397 + */ 1.3398 + 1.3399 + 1.3400 +/* 1.3401 + * generate a password based encryption key. This code uses 1.3402 + * PKCS5 to do the work. 1.3403 + */ 1.3404 +static CK_RV 1.3405 +nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, 1.3406 + void *buf, CK_ULONG *key_length, PRBool faulty3DES) 1.3407 +{ 1.3408 + SECItem *pbe_key = NULL, iv, pwitem; 1.3409 + CK_PBE_PARAMS *pbe_params = NULL; 1.3410 + CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL; 1.3411 + 1.3412 + *key_length = 0; 1.3413 + iv.data = NULL; iv.len = 0; 1.3414 + 1.3415 + if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { 1.3416 + pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; 1.3417 + pwitem.data = (unsigned char *)pbkd2_params->pPassword; 1.3418 + /* was this a typo in the PKCS #11 spec? */ 1.3419 + pwitem.len = *pbkd2_params->ulPasswordLen; 1.3420 + } else { 1.3421 + pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; 1.3422 + pwitem.data = (unsigned char *)pbe_params->pPassword; 1.3423 + pwitem.len = pbe_params->ulPasswordLen; 1.3424 + } 1.3425 + pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES); 1.3426 + if (pbe_key == NULL) { 1.3427 + return CKR_HOST_MEMORY; 1.3428 + } 1.3429 + 1.3430 + PORT_Memcpy(buf, pbe_key->data, pbe_key->len); 1.3431 + *key_length = pbe_key->len; 1.3432 + SECITEM_ZfreeItem(pbe_key, PR_TRUE); 1.3433 + pbe_key = NULL; 1.3434 + 1.3435 + if (iv.data) { 1.3436 + if (pbe_params && pbe_params->pInitVector != NULL) { 1.3437 + PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); 1.3438 + } 1.3439 + PORT_Free(iv.data); 1.3440 + } 1.3441 + 1.3442 + return CKR_OK; 1.3443 +} 1.3444 + 1.3445 +/* 1.3446 + * this is coded for "full" support. These selections will be limitted to 1.3447 + * the official subset by freebl. 1.3448 + */ 1.3449 +static unsigned int 1.3450 +sftk_GetSubPrimeFromPrime(unsigned int primeBits) 1.3451 +{ 1.3452 + if (primeBits <= 1024) { 1.3453 + return 160; 1.3454 + } else if (primeBits <= 2048) { 1.3455 + return 224; 1.3456 + } else if (primeBits <= 3072) { 1.3457 + return 256; 1.3458 + } else if (primeBits <= 7680) { 1.3459 + return 384; 1.3460 + } else { 1.3461 + return 512; 1.3462 + } 1.3463 +} 1.3464 + 1.3465 +static CK_RV 1.3466 +nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) 1.3467 +{ 1.3468 + SFTKAttribute *attribute; 1.3469 + CK_ULONG counter; 1.3470 + unsigned int seedBits = 0; 1.3471 + unsigned int subprimeBits = 0; 1.3472 + unsigned int primeBits; 1.3473 + unsigned int j = 8; /* default to 1024 bits */ 1.3474 + CK_RV crv = CKR_OK; 1.3475 + PQGParams *params = NULL; 1.3476 + PQGVerify *vfy = NULL; 1.3477 + SECStatus rv; 1.3478 + 1.3479 + attribute = sftk_FindAttribute(key, CKA_PRIME_BITS); 1.3480 + if (attribute == NULL) { 1.3481 + return CKR_TEMPLATE_INCOMPLETE; 1.3482 + } 1.3483 + primeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue; 1.3484 + sftk_FreeAttribute(attribute); 1.3485 + if (primeBits < 1024) { 1.3486 + j = PQG_PBITS_TO_INDEX(primeBits); 1.3487 + if (j == (unsigned int)-1) { 1.3488 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.3489 + } 1.3490 + } 1.3491 + 1.3492 + attribute = sftk_FindAttribute(key, CKA_NETSCAPE_PQG_SEED_BITS); 1.3493 + if (attribute != NULL) { 1.3494 + seedBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue; 1.3495 + sftk_FreeAttribute(attribute); 1.3496 + } 1.3497 + 1.3498 + attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS); 1.3499 + if (attribute != NULL) { 1.3500 + subprimeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue; 1.3501 + sftk_FreeAttribute(attribute); 1.3502 + } 1.3503 + 1.3504 + sftk_DeleteAttributeType(key,CKA_PRIME_BITS); 1.3505 + sftk_DeleteAttributeType(key,CKA_SUBPRIME_BITS); 1.3506 + sftk_DeleteAttributeType(key,CKA_NETSCAPE_PQG_SEED_BITS); 1.3507 + 1.3508 + /* use the old PQG interface if we have old input data */ 1.3509 + if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) { 1.3510 + if (seedBits == 0) { 1.3511 + rv = PQG_ParamGen(j, ¶ms, &vfy); 1.3512 + } else { 1.3513 + rv = PQG_ParamGenSeedLen(j,seedBits/8, ¶ms, &vfy); 1.3514 + } 1.3515 + } else { 1.3516 + if (subprimeBits == 0) { 1.3517 + subprimeBits = sftk_GetSubPrimeFromPrime(primeBits); 1.3518 + } 1.3519 + if (seedBits == 0) { 1.3520 + seedBits = primeBits; 1.3521 + } 1.3522 + rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits/8, ¶ms, &vfy); 1.3523 + } 1.3524 + 1.3525 + 1.3526 + 1.3527 + if (rv != SECSuccess) { 1.3528 + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.3529 + sftk_fatalError = PR_TRUE; 1.3530 + } 1.3531 + return sftk_MapCryptError(PORT_GetError()); 1.3532 + } 1.3533 + crv = sftk_AddAttributeType(key,CKA_PRIME, 1.3534 + params->prime.data, params->prime.len); 1.3535 + if (crv != CKR_OK) goto loser; 1.3536 + crv = sftk_AddAttributeType(key,CKA_SUBPRIME, 1.3537 + params->subPrime.data, params->subPrime.len); 1.3538 + if (crv != CKR_OK) goto loser; 1.3539 + crv = sftk_AddAttributeType(key,CKA_BASE, 1.3540 + params->base.data, params->base.len); 1.3541 + if (crv != CKR_OK) goto loser; 1.3542 + counter = vfy->counter; 1.3543 + crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_COUNTER, 1.3544 + &counter, sizeof(counter)); 1.3545 + crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_SEED, 1.3546 + vfy->seed.data, vfy->seed.len); 1.3547 + if (crv != CKR_OK) goto loser; 1.3548 + crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_H, 1.3549 + vfy->h.data, vfy->h.len); 1.3550 + if (crv != CKR_OK) goto loser; 1.3551 + 1.3552 +loser: 1.3553 + PQG_DestroyParams(params); 1.3554 + 1.3555 + if (vfy) { 1.3556 + PQG_DestroyVerify(vfy); 1.3557 + } 1.3558 + return crv; 1.3559 +} 1.3560 + 1.3561 + 1.3562 +static CK_RV 1.3563 +nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type, 1.3564 + CK_ULONG *key_length) 1.3565 +{ 1.3566 + CK_RV crv = CKR_OK; 1.3567 + 1.3568 + switch (mechanism) { 1.3569 + case CKM_RC2_KEY_GEN: 1.3570 + *key_type = CKK_RC2; 1.3571 + if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; 1.3572 + break; 1.3573 +#if NSS_SOFTOKEN_DOES_RC5 1.3574 + case CKM_RC5_KEY_GEN: 1.3575 + *key_type = CKK_RC5; 1.3576 + if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; 1.3577 + break; 1.3578 +#endif 1.3579 + case CKM_RC4_KEY_GEN: 1.3580 + *key_type = CKK_RC4; 1.3581 + if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; 1.3582 + break; 1.3583 + case CKM_GENERIC_SECRET_KEY_GEN: 1.3584 + *key_type = CKK_GENERIC_SECRET; 1.3585 + if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; 1.3586 + break; 1.3587 + case CKM_CDMF_KEY_GEN: 1.3588 + *key_type = CKK_CDMF; 1.3589 + *key_length = 8; 1.3590 + break; 1.3591 + case CKM_DES_KEY_GEN: 1.3592 + *key_type = CKK_DES; 1.3593 + *key_length = 8; 1.3594 + break; 1.3595 + case CKM_DES2_KEY_GEN: 1.3596 + *key_type = CKK_DES2; 1.3597 + *key_length = 16; 1.3598 + break; 1.3599 + case CKM_DES3_KEY_GEN: 1.3600 + *key_type = CKK_DES3; 1.3601 + *key_length = 24; 1.3602 + break; 1.3603 + case CKM_SEED_KEY_GEN: 1.3604 + *key_type = CKK_SEED; 1.3605 + *key_length = 16; 1.3606 + break; 1.3607 + case CKM_CAMELLIA_KEY_GEN: 1.3608 + *key_type = CKK_CAMELLIA; 1.3609 + if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; 1.3610 + break; 1.3611 + case CKM_AES_KEY_GEN: 1.3612 + *key_type = CKK_AES; 1.3613 + if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; 1.3614 + break; 1.3615 + default: 1.3616 + PORT_Assert(0); 1.3617 + crv = CKR_MECHANISM_INVALID; 1.3618 + break; 1.3619 + } 1.3620 + 1.3621 + return crv; 1.3622 +} 1.3623 + 1.3624 +CK_RV 1.3625 +nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) 1.3626 +{ 1.3627 + SECItem salt; 1.3628 + CK_PBE_PARAMS *pbe_params = NULL; 1.3629 + NSSPKCS5PBEParameter *params; 1.3630 + PLArenaPool *arena = NULL; 1.3631 + SECStatus rv; 1.3632 + 1.3633 + *pbe = NULL; 1.3634 + 1.3635 + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.3636 + if (arena == NULL) { 1.3637 + return CKR_HOST_MEMORY; 1.3638 + } 1.3639 + 1.3640 + params = (NSSPKCS5PBEParameter *) PORT_ArenaZAlloc(arena, 1.3641 + sizeof(NSSPKCS5PBEParameter)); 1.3642 + if (params == NULL) { 1.3643 + PORT_FreeArena(arena,PR_TRUE); 1.3644 + return CKR_HOST_MEMORY; 1.3645 + } 1.3646 + 1.3647 + params->poolp = arena; 1.3648 + params->ivLen = 0; 1.3649 + params->pbeType = NSSPKCS5_PKCS12_V2; 1.3650 + params->hashType = HASH_AlgSHA1; 1.3651 + params->encAlg = SEC_OID_SHA1; /* any invalid value */ 1.3652 + params->is2KeyDES = PR_FALSE; 1.3653 + params->keyID = pbeBitGenIntegrityKey; 1.3654 + pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; 1.3655 + params->iter = pbe_params->ulIteration; 1.3656 + 1.3657 + salt.data = (unsigned char *)pbe_params->pSalt; 1.3658 + salt.len = (unsigned int)pbe_params->ulSaltLen; 1.3659 + rv = SECITEM_CopyItem(arena,¶ms->salt,&salt); 1.3660 + if (rv != SECSuccess) { 1.3661 + PORT_FreeArena(arena,PR_TRUE); 1.3662 + return CKR_HOST_MEMORY; 1.3663 + } 1.3664 + switch (pMechanism->mechanism) { 1.3665 + case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: 1.3666 + case CKM_PBA_SHA1_WITH_SHA1_HMAC: 1.3667 + params->hashType = HASH_AlgSHA1; 1.3668 + params->keyLen = 20; 1.3669 + break; 1.3670 + case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: 1.3671 + params->hashType = HASH_AlgMD5; 1.3672 + params->keyLen = 16; 1.3673 + break; 1.3674 + case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: 1.3675 + params->hashType = HASH_AlgMD2; 1.3676 + params->keyLen = 16; 1.3677 + break; 1.3678 + default: 1.3679 + PORT_FreeArena(arena,PR_TRUE); 1.3680 + return CKR_MECHANISM_INVALID; 1.3681 + } 1.3682 + *pbe = params; 1.3683 + return CKR_OK; 1.3684 +} 1.3685 + 1.3686 +/* maybe this should be table driven? */ 1.3687 +static CK_RV 1.3688 +nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, 1.3689 + CK_KEY_TYPE *key_type, CK_ULONG *key_length) 1.3690 +{ 1.3691 + CK_RV crv = CKR_OK; 1.3692 + SECOidData *oid; 1.3693 + CK_PBE_PARAMS *pbe_params = NULL; 1.3694 + NSSPKCS5PBEParameter *params = NULL; 1.3695 + CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL; 1.3696 + SECItem salt; 1.3697 + CK_ULONG iteration = 0; 1.3698 + 1.3699 + *pbe = NULL; 1.3700 + 1.3701 + oid = SECOID_FindOIDByMechanism(pMechanism->mechanism); 1.3702 + if (oid == NULL) { 1.3703 + return CKR_MECHANISM_INVALID; 1.3704 + } 1.3705 + 1.3706 + if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { 1.3707 + pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; 1.3708 + if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) { 1.3709 + return CKR_MECHANISM_PARAM_INVALID; 1.3710 + } 1.3711 + salt.data = (unsigned char *)pbkd2_params->pSaltSourceData; 1.3712 + salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen; 1.3713 + iteration = pbkd2_params->iterations; 1.3714 + } else { 1.3715 + pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; 1.3716 + salt.data = (unsigned char *)pbe_params->pSalt; 1.3717 + salt.len = (unsigned int)pbe_params->ulSaltLen; 1.3718 + iteration = pbe_params->ulIteration; 1.3719 + } 1.3720 + params=nsspkcs5_NewParam(oid->offset, &salt, iteration); 1.3721 + if (params == NULL) { 1.3722 + return CKR_MECHANISM_INVALID; 1.3723 + } 1.3724 + 1.3725 + switch (params->encAlg) { 1.3726 + case SEC_OID_DES_CBC: 1.3727 + *key_type = CKK_DES; 1.3728 + *key_length = params->keyLen; 1.3729 + break; 1.3730 + case SEC_OID_DES_EDE3_CBC: 1.3731 + *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3; 1.3732 + *key_length = params->keyLen; 1.3733 + break; 1.3734 + case SEC_OID_RC2_CBC: 1.3735 + *key_type = CKK_RC2; 1.3736 + *key_length = params->keyLen; 1.3737 + break; 1.3738 + case SEC_OID_RC4: 1.3739 + *key_type = CKK_RC4; 1.3740 + *key_length = params->keyLen; 1.3741 + break; 1.3742 + case SEC_OID_PKCS5_PBKDF2: 1.3743 + /* sigh, PKCS #11 currently only defines SHA1 for the KDF hash type. 1.3744 + * we do the check here because this where we would handle multiple 1.3745 + * hash types in the future */ 1.3746 + if (pbkd2_params == NULL || 1.3747 + pbkd2_params->prf != CKP_PKCS5_PBKD2_HMAC_SHA1) { 1.3748 + crv = CKR_MECHANISM_PARAM_INVALID; 1.3749 + break; 1.3750 + } 1.3751 + /* key type must already be set */ 1.3752 + if (*key_type == CKK_INVALID_KEY_TYPE) { 1.3753 + crv = CKR_TEMPLATE_INCOMPLETE; 1.3754 + break; 1.3755 + } 1.3756 + /* PBKDF2 needs to calculate the key length from the other parameters 1.3757 + */ 1.3758 + if (*key_length == 0) { 1.3759 + *key_length = sftk_MapKeySize(*key_type); 1.3760 + } 1.3761 + if (*key_length == 0) { 1.3762 + crv = CKR_TEMPLATE_INCOMPLETE; 1.3763 + break; 1.3764 + } 1.3765 + params->keyLen = *key_length; 1.3766 + break; 1.3767 + default: 1.3768 + crv = CKR_MECHANISM_INVALID; 1.3769 + nsspkcs5_DestroyPBEParameter(params); 1.3770 + break; 1.3771 + } 1.3772 + if (crv == CKR_OK) { 1.3773 + *pbe = params; 1.3774 + } 1.3775 + return crv; 1.3776 +} 1.3777 + 1.3778 +/* NSC_GenerateKey generates a secret key, creating a new key object. */ 1.3779 +CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, 1.3780 + CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, 1.3781 + CK_OBJECT_HANDLE_PTR phKey) 1.3782 +{ 1.3783 + SFTKObject *key; 1.3784 + SFTKSession *session; 1.3785 + PRBool checkWeak = PR_FALSE; 1.3786 + CK_ULONG key_length = 0; 1.3787 + CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE; 1.3788 + CK_OBJECT_CLASS objclass = CKO_SECRET_KEY; 1.3789 + CK_RV crv = CKR_OK; 1.3790 + CK_BBOOL cktrue = CK_TRUE; 1.3791 + int i; 1.3792 + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 1.3793 + unsigned char buf[MAX_KEY_LEN]; 1.3794 + enum {nsc_pbe, nsc_ssl, nsc_bulk, nsc_param, nsc_jpake} key_gen_type; 1.3795 + NSSPKCS5PBEParameter *pbe_param; 1.3796 + SSL3RSAPreMasterSecret *rsa_pms; 1.3797 + CK_VERSION *version; 1.3798 + /* in very old versions of NSS, there were implementation errors with key 1.3799 + * generation methods. We want to beable to read these, but not 1.3800 + * produce them any more. The affected algorithm was 3DES. 1.3801 + */ 1.3802 + PRBool faultyPBE3DES = PR_FALSE; 1.3803 + HASH_HashType hashType; 1.3804 + 1.3805 + CHECK_FORK(); 1.3806 + 1.3807 + if (!slot) { 1.3808 + return CKR_SESSION_HANDLE_INVALID; 1.3809 + } 1.3810 + /* 1.3811 + * now lets create an object to hang the attributes off of 1.3812 + */ 1.3813 + key = sftk_NewObject(slot); /* fill in the handle later */ 1.3814 + if (key == NULL) { 1.3815 + return CKR_HOST_MEMORY; 1.3816 + } 1.3817 + 1.3818 + /* 1.3819 + * load the template values into the object 1.3820 + */ 1.3821 + for (i=0; i < (int) ulCount; i++) { 1.3822 + if (pTemplate[i].type == CKA_VALUE_LEN) { 1.3823 + key_length = *(CK_ULONG *)pTemplate[i].pValue; 1.3824 + continue; 1.3825 + } 1.3826 + /* some algorithms need keytype specified */ 1.3827 + if (pTemplate[i].type == CKA_KEY_TYPE) { 1.3828 + key_type = *(CK_ULONG *)pTemplate[i].pValue; 1.3829 + continue; 1.3830 + } 1.3831 + 1.3832 + crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i])); 1.3833 + if (crv != CKR_OK) break; 1.3834 + } 1.3835 + if (crv != CKR_OK) { 1.3836 + sftk_FreeObject(key); 1.3837 + return crv; 1.3838 + } 1.3839 + 1.3840 + /* make sure we don't have any class, key_type, or value fields */ 1.3841 + sftk_DeleteAttributeType(key,CKA_CLASS); 1.3842 + sftk_DeleteAttributeType(key,CKA_KEY_TYPE); 1.3843 + sftk_DeleteAttributeType(key,CKA_VALUE); 1.3844 + 1.3845 + /* Now Set up the parameters to generate the key (based on mechanism) */ 1.3846 + key_gen_type = nsc_bulk; /* bulk key by default */ 1.3847 + switch (pMechanism->mechanism) { 1.3848 + case CKM_CDMF_KEY_GEN: 1.3849 + case CKM_DES_KEY_GEN: 1.3850 + case CKM_DES2_KEY_GEN: 1.3851 + case CKM_DES3_KEY_GEN: 1.3852 + checkWeak = PR_TRUE; 1.3853 + /* fall through */ 1.3854 + case CKM_RC2_KEY_GEN: 1.3855 + case CKM_RC4_KEY_GEN: 1.3856 + case CKM_GENERIC_SECRET_KEY_GEN: 1.3857 + case CKM_SEED_KEY_GEN: 1.3858 + case CKM_CAMELLIA_KEY_GEN: 1.3859 + case CKM_AES_KEY_GEN: 1.3860 +#if NSS_SOFTOKEN_DOES_RC5 1.3861 + case CKM_RC5_KEY_GEN: 1.3862 +#endif 1.3863 + crv = nsc_SetupBulkKeyGen(pMechanism->mechanism,&key_type,&key_length); 1.3864 + break; 1.3865 + case CKM_SSL3_PRE_MASTER_KEY_GEN: 1.3866 + key_type = CKK_GENERIC_SECRET; 1.3867 + key_length = 48; 1.3868 + key_gen_type = nsc_ssl; 1.3869 + break; 1.3870 + case CKM_PBA_SHA1_WITH_SHA1_HMAC: 1.3871 + case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: 1.3872 + case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: 1.3873 + case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: 1.3874 + key_gen_type = nsc_pbe; 1.3875 + key_type = CKK_GENERIC_SECRET; 1.3876 + crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param); 1.3877 + break; 1.3878 + case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: 1.3879 + faultyPBE3DES = PR_TRUE; 1.3880 + /* fall through */ 1.3881 + case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: 1.3882 + case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: 1.3883 + case CKM_NETSCAPE_PBE_SHA1_DES_CBC: 1.3884 + case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: 1.3885 + case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: 1.3886 + case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: 1.3887 + case CKM_PBE_SHA1_DES3_EDE_CBC: 1.3888 + case CKM_PBE_SHA1_DES2_EDE_CBC: 1.3889 + case CKM_PBE_SHA1_RC2_128_CBC: 1.3890 + case CKM_PBE_SHA1_RC2_40_CBC: 1.3891 + case CKM_PBE_SHA1_RC4_128: 1.3892 + case CKM_PBE_SHA1_RC4_40: 1.3893 + case CKM_PBE_MD5_DES_CBC: 1.3894 + case CKM_PBE_MD2_DES_CBC: 1.3895 + case CKM_PKCS5_PBKD2: 1.3896 + key_gen_type = nsc_pbe; 1.3897 + crv = nsc_SetupPBEKeyGen(pMechanism,&pbe_param, &key_type, &key_length); 1.3898 + break; 1.3899 + case CKM_DSA_PARAMETER_GEN: 1.3900 + key_gen_type = nsc_param; 1.3901 + key_type = CKK_DSA; 1.3902 + objclass = CKO_KG_PARAMETERS; 1.3903 + crv = CKR_OK; 1.3904 + break; 1.3905 + case CKM_NSS_JPAKE_ROUND1_SHA1: hashType = HASH_AlgSHA1; goto jpake1; 1.3906 + case CKM_NSS_JPAKE_ROUND1_SHA256: hashType = HASH_AlgSHA256; goto jpake1; 1.3907 + case CKM_NSS_JPAKE_ROUND1_SHA384: hashType = HASH_AlgSHA384; goto jpake1; 1.3908 + case CKM_NSS_JPAKE_ROUND1_SHA512: hashType = HASH_AlgSHA512; goto jpake1; 1.3909 +jpake1: 1.3910 + key_gen_type = nsc_jpake; 1.3911 + key_type = CKK_NSS_JPAKE_ROUND1; 1.3912 + objclass = CKO_PRIVATE_KEY; 1.3913 + if (pMechanism->pParameter == NULL || 1.3914 + pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) { 1.3915 + crv = CKR_MECHANISM_PARAM_INVALID; 1.3916 + break; 1.3917 + } 1.3918 + if (sftk_isTrue(key, CKA_TOKEN)) { 1.3919 + crv = CKR_TEMPLATE_INCONSISTENT; 1.3920 + break; 1.3921 + } 1.3922 + crv = CKR_OK; 1.3923 + break; 1.3924 + default: 1.3925 + crv = CKR_MECHANISM_INVALID; 1.3926 + break; 1.3927 + } 1.3928 + 1.3929 + /* make sure we aren't going to overflow the buffer */ 1.3930 + if (sizeof(buf) < key_length) { 1.3931 + /* someone is getting pretty optimistic about how big their key can 1.3932 + * be... */ 1.3933 + crv = CKR_TEMPLATE_INCONSISTENT; 1.3934 + } 1.3935 + 1.3936 + if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } 1.3937 + 1.3938 + /* if there was no error, 1.3939 + * key_type *MUST* be set in the switch statement above */ 1.3940 + PORT_Assert( key_type != CKK_INVALID_KEY_TYPE ); 1.3941 + 1.3942 + /* 1.3943 + * now to the actual key gen. 1.3944 + */ 1.3945 + switch (key_gen_type) { 1.3946 + case nsc_pbe: 1.3947 + crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length, 1.3948 + faultyPBE3DES); 1.3949 + nsspkcs5_DestroyPBEParameter(pbe_param); 1.3950 + break; 1.3951 + case nsc_ssl: 1.3952 + rsa_pms = (SSL3RSAPreMasterSecret *)buf; 1.3953 + version = (CK_VERSION *)pMechanism->pParameter; 1.3954 + rsa_pms->client_version[0] = version->major; 1.3955 + rsa_pms->client_version[1] = version->minor; 1.3956 + crv = 1.3957 + NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random)); 1.3958 + break; 1.3959 + case nsc_bulk: 1.3960 + /* get the key, check for weak keys and repeat if found */ 1.3961 + do { 1.3962 + crv = NSC_GenerateRandom(0, buf, key_length); 1.3963 + } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf,key_type)); 1.3964 + break; 1.3965 + case nsc_param: 1.3966 + /* generate parameters */ 1.3967 + *buf = 0; 1.3968 + crv = nsc_parameter_gen(key_type,key); 1.3969 + break; 1.3970 + case nsc_jpake: 1.3971 + crv = jpake_Round1(hashType, 1.3972 + (CK_NSS_JPAKERound1Params *) pMechanism->pParameter, 1.3973 + key); 1.3974 + break; 1.3975 + } 1.3976 + 1.3977 + if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } 1.3978 + 1.3979 + /* Add the class, key_type, and value */ 1.3980 + crv = sftk_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS)); 1.3981 + if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } 1.3982 + crv = sftk_AddAttributeType(key,CKA_KEY_TYPE,&key_type,sizeof(CK_KEY_TYPE)); 1.3983 + if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } 1.3984 + if (key_length != 0) { 1.3985 + crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length); 1.3986 + if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } 1.3987 + } 1.3988 + 1.3989 + /* get the session */ 1.3990 + session = sftk_SessionFromHandle(hSession); 1.3991 + if (session == NULL) { 1.3992 + sftk_FreeObject(key); 1.3993 + return CKR_SESSION_HANDLE_INVALID; 1.3994 + } 1.3995 + 1.3996 + /* 1.3997 + * handle the base object stuff 1.3998 + */ 1.3999 + crv = sftk_handleObject(key,session); 1.4000 + sftk_FreeSession(session); 1.4001 + if (sftk_isTrue(key,CKA_SENSITIVE)) { 1.4002 + sftk_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL)); 1.4003 + } 1.4004 + if (!sftk_isTrue(key,CKA_EXTRACTABLE)) { 1.4005 + sftk_forceAttribute(key,CKA_NEVER_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL)); 1.4006 + } 1.4007 + 1.4008 + *phKey = key->handle; 1.4009 + sftk_FreeObject(key); 1.4010 + return crv; 1.4011 +} 1.4012 + 1.4013 +#define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */ 1.4014 +#define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ 1.4015 + 1.4016 +/* 1.4017 + * FIPS 140-2 pairwise consistency check utilized to validate key pair. 1.4018 + * 1.4019 + * This function returns 1.4020 + * CKR_OK if pairwise consistency check passed 1.4021 + * CKR_GENERAL_ERROR if pairwise consistency check failed 1.4022 + * other error codes if paiswise consistency check could not be 1.4023 + * performed, for example, CKR_HOST_MEMORY. 1.4024 + */ 1.4025 +static CK_RV 1.4026 +sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, 1.4027 + SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType) 1.4028 +{ 1.4029 + /* 1.4030 + * Key type Mechanism type 1.4031 + * -------------------------------- 1.4032 + * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS 1.4033 + * others => CKM_INVALID_MECHANISM 1.4034 + * 1.4035 + * For sign/verify: CKK_RSA => CKM_RSA_PKCS 1.4036 + * CKK_DSA => CKM_DSA 1.4037 + * CKK_EC => CKM_ECDSA 1.4038 + * others => CKM_INVALID_MECHANISM 1.4039 + * 1.4040 + * None of these mechanisms has a parameter. 1.4041 + */ 1.4042 + CK_MECHANISM mech = {0, NULL, 0}; 1.4043 + 1.4044 + CK_ULONG modulusLen; 1.4045 + CK_ULONG subPrimeLen; 1.4046 + PRBool isEncryptable = PR_FALSE; 1.4047 + PRBool canSignVerify = PR_FALSE; 1.4048 + PRBool isDerivable = PR_FALSE; 1.4049 + CK_RV crv; 1.4050 + 1.4051 + /* Variables used for Encrypt/Decrypt functions. */ 1.4052 + unsigned char *known_message = (unsigned char *)"Known Crypto Message"; 1.4053 + unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH]; 1.4054 + CK_ULONG bytes_decrypted; 1.4055 + unsigned char *ciphertext; 1.4056 + unsigned char *text_compared; 1.4057 + CK_ULONG bytes_encrypted; 1.4058 + CK_ULONG bytes_compared; 1.4059 + CK_ULONG pairwise_digest_length = PAIRWISE_DIGEST_LENGTH; 1.4060 + 1.4061 + /* Variables used for Signature/Verification functions. */ 1.4062 + /* Must be at least 256 bits for DSA2 digest */ 1.4063 + unsigned char *known_digest = (unsigned char *) 1.4064 + "Mozilla Rules the World through NSS!"; 1.4065 + unsigned char *signature; 1.4066 + CK_ULONG signature_length; 1.4067 + 1.4068 + if (keyType == CKK_RSA) { 1.4069 + SFTKAttribute *attribute; 1.4070 + 1.4071 + /* Get modulus length of private key. */ 1.4072 + attribute = sftk_FindAttribute(privateKey, CKA_MODULUS); 1.4073 + if (attribute == NULL) { 1.4074 + return CKR_DEVICE_ERROR; 1.4075 + } 1.4076 + modulusLen = attribute->attrib.ulValueLen; 1.4077 + if (*(unsigned char *)attribute->attrib.pValue == 0) { 1.4078 + modulusLen--; 1.4079 + } 1.4080 + sftk_FreeAttribute(attribute); 1.4081 + } else if (keyType == CKK_DSA) { 1.4082 + SFTKAttribute *attribute; 1.4083 + 1.4084 + /* Get subprime length of private key. */ 1.4085 + attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME); 1.4086 + if (attribute == NULL) { 1.4087 + return CKR_DEVICE_ERROR; 1.4088 + } 1.4089 + subPrimeLen = attribute->attrib.ulValueLen; 1.4090 + if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) { 1.4091 + subPrimeLen--; 1.4092 + } 1.4093 + sftk_FreeAttribute(attribute); 1.4094 + } 1.4095 + 1.4096 + /**************************************************/ 1.4097 + /* Pairwise Consistency Check of Encrypt/Decrypt. */ 1.4098 + /**************************************************/ 1.4099 + 1.4100 + isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT); 1.4101 + 1.4102 + /* 1.4103 + * If the decryption attribute is set, attempt to encrypt 1.4104 + * with the public key and decrypt with the private key. 1.4105 + */ 1.4106 + if (isEncryptable) { 1.4107 + if (keyType != CKK_RSA) { 1.4108 + return CKR_DEVICE_ERROR; 1.4109 + } 1.4110 + bytes_encrypted = modulusLen; 1.4111 + mech.mechanism = CKM_RSA_PKCS; 1.4112 + 1.4113 + /* Allocate space for ciphertext. */ 1.4114 + ciphertext = (unsigned char *) PORT_ZAlloc(bytes_encrypted); 1.4115 + if (ciphertext == NULL) { 1.4116 + return CKR_HOST_MEMORY; 1.4117 + } 1.4118 + 1.4119 + /* Prepare for encryption using the public key. */ 1.4120 + crv = NSC_EncryptInit(hSession, &mech, publicKey->handle); 1.4121 + if (crv != CKR_OK) { 1.4122 + PORT_Free(ciphertext); 1.4123 + return crv; 1.4124 + } 1.4125 + 1.4126 + /* Encrypt using the public key. */ 1.4127 + crv = NSC_Encrypt(hSession, 1.4128 + known_message, 1.4129 + PAIRWISE_MESSAGE_LENGTH, 1.4130 + ciphertext, 1.4131 + &bytes_encrypted); 1.4132 + if (crv != CKR_OK) { 1.4133 + PORT_Free(ciphertext); 1.4134 + return crv; 1.4135 + } 1.4136 + 1.4137 + /* Always use the smaller of these two values . . . */ 1.4138 + bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH); 1.4139 + 1.4140 + /* 1.4141 + * If there was a failure, the plaintext 1.4142 + * goes at the end, therefore . . . 1.4143 + */ 1.4144 + text_compared = ciphertext + bytes_encrypted - bytes_compared; 1.4145 + 1.4146 + /* 1.4147 + * Check to ensure that ciphertext does 1.4148 + * NOT EQUAL known input message text 1.4149 + * per FIPS PUB 140-2 directive. 1.4150 + */ 1.4151 + if (PORT_Memcmp(text_compared, known_message, 1.4152 + bytes_compared) == 0) { 1.4153 + /* Set error to Invalid PRIVATE Key. */ 1.4154 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.4155 + PORT_Free(ciphertext); 1.4156 + return CKR_GENERAL_ERROR; 1.4157 + } 1.4158 + 1.4159 + /* Prepare for decryption using the private key. */ 1.4160 + crv = NSC_DecryptInit(hSession, &mech, privateKey->handle); 1.4161 + if (crv != CKR_OK) { 1.4162 + PORT_Free(ciphertext); 1.4163 + return crv; 1.4164 + } 1.4165 + 1.4166 + memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH); 1.4167 + 1.4168 + /* 1.4169 + * Initialize bytes decrypted to be the 1.4170 + * expected PAIRWISE_MESSAGE_LENGTH. 1.4171 + */ 1.4172 + bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; 1.4173 + 1.4174 + /* 1.4175 + * Decrypt using the private key. 1.4176 + * NOTE: No need to reset the 1.4177 + * value of bytes_encrypted. 1.4178 + */ 1.4179 + crv = NSC_Decrypt(hSession, 1.4180 + ciphertext, 1.4181 + bytes_encrypted, 1.4182 + plaintext, 1.4183 + &bytes_decrypted); 1.4184 + 1.4185 + /* Finished with ciphertext; free it. */ 1.4186 + PORT_Free(ciphertext); 1.4187 + 1.4188 + if (crv != CKR_OK) { 1.4189 + return crv; 1.4190 + } 1.4191 + 1.4192 + /* 1.4193 + * Check to ensure that the output plaintext 1.4194 + * does EQUAL known input message text. 1.4195 + */ 1.4196 + if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) || 1.4197 + (PORT_Memcmp(plaintext, known_message, 1.4198 + PAIRWISE_MESSAGE_LENGTH) != 0)) { 1.4199 + /* Set error to Bad PUBLIC Key. */ 1.4200 + PORT_SetError(SEC_ERROR_BAD_KEY); 1.4201 + return CKR_GENERAL_ERROR; 1.4202 + } 1.4203 + } 1.4204 + 1.4205 + /**********************************************/ 1.4206 + /* Pairwise Consistency Check of Sign/Verify. */ 1.4207 + /**********************************************/ 1.4208 + 1.4209 + canSignVerify = sftk_isTrue(privateKey, CKA_SIGN); 1.4210 + 1.4211 + if (canSignVerify) { 1.4212 + /* Determine length of signature. */ 1.4213 + switch (keyType) { 1.4214 + case CKK_RSA: 1.4215 + signature_length = modulusLen; 1.4216 + mech.mechanism = CKM_RSA_PKCS; 1.4217 + break; 1.4218 + case CKK_DSA: 1.4219 + signature_length = DSA_MAX_SIGNATURE_LEN; 1.4220 + pairwise_digest_length = subPrimeLen; 1.4221 + mech.mechanism = CKM_DSA; 1.4222 + break; 1.4223 +#ifndef NSS_DISABLE_ECC 1.4224 + case CKK_EC: 1.4225 + signature_length = MAX_ECKEY_LEN * 2; 1.4226 + mech.mechanism = CKM_ECDSA; 1.4227 + break; 1.4228 +#endif 1.4229 + default: 1.4230 + return CKR_DEVICE_ERROR; 1.4231 + } 1.4232 + 1.4233 + /* Allocate space for signature data. */ 1.4234 + signature = (unsigned char *) PORT_ZAlloc(signature_length); 1.4235 + if (signature == NULL) { 1.4236 + return CKR_HOST_MEMORY; 1.4237 + } 1.4238 + 1.4239 + /* Sign the known hash using the private key. */ 1.4240 + crv = NSC_SignInit(hSession, &mech, privateKey->handle); 1.4241 + if (crv != CKR_OK) { 1.4242 + PORT_Free(signature); 1.4243 + return crv; 1.4244 + } 1.4245 + 1.4246 + crv = NSC_Sign(hSession, 1.4247 + known_digest, 1.4248 + pairwise_digest_length, 1.4249 + signature, 1.4250 + &signature_length); 1.4251 + if (crv != CKR_OK) { 1.4252 + PORT_Free(signature); 1.4253 + return crv; 1.4254 + } 1.4255 + 1.4256 + /* Verify the known hash using the public key. */ 1.4257 + crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); 1.4258 + if (crv != CKR_OK) { 1.4259 + PORT_Free(signature); 1.4260 + return crv; 1.4261 + } 1.4262 + 1.4263 + crv = NSC_Verify(hSession, 1.4264 + known_digest, 1.4265 + pairwise_digest_length, 1.4266 + signature, 1.4267 + signature_length); 1.4268 + 1.4269 + /* Free signature data. */ 1.4270 + PORT_Free(signature); 1.4271 + 1.4272 + if ((crv == CKR_SIGNATURE_LEN_RANGE) || 1.4273 + (crv == CKR_SIGNATURE_INVALID)) { 1.4274 + return CKR_GENERAL_ERROR; 1.4275 + } 1.4276 + if (crv != CKR_OK) { 1.4277 + return crv; 1.4278 + } 1.4279 + } 1.4280 + 1.4281 + /**********************************************/ 1.4282 + /* Pairwise Consistency Check for Derivation */ 1.4283 + /**********************************************/ 1.4284 + 1.4285 + isDerivable = sftk_isTrue(privateKey, CKA_DERIVE); 1.4286 + 1.4287 + if (isDerivable) { 1.4288 + /* 1.4289 + * We are not doing consistency check for Diffie-Hellman Key - 1.4290 + * otherwise it would be here 1.4291 + * This is also true for Elliptic Curve Diffie-Hellman keys 1.4292 + * NOTE: EC keys are currently subjected to pairwise 1.4293 + * consistency check for signing/verification. 1.4294 + */ 1.4295 + /* 1.4296 + * FIPS 140-2 had the following pairwise consistency test for 1.4297 + * public and private keys used for key agreement: 1.4298 + * If the keys are used to perform key agreement, then the 1.4299 + * cryptographic module shall create a second, compatible 1.4300 + * key pair. The cryptographic module shall perform both 1.4301 + * sides of the key agreement algorithm and shall compare 1.4302 + * the resulting shared values. If the shared values are 1.4303 + * not equal, the test shall fail. 1.4304 + * This test was removed in Change Notice 3. 1.4305 + */ 1.4306 + 1.4307 + } 1.4308 + 1.4309 + return CKR_OK; 1.4310 +} 1.4311 + 1.4312 +/* NSC_GenerateKeyPair generates a public-key/private-key pair, 1.4313 + * creating new key objects. */ 1.4314 +CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession, 1.4315 + CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, 1.4316 + CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, 1.4317 + CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, 1.4318 + CK_OBJECT_HANDLE_PTR phPrivateKey) 1.4319 +{ 1.4320 + SFTKObject * publicKey,*privateKey; 1.4321 + SFTKSession * session; 1.4322 + CK_KEY_TYPE key_type; 1.4323 + CK_RV crv = CKR_OK; 1.4324 + CK_BBOOL cktrue = CK_TRUE; 1.4325 + SECStatus rv; 1.4326 + CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; 1.4327 + CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; 1.4328 + int i; 1.4329 + SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession); 1.4330 + unsigned int bitSize; 1.4331 + 1.4332 + /* RSA */ 1.4333 + int public_modulus_bits = 0; 1.4334 + SECItem pubExp; 1.4335 + RSAPrivateKey * rsaPriv; 1.4336 + 1.4337 + /* DSA */ 1.4338 + PQGParams pqgParam; 1.4339 + DHParams dhParam; 1.4340 + DSAPrivateKey * dsaPriv; 1.4341 + 1.4342 + /* Diffie Hellman */ 1.4343 + int private_value_bits = 0; 1.4344 + DHPrivateKey * dhPriv; 1.4345 + 1.4346 +#ifndef NSS_DISABLE_ECC 1.4347 + /* Elliptic Curve Cryptography */ 1.4348 + SECItem ecEncodedParams; /* DER Encoded parameters */ 1.4349 + ECPrivateKey * ecPriv; 1.4350 + ECParams * ecParams; 1.4351 +#endif /* NSS_DISABLE_ECC */ 1.4352 + 1.4353 + CHECK_FORK(); 1.4354 + 1.4355 + if (!slot) { 1.4356 + return CKR_SESSION_HANDLE_INVALID; 1.4357 + } 1.4358 + /* 1.4359 + * now lets create an object to hang the attributes off of 1.4360 + */ 1.4361 + publicKey = sftk_NewObject(slot); /* fill in the handle later */ 1.4362 + if (publicKey == NULL) { 1.4363 + return CKR_HOST_MEMORY; 1.4364 + } 1.4365 + 1.4366 + /* 1.4367 + * load the template values into the publicKey 1.4368 + */ 1.4369 + for (i=0; i < (int) ulPublicKeyAttributeCount; i++) { 1.4370 + if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) { 1.4371 + public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue; 1.4372 + continue; 1.4373 + } 1.4374 + 1.4375 + crv = sftk_AddAttributeType(publicKey, 1.4376 + sftk_attr_expand(&pPublicKeyTemplate[i])); 1.4377 + if (crv != CKR_OK) break; 1.4378 + } 1.4379 + 1.4380 + if (crv != CKR_OK) { 1.4381 + sftk_FreeObject(publicKey); 1.4382 + return CKR_HOST_MEMORY; 1.4383 + } 1.4384 + 1.4385 + privateKey = sftk_NewObject(slot); /* fill in the handle later */ 1.4386 + if (privateKey == NULL) { 1.4387 + sftk_FreeObject(publicKey); 1.4388 + return CKR_HOST_MEMORY; 1.4389 + } 1.4390 + /* 1.4391 + * now load the private key template 1.4392 + */ 1.4393 + for (i=0; i < (int) ulPrivateKeyAttributeCount; i++) { 1.4394 + if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) { 1.4395 + private_value_bits = *(CK_ULONG *)pPrivateKeyTemplate[i].pValue; 1.4396 + continue; 1.4397 + } 1.4398 + 1.4399 + crv = sftk_AddAttributeType(privateKey, 1.4400 + sftk_attr_expand(&pPrivateKeyTemplate[i])); 1.4401 + if (crv != CKR_OK) break; 1.4402 + } 1.4403 + 1.4404 + if (crv != CKR_OK) { 1.4405 + sftk_FreeObject(publicKey); 1.4406 + sftk_FreeObject(privateKey); 1.4407 + return CKR_HOST_MEMORY; 1.4408 + } 1.4409 + sftk_DeleteAttributeType(privateKey,CKA_CLASS); 1.4410 + sftk_DeleteAttributeType(privateKey,CKA_KEY_TYPE); 1.4411 + sftk_DeleteAttributeType(privateKey,CKA_VALUE); 1.4412 + sftk_DeleteAttributeType(publicKey,CKA_CLASS); 1.4413 + sftk_DeleteAttributeType(publicKey,CKA_KEY_TYPE); 1.4414 + sftk_DeleteAttributeType(publicKey,CKA_VALUE); 1.4415 + 1.4416 + /* Now Set up the parameters to generate the key (based on mechanism) */ 1.4417 + switch (pMechanism->mechanism) { 1.4418 + case CKM_RSA_PKCS_KEY_PAIR_GEN: 1.4419 + /* format the keys */ 1.4420 + sftk_DeleteAttributeType(publicKey,CKA_MODULUS); 1.4421 + sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); 1.4422 + sftk_DeleteAttributeType(privateKey,CKA_MODULUS); 1.4423 + sftk_DeleteAttributeType(privateKey,CKA_PRIVATE_EXPONENT); 1.4424 + sftk_DeleteAttributeType(privateKey,CKA_PUBLIC_EXPONENT); 1.4425 + sftk_DeleteAttributeType(privateKey,CKA_PRIME_1); 1.4426 + sftk_DeleteAttributeType(privateKey,CKA_PRIME_2); 1.4427 + sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_1); 1.4428 + sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_2); 1.4429 + sftk_DeleteAttributeType(privateKey,CKA_COEFFICIENT); 1.4430 + key_type = CKK_RSA; 1.4431 + if (public_modulus_bits == 0) { 1.4432 + crv = CKR_TEMPLATE_INCOMPLETE; 1.4433 + break; 1.4434 + } 1.4435 + if (public_modulus_bits < RSA_MIN_MODULUS_BITS) { 1.4436 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.4437 + break; 1.4438 + } 1.4439 + if (public_modulus_bits % 2 != 0) { 1.4440 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.4441 + break; 1.4442 + } 1.4443 + 1.4444 + /* extract the exponent */ 1.4445 + crv=sftk_Attribute2SSecItem(NULL,&pubExp,publicKey,CKA_PUBLIC_EXPONENT); 1.4446 + if (crv != CKR_OK) break; 1.4447 + bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len); 1.4448 + if (bitSize < 2) { 1.4449 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.4450 + break; 1.4451 + } 1.4452 + crv = sftk_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT, 1.4453 + sftk_item_expand(&pubExp)); 1.4454 + if (crv != CKR_OK) { 1.4455 + PORT_Free(pubExp.data); 1.4456 + break; 1.4457 + } 1.4458 + 1.4459 + rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp); 1.4460 + PORT_Free(pubExp.data); 1.4461 + if (rsaPriv == NULL) { 1.4462 + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.4463 + sftk_fatalError = PR_TRUE; 1.4464 + } 1.4465 + crv = sftk_MapCryptError(PORT_GetError()); 1.4466 + break; 1.4467 + } 1.4468 + /* now fill in the RSA dependent paramenters in the public key */ 1.4469 + crv = sftk_AddAttributeType(publicKey,CKA_MODULUS, 1.4470 + sftk_item_expand(&rsaPriv->modulus)); 1.4471 + if (crv != CKR_OK) goto kpg_done; 1.4472 + /* now fill in the RSA dependent paramenters in the private key */ 1.4473 + crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, 1.4474 + sftk_item_expand(&rsaPriv->modulus)); 1.4475 + if (crv != CKR_OK) goto kpg_done; 1.4476 + crv = sftk_AddAttributeType(privateKey,CKA_MODULUS, 1.4477 + sftk_item_expand(&rsaPriv->modulus)); 1.4478 + if (crv != CKR_OK) goto kpg_done; 1.4479 + crv = sftk_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT, 1.4480 + sftk_item_expand(&rsaPriv->privateExponent)); 1.4481 + if (crv != CKR_OK) goto kpg_done; 1.4482 + crv = sftk_AddAttributeType(privateKey,CKA_PRIME_1, 1.4483 + sftk_item_expand(&rsaPriv->prime1)); 1.4484 + if (crv != CKR_OK) goto kpg_done; 1.4485 + crv = sftk_AddAttributeType(privateKey,CKA_PRIME_2, 1.4486 + sftk_item_expand(&rsaPriv->prime2)); 1.4487 + if (crv != CKR_OK) goto kpg_done; 1.4488 + crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_1, 1.4489 + sftk_item_expand(&rsaPriv->exponent1)); 1.4490 + if (crv != CKR_OK) goto kpg_done; 1.4491 + crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_2, 1.4492 + sftk_item_expand(&rsaPriv->exponent2)); 1.4493 + if (crv != CKR_OK) goto kpg_done; 1.4494 + crv = sftk_AddAttributeType(privateKey,CKA_COEFFICIENT, 1.4495 + sftk_item_expand(&rsaPriv->coefficient)); 1.4496 +kpg_done: 1.4497 + /* Should zeroize the contents first, since this func doesn't. */ 1.4498 + PORT_FreeArena(rsaPriv->arena, PR_TRUE); 1.4499 + break; 1.4500 + case CKM_DSA_KEY_PAIR_GEN: 1.4501 + sftk_DeleteAttributeType(publicKey,CKA_VALUE); 1.4502 + sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); 1.4503 + sftk_DeleteAttributeType(privateKey,CKA_PRIME); 1.4504 + sftk_DeleteAttributeType(privateKey,CKA_SUBPRIME); 1.4505 + sftk_DeleteAttributeType(privateKey,CKA_BASE); 1.4506 + key_type = CKK_DSA; 1.4507 + 1.4508 + /* extract the necessary parameters and copy them to the private key */ 1.4509 + crv=sftk_Attribute2SSecItem(NULL,&pqgParam.prime,publicKey,CKA_PRIME); 1.4510 + if (crv != CKR_OK) break; 1.4511 + crv=sftk_Attribute2SSecItem(NULL,&pqgParam.subPrime,publicKey, 1.4512 + CKA_SUBPRIME); 1.4513 + if (crv != CKR_OK) { 1.4514 + PORT_Free(pqgParam.prime.data); 1.4515 + break; 1.4516 + } 1.4517 + crv=sftk_Attribute2SSecItem(NULL,&pqgParam.base,publicKey,CKA_BASE); 1.4518 + if (crv != CKR_OK) { 1.4519 + PORT_Free(pqgParam.prime.data); 1.4520 + PORT_Free(pqgParam.subPrime.data); 1.4521 + break; 1.4522 + } 1.4523 + crv = sftk_AddAttributeType(privateKey,CKA_PRIME, 1.4524 + sftk_item_expand(&pqgParam.prime)); 1.4525 + if (crv != CKR_OK) { 1.4526 + PORT_Free(pqgParam.prime.data); 1.4527 + PORT_Free(pqgParam.subPrime.data); 1.4528 + PORT_Free(pqgParam.base.data); 1.4529 + break; 1.4530 + } 1.4531 + crv = sftk_AddAttributeType(privateKey,CKA_SUBPRIME, 1.4532 + sftk_item_expand(&pqgParam.subPrime)); 1.4533 + if (crv != CKR_OK) { 1.4534 + PORT_Free(pqgParam.prime.data); 1.4535 + PORT_Free(pqgParam.subPrime.data); 1.4536 + PORT_Free(pqgParam.base.data); 1.4537 + break; 1.4538 + } 1.4539 + crv = sftk_AddAttributeType(privateKey,CKA_BASE, 1.4540 + sftk_item_expand(&pqgParam.base)); 1.4541 + if (crv != CKR_OK) { 1.4542 + PORT_Free(pqgParam.prime.data); 1.4543 + PORT_Free(pqgParam.subPrime.data); 1.4544 + PORT_Free(pqgParam.base.data); 1.4545 + break; 1.4546 + } 1.4547 + 1.4548 + /* 1.4549 + * these are checked by DSA_NewKey 1.4550 + */ 1.4551 + bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data, 1.4552 + pqgParam.subPrime.len); 1.4553 + if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) { 1.4554 + crv = CKR_TEMPLATE_INCOMPLETE; 1.4555 + PORT_Free(pqgParam.prime.data); 1.4556 + PORT_Free(pqgParam.subPrime.data); 1.4557 + PORT_Free(pqgParam.base.data); 1.4558 + break; 1.4559 + } 1.4560 + bitSize = sftk_GetLengthInBits(pqgParam.prime.data,pqgParam.prime.len); 1.4561 + if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) { 1.4562 + crv = CKR_TEMPLATE_INCOMPLETE; 1.4563 + PORT_Free(pqgParam.prime.data); 1.4564 + PORT_Free(pqgParam.subPrime.data); 1.4565 + PORT_Free(pqgParam.base.data); 1.4566 + break; 1.4567 + } 1.4568 + bitSize = sftk_GetLengthInBits(pqgParam.base.data,pqgParam.base.len); 1.4569 + if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) { 1.4570 + crv = CKR_TEMPLATE_INCOMPLETE; 1.4571 + PORT_Free(pqgParam.prime.data); 1.4572 + PORT_Free(pqgParam.subPrime.data); 1.4573 + PORT_Free(pqgParam.base.data); 1.4574 + break; 1.4575 + } 1.4576 + 1.4577 + /* Generate the key */ 1.4578 + rv = DSA_NewKey(&pqgParam, &dsaPriv); 1.4579 + 1.4580 + PORT_Free(pqgParam.prime.data); 1.4581 + PORT_Free(pqgParam.subPrime.data); 1.4582 + PORT_Free(pqgParam.base.data); 1.4583 + 1.4584 + if (rv != SECSuccess) { 1.4585 + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.4586 + sftk_fatalError = PR_TRUE; 1.4587 + } 1.4588 + crv = sftk_MapCryptError(PORT_GetError()); 1.4589 + break; 1.4590 + } 1.4591 + 1.4592 + /* store the generated key into the attributes */ 1.4593 + crv = sftk_AddAttributeType(publicKey,CKA_VALUE, 1.4594 + sftk_item_expand(&dsaPriv->publicValue)); 1.4595 + if (crv != CKR_OK) goto dsagn_done; 1.4596 + 1.4597 + /* now fill in the RSA dependent paramenters in the private key */ 1.4598 + crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, 1.4599 + sftk_item_expand(&dsaPriv->publicValue)); 1.4600 + if (crv != CKR_OK) goto dsagn_done; 1.4601 + crv = sftk_AddAttributeType(privateKey,CKA_VALUE, 1.4602 + sftk_item_expand(&dsaPriv->privateValue)); 1.4603 + 1.4604 +dsagn_done: 1.4605 + /* should zeroize, since this function doesn't. */ 1.4606 + PORT_FreeArena(dsaPriv->params.arena, PR_TRUE); 1.4607 + break; 1.4608 + 1.4609 + case CKM_DH_PKCS_KEY_PAIR_GEN: 1.4610 + sftk_DeleteAttributeType(privateKey,CKA_PRIME); 1.4611 + sftk_DeleteAttributeType(privateKey,CKA_BASE); 1.4612 + sftk_DeleteAttributeType(privateKey,CKA_VALUE); 1.4613 + sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); 1.4614 + key_type = CKK_DH; 1.4615 + 1.4616 + /* extract the necessary parameters and copy them to private keys */ 1.4617 + crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, 1.4618 + CKA_PRIME); 1.4619 + if (crv != CKR_OK) break; 1.4620 + crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE); 1.4621 + if (crv != CKR_OK) { 1.4622 + PORT_Free(dhParam.prime.data); 1.4623 + break; 1.4624 + } 1.4625 + crv = sftk_AddAttributeType(privateKey, CKA_PRIME, 1.4626 + sftk_item_expand(&dhParam.prime)); 1.4627 + if (crv != CKR_OK) { 1.4628 + PORT_Free(dhParam.prime.data); 1.4629 + PORT_Free(dhParam.base.data); 1.4630 + break; 1.4631 + } 1.4632 + crv = sftk_AddAttributeType(privateKey, CKA_BASE, 1.4633 + sftk_item_expand(&dhParam.base)); 1.4634 + if (crv != CKR_OK) { 1.4635 + PORT_Free(dhParam.prime.data); 1.4636 + PORT_Free(dhParam.base.data); 1.4637 + break; 1.4638 + } 1.4639 + bitSize = sftk_GetLengthInBits(dhParam.prime.data,dhParam.prime.len); 1.4640 + if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) { 1.4641 + crv = CKR_TEMPLATE_INCOMPLETE; 1.4642 + PORT_Free(dhParam.prime.data); 1.4643 + PORT_Free(dhParam.base.data); 1.4644 + break; 1.4645 + } 1.4646 + bitSize = sftk_GetLengthInBits(dhParam.base.data,dhParam.base.len); 1.4647 + if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) { 1.4648 + crv = CKR_TEMPLATE_INCOMPLETE; 1.4649 + PORT_Free(dhParam.prime.data); 1.4650 + PORT_Free(dhParam.base.data); 1.4651 + break; 1.4652 + } 1.4653 + 1.4654 + rv = DH_NewKey(&dhParam, &dhPriv); 1.4655 + PORT_Free(dhParam.prime.data); 1.4656 + PORT_Free(dhParam.base.data); 1.4657 + if (rv != SECSuccess) { 1.4658 + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.4659 + sftk_fatalError = PR_TRUE; 1.4660 + } 1.4661 + crv = sftk_MapCryptError(PORT_GetError()); 1.4662 + break; 1.4663 + } 1.4664 + 1.4665 + crv=sftk_AddAttributeType(publicKey, CKA_VALUE, 1.4666 + sftk_item_expand(&dhPriv->publicValue)); 1.4667 + if (crv != CKR_OK) goto dhgn_done; 1.4668 + 1.4669 + crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, 1.4670 + sftk_item_expand(&dhPriv->publicValue)); 1.4671 + if (crv != CKR_OK) goto dhgn_done; 1.4672 + 1.4673 + crv=sftk_AddAttributeType(privateKey, CKA_VALUE, 1.4674 + sftk_item_expand(&dhPriv->privateValue)); 1.4675 + 1.4676 +dhgn_done: 1.4677 + /* should zeroize, since this function doesn't. */ 1.4678 + PORT_FreeArena(dhPriv->arena, PR_TRUE); 1.4679 + break; 1.4680 + 1.4681 +#ifndef NSS_DISABLE_ECC 1.4682 + case CKM_EC_KEY_PAIR_GEN: 1.4683 + sftk_DeleteAttributeType(privateKey,CKA_EC_PARAMS); 1.4684 + sftk_DeleteAttributeType(privateKey,CKA_VALUE); 1.4685 + sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); 1.4686 + key_type = CKK_EC; 1.4687 + 1.4688 + /* extract the necessary parameters and copy them to private keys */ 1.4689 + crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, 1.4690 + CKA_EC_PARAMS); 1.4691 + if (crv != CKR_OK) break; 1.4692 + 1.4693 + crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, 1.4694 + sftk_item_expand(&ecEncodedParams)); 1.4695 + if (crv != CKR_OK) { 1.4696 + PORT_Free(ecEncodedParams.data); 1.4697 + break; 1.4698 + } 1.4699 + 1.4700 + /* Decode ec params before calling EC_NewKey */ 1.4701 + rv = EC_DecodeParams(&ecEncodedParams, &ecParams); 1.4702 + PORT_Free(ecEncodedParams.data); 1.4703 + if (rv != SECSuccess) { 1.4704 + crv = sftk_MapCryptError(PORT_GetError()); 1.4705 + break; 1.4706 + } 1.4707 + rv = EC_NewKey(ecParams, &ecPriv); 1.4708 + PORT_FreeArena(ecParams->arena, PR_TRUE); 1.4709 + if (rv != SECSuccess) { 1.4710 + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1.4711 + sftk_fatalError = PR_TRUE; 1.4712 + } 1.4713 + crv = sftk_MapCryptError(PORT_GetError()); 1.4714 + break; 1.4715 + } 1.4716 + 1.4717 + if (getenv("NSS_USE_DECODED_CKA_EC_POINT")) { 1.4718 + crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, 1.4719 + sftk_item_expand(&ecPriv->publicValue)); 1.4720 + } else { 1.4721 + SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, 1.4722 + &ecPriv->publicValue, 1.4723 + SEC_ASN1_GET(SEC_OctetStringTemplate)); 1.4724 + if (!pubValue) { 1.4725 + crv = CKR_ARGUMENTS_BAD; 1.4726 + goto ecgn_done; 1.4727 + } 1.4728 + crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, 1.4729 + sftk_item_expand(pubValue)); 1.4730 + SECITEM_FreeItem(pubValue, PR_TRUE); 1.4731 + } 1.4732 + if (crv != CKR_OK) goto ecgn_done; 1.4733 + 1.4734 + crv = sftk_AddAttributeType(privateKey, CKA_VALUE, 1.4735 + sftk_item_expand(&ecPriv->privateValue)); 1.4736 + if (crv != CKR_OK) goto ecgn_done; 1.4737 + 1.4738 + crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, 1.4739 + sftk_item_expand(&ecPriv->publicValue)); 1.4740 +ecgn_done: 1.4741 + /* should zeroize, since this function doesn't. */ 1.4742 + PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); 1.4743 + break; 1.4744 +#endif /* NSS_DISABLE_ECC */ 1.4745 + 1.4746 + default: 1.4747 + crv = CKR_MECHANISM_INVALID; 1.4748 + } 1.4749 + 1.4750 + if (crv != CKR_OK) { 1.4751 + sftk_FreeObject(privateKey); 1.4752 + sftk_FreeObject(publicKey); 1.4753 + return crv; 1.4754 + } 1.4755 + 1.4756 + 1.4757 + /* Add the class, key_type The loop lets us check errors blow out 1.4758 + * on errors and clean up at the bottom */ 1.4759 + session = NULL; /* make pedtantic happy... session cannot leave the*/ 1.4760 + /* loop below NULL unless an error is set... */ 1.4761 + do { 1.4762 + crv = sftk_AddAttributeType(privateKey,CKA_CLASS,&privClass, 1.4763 + sizeof(CK_OBJECT_CLASS)); 1.4764 + if (crv != CKR_OK) break; 1.4765 + crv = sftk_AddAttributeType(publicKey,CKA_CLASS,&pubClass, 1.4766 + sizeof(CK_OBJECT_CLASS)); 1.4767 + if (crv != CKR_OK) break; 1.4768 + crv = sftk_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type, 1.4769 + sizeof(CK_KEY_TYPE)); 1.4770 + if (crv != CKR_OK) break; 1.4771 + crv = sftk_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type, 1.4772 + sizeof(CK_KEY_TYPE)); 1.4773 + if (crv != CKR_OK) break; 1.4774 + session = sftk_SessionFromHandle(hSession); 1.4775 + if (session == NULL) crv = CKR_SESSION_HANDLE_INVALID; 1.4776 + } while (0); 1.4777 + 1.4778 + if (crv != CKR_OK) { 1.4779 + sftk_FreeObject(privateKey); 1.4780 + sftk_FreeObject(publicKey); 1.4781 + return crv; 1.4782 + } 1.4783 + 1.4784 + /* 1.4785 + * handle the base object cleanup for the public Key 1.4786 + */ 1.4787 + crv = sftk_handleObject(privateKey,session); 1.4788 + if (crv != CKR_OK) { 1.4789 + sftk_FreeSession(session); 1.4790 + sftk_FreeObject(privateKey); 1.4791 + sftk_FreeObject(publicKey); 1.4792 + return crv; 1.4793 + } 1.4794 + 1.4795 + /* 1.4796 + * handle the base object cleanup for the private Key 1.4797 + * If we have any problems, we destroy the public Key we've 1.4798 + * created and linked. 1.4799 + */ 1.4800 + crv = sftk_handleObject(publicKey,session); 1.4801 + sftk_FreeSession(session); 1.4802 + if (crv != CKR_OK) { 1.4803 + sftk_FreeObject(publicKey); 1.4804 + NSC_DestroyObject(hSession,privateKey->handle); 1.4805 + sftk_FreeObject(privateKey); 1.4806 + return crv; 1.4807 + } 1.4808 + if (sftk_isTrue(privateKey,CKA_SENSITIVE)) { 1.4809 + sftk_forceAttribute(privateKey,CKA_ALWAYS_SENSITIVE, 1.4810 + &cktrue,sizeof(CK_BBOOL)); 1.4811 + } 1.4812 + if (sftk_isTrue(publicKey,CKA_SENSITIVE)) { 1.4813 + sftk_forceAttribute(publicKey,CKA_ALWAYS_SENSITIVE, 1.4814 + &cktrue,sizeof(CK_BBOOL)); 1.4815 + } 1.4816 + if (!sftk_isTrue(privateKey,CKA_EXTRACTABLE)) { 1.4817 + sftk_forceAttribute(privateKey,CKA_NEVER_EXTRACTABLE, 1.4818 + &cktrue,sizeof(CK_BBOOL)); 1.4819 + } 1.4820 + if (!sftk_isTrue(publicKey,CKA_EXTRACTABLE)) { 1.4821 + sftk_forceAttribute(publicKey,CKA_NEVER_EXTRACTABLE, 1.4822 + &cktrue,sizeof(CK_BBOOL)); 1.4823 + } 1.4824 + 1.4825 + /* Perform FIPS 140-2 pairwise consistency check. */ 1.4826 + crv = sftk_PairwiseConsistencyCheck(hSession, 1.4827 + publicKey, privateKey, key_type); 1.4828 + if (crv != CKR_OK) { 1.4829 + NSC_DestroyObject(hSession,publicKey->handle); 1.4830 + sftk_FreeObject(publicKey); 1.4831 + NSC_DestroyObject(hSession,privateKey->handle); 1.4832 + sftk_FreeObject(privateKey); 1.4833 + if (sftk_audit_enabled) { 1.4834 + char msg[128]; 1.4835 + PR_snprintf(msg,sizeof msg, 1.4836 + "C_GenerateKeyPair(hSession=0x%08lX, " 1.4837 + "pMechanism->mechanism=0x%08lX)=0x%08lX " 1.4838 + "self-test: pair-wise consistency test failed", 1.4839 + (PRUint32)hSession,(PRUint32)pMechanism->mechanism, 1.4840 + (PRUint32)crv); 1.4841 + sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg); 1.4842 + } 1.4843 + return crv; 1.4844 + } 1.4845 + 1.4846 + *phPrivateKey = privateKey->handle; 1.4847 + *phPublicKey = publicKey->handle; 1.4848 + sftk_FreeObject(publicKey); 1.4849 + sftk_FreeObject(privateKey); 1.4850 + 1.4851 + return CKR_OK; 1.4852 +} 1.4853 + 1.4854 +static SECItem *sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) 1.4855 +{ 1.4856 + NSSLOWKEYPrivateKey *lk = NULL; 1.4857 + NSSLOWKEYPrivateKeyInfo *pki = NULL; 1.4858 + SFTKAttribute *attribute = NULL; 1.4859 + PLArenaPool *arena = NULL; 1.4860 + SECOidTag algorithm = SEC_OID_UNKNOWN; 1.4861 + void *dummy, *param = NULL; 1.4862 + SECStatus rv = SECSuccess; 1.4863 + SECItem *encodedKey = NULL; 1.4864 +#ifndef NSS_DISABLE_ECC 1.4865 + SECItem *fordebug; 1.4866 + int savelen; 1.4867 +#endif 1.4868 + 1.4869 + if(!key) { 1.4870 + *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */ 1.4871 + return NULL; 1.4872 + } 1.4873 + 1.4874 + attribute = sftk_FindAttribute(key, CKA_KEY_TYPE); 1.4875 + if(!attribute) { 1.4876 + *crvp = CKR_KEY_TYPE_INCONSISTENT; 1.4877 + return NULL; 1.4878 + } 1.4879 + 1.4880 + lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp); 1.4881 + sftk_FreeAttribute(attribute); 1.4882 + if(!lk) { 1.4883 + return NULL; 1.4884 + } 1.4885 + 1.4886 + arena = PORT_NewArena(2048); /* XXX different size? */ 1.4887 + if(!arena) { 1.4888 + *crvp = CKR_HOST_MEMORY; 1.4889 + rv = SECFailure; 1.4890 + goto loser; 1.4891 + } 1.4892 + 1.4893 + pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, 1.4894 + sizeof(NSSLOWKEYPrivateKeyInfo)); 1.4895 + if(!pki) { 1.4896 + *crvp = CKR_HOST_MEMORY; 1.4897 + rv = SECFailure; 1.4898 + goto loser; 1.4899 + } 1.4900 + pki->arena = arena; 1.4901 + 1.4902 + param = NULL; 1.4903 + switch(lk->keyType) { 1.4904 + case NSSLOWKEYRSAKey: 1.4905 + prepare_low_rsa_priv_key_for_asn1(lk); 1.4906 + dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, 1.4907 + nsslowkey_RSAPrivateKeyTemplate); 1.4908 + algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; 1.4909 + break; 1.4910 + case NSSLOWKEYDSAKey: 1.4911 + prepare_low_dsa_priv_key_export_for_asn1(lk); 1.4912 + dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, 1.4913 + nsslowkey_DSAPrivateKeyExportTemplate); 1.4914 + prepare_low_pqg_params_for_asn1(&lk->u.dsa.params); 1.4915 + param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params), 1.4916 + nsslowkey_PQGParamsTemplate); 1.4917 + algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; 1.4918 + break; 1.4919 +#ifndef NSS_DISABLE_ECC 1.4920 + case NSSLOWKEYECKey: 1.4921 + prepare_low_ec_priv_key_for_asn1(lk); 1.4922 + /* Public value is encoded as a bit string so adjust length 1.4923 + * to be in bits before ASN encoding and readjust 1.4924 + * immediately after. 1.4925 + * 1.4926 + * Since the SECG specification recommends not including the 1.4927 + * parameters as part of ECPrivateKey, we zero out the curveOID 1.4928 + * length before encoding and restore it later. 1.4929 + */ 1.4930 + lk->u.ec.publicValue.len <<= 3; 1.4931 + savelen = lk->u.ec.ecParams.curveOID.len; 1.4932 + lk->u.ec.ecParams.curveOID.len = 0; 1.4933 + dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, 1.4934 + nsslowkey_ECPrivateKeyTemplate); 1.4935 + lk->u.ec.ecParams.curveOID.len = savelen; 1.4936 + lk->u.ec.publicValue.len >>= 3; 1.4937 + 1.4938 + fordebug = &pki->privateKey; 1.4939 + SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType, 1.4940 + fordebug); 1.4941 + 1.4942 + param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding); 1.4943 + 1.4944 + algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY; 1.4945 + break; 1.4946 +#endif /* NSS_DISABLE_ECC */ 1.4947 + case NSSLOWKEYDHKey: 1.4948 + default: 1.4949 + dummy = NULL; 1.4950 + break; 1.4951 + } 1.4952 + 1.4953 + if(!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) { 1.4954 + *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ 1.4955 + rv = SECFailure; 1.4956 + goto loser; 1.4957 + } 1.4958 + 1.4959 + rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, 1.4960 + (SECItem*)param); 1.4961 + if(rv != SECSuccess) { 1.4962 + *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ 1.4963 + rv = SECFailure; 1.4964 + goto loser; 1.4965 + } 1.4966 + 1.4967 + dummy = SEC_ASN1EncodeInteger(arena, &pki->version, 1.4968 + NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); 1.4969 + if(!dummy) { 1.4970 + *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ 1.4971 + rv = SECFailure; 1.4972 + goto loser; 1.4973 + } 1.4974 + 1.4975 + encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, 1.4976 + nsslowkey_PrivateKeyInfoTemplate); 1.4977 + *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR; 1.4978 + 1.4979 +#ifndef NSS_DISABLE_ECC 1.4980 + fordebug = encodedKey; 1.4981 + SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType, 1.4982 + fordebug); 1.4983 +#endif 1.4984 +loser: 1.4985 + if(arena) { 1.4986 + PORT_FreeArena(arena, PR_TRUE); 1.4987 + } 1.4988 + 1.4989 + if(lk && (lk != key->objectInfo)) { 1.4990 + nsslowkey_DestroyPrivateKey(lk); 1.4991 + } 1.4992 + 1.4993 + if(param) { 1.4994 + SECITEM_ZfreeItem((SECItem*)param, PR_TRUE); 1.4995 + } 1.4996 + 1.4997 + if(rv != SECSuccess) { 1.4998 + return NULL; 1.4999 + } 1.5000 + 1.5001 + return encodedKey; 1.5002 +} 1.5003 + 1.5004 +/* it doesn't matter yet, since we colapse error conditions in the 1.5005 + * level above, but we really should map those few key error differences */ 1.5006 +static CK_RV 1.5007 +sftk_mapWrap(CK_RV crv) 1.5008 +{ 1.5009 + switch (crv) { 1.5010 + case CKR_ENCRYPTED_DATA_INVALID: crv = CKR_WRAPPED_KEY_INVALID; break; 1.5011 + } 1.5012 + return crv; 1.5013 +} 1.5014 + 1.5015 +/* NSC_WrapKey wraps (i.e., encrypts) a key. */ 1.5016 +CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, 1.5017 + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, 1.5018 + CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, 1.5019 + CK_ULONG_PTR pulWrappedKeyLen) 1.5020 +{ 1.5021 + SFTKSession *session; 1.5022 + SFTKAttribute *attribute; 1.5023 + SFTKObject *key; 1.5024 + CK_RV crv; 1.5025 + 1.5026 + CHECK_FORK(); 1.5027 + 1.5028 + session = sftk_SessionFromHandle(hSession); 1.5029 + if (session == NULL) { 1.5030 + return CKR_SESSION_HANDLE_INVALID; 1.5031 + } 1.5032 + 1.5033 + key = sftk_ObjectFromHandle(hKey,session); 1.5034 + sftk_FreeSession(session); 1.5035 + if (key == NULL) { 1.5036 + return CKR_KEY_HANDLE_INVALID; 1.5037 + } 1.5038 + 1.5039 + switch(key->objclass) { 1.5040 + case CKO_SECRET_KEY: 1.5041 + { 1.5042 + SFTKSessionContext *context = NULL; 1.5043 + SECItem pText; 1.5044 + 1.5045 + attribute = sftk_FindAttribute(key,CKA_VALUE); 1.5046 + 1.5047 + if (attribute == NULL) { 1.5048 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.5049 + break; 1.5050 + } 1.5051 + crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, 1.5052 + CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); 1.5053 + if (crv != CKR_OK) { 1.5054 + sftk_FreeAttribute(attribute); 1.5055 + break; 1.5056 + } 1.5057 + 1.5058 + pText.type = siBuffer; 1.5059 + pText.data = (unsigned char *)attribute->attrib.pValue; 1.5060 + pText.len = attribute->attrib.ulValueLen; 1.5061 + 1.5062 + /* Find out if this is a block cipher. */ 1.5063 + crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,NULL); 1.5064 + if (crv != CKR_OK || !context) 1.5065 + break; 1.5066 + if (context->blockSize > 1) { 1.5067 + unsigned int remainder = pText.len % context->blockSize; 1.5068 + if (!context->doPad && remainder) { 1.5069 + /* When wrapping secret keys with unpadded block ciphers, 1.5070 + ** the keys are zero padded, if necessary, to fill out 1.5071 + ** a full block. 1.5072 + */ 1.5073 + pText.len += context->blockSize - remainder; 1.5074 + pText.data = PORT_ZAlloc(pText.len); 1.5075 + if (pText.data) 1.5076 + memcpy(pText.data, attribute->attrib.pValue, 1.5077 + attribute->attrib.ulValueLen); 1.5078 + else { 1.5079 + crv = CKR_HOST_MEMORY; 1.5080 + break; 1.5081 + } 1.5082 + } 1.5083 + } 1.5084 + 1.5085 + crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data, 1.5086 + pText.len, pWrappedKey, pulWrappedKeyLen); 1.5087 + /* always force a finalize, both on errors and when 1.5088 + * we are just getting the size */ 1.5089 + if (crv != CKR_OK || pWrappedKey == NULL) { 1.5090 + CK_RV lcrv ; 1.5091 + lcrv = sftk_GetContext(hSession,&context, 1.5092 + SFTK_ENCRYPT,PR_FALSE,NULL); 1.5093 + sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); 1.5094 + if (lcrv == CKR_OK && context) { 1.5095 + sftk_FreeContext(context); 1.5096 + } 1.5097 + } 1.5098 + 1.5099 + if (pText.data != (unsigned char *)attribute->attrib.pValue) 1.5100 + PORT_ZFree(pText.data, pText.len); 1.5101 + sftk_FreeAttribute(attribute); 1.5102 + break; 1.5103 + } 1.5104 + 1.5105 + case CKO_PRIVATE_KEY: 1.5106 + { 1.5107 + SECItem *bpki = sftk_PackagePrivateKey(key, &crv); 1.5108 + SFTKSessionContext *context = NULL; 1.5109 + 1.5110 + if(!bpki) { 1.5111 + break; 1.5112 + } 1.5113 + 1.5114 + crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, 1.5115 + CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); 1.5116 + if(crv != CKR_OK) { 1.5117 + SECITEM_ZfreeItem(bpki, PR_TRUE); 1.5118 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.5119 + break; 1.5120 + } 1.5121 + 1.5122 + crv = NSC_Encrypt(hSession, bpki->data, bpki->len, 1.5123 + pWrappedKey, pulWrappedKeyLen); 1.5124 + /* always force a finalize */ 1.5125 + if (crv != CKR_OK || pWrappedKey == NULL) { 1.5126 + CK_RV lcrv ; 1.5127 + lcrv = sftk_GetContext(hSession,&context, 1.5128 + SFTK_ENCRYPT,PR_FALSE,NULL); 1.5129 + sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); 1.5130 + if (lcrv == CKR_OK && context) { 1.5131 + sftk_FreeContext(context); 1.5132 + } 1.5133 + } 1.5134 + SECITEM_ZfreeItem(bpki, PR_TRUE); 1.5135 + break; 1.5136 + } 1.5137 + 1.5138 + default: 1.5139 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.5140 + break; 1.5141 + } 1.5142 + sftk_FreeObject(key); 1.5143 + 1.5144 + return sftk_mapWrap(crv); 1.5145 +} 1.5146 + 1.5147 +/* 1.5148 + * import a pprivate key info into the desired slot 1.5149 + */ 1.5150 +static SECStatus 1.5151 +sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) 1.5152 +{ 1.5153 + CK_BBOOL cktrue = CK_TRUE; 1.5154 + CK_KEY_TYPE keyType = CKK_RSA; 1.5155 + SECStatus rv = SECFailure; 1.5156 + const SEC_ASN1Template *keyTemplate, *paramTemplate; 1.5157 + void *paramDest = NULL; 1.5158 + PLArenaPool *arena; 1.5159 + NSSLOWKEYPrivateKey *lpk = NULL; 1.5160 + NSSLOWKEYPrivateKeyInfo *pki = NULL; 1.5161 + CK_RV crv = CKR_KEY_TYPE_INCONSISTENT; 1.5162 + 1.5163 + arena = PORT_NewArena(2048); 1.5164 + if(!arena) { 1.5165 + return SECFailure; 1.5166 + } 1.5167 + 1.5168 + pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, 1.5169 + sizeof(NSSLOWKEYPrivateKeyInfo)); 1.5170 + if(!pki) { 1.5171 + PORT_FreeArena(arena, PR_FALSE); 1.5172 + return SECFailure; 1.5173 + } 1.5174 + 1.5175 + if(SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) 1.5176 + != SECSuccess) { 1.5177 + PORT_FreeArena(arena, PR_TRUE); 1.5178 + return SECFailure; 1.5179 + } 1.5180 + 1.5181 + lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena, 1.5182 + sizeof(NSSLOWKEYPrivateKey)); 1.5183 + if(lpk == NULL) { 1.5184 + goto loser; 1.5185 + } 1.5186 + lpk->arena = arena; 1.5187 + 1.5188 + switch(SECOID_GetAlgorithmTag(&pki->algorithm)) { 1.5189 + case SEC_OID_PKCS1_RSA_ENCRYPTION: 1.5190 + keyTemplate = nsslowkey_RSAPrivateKeyTemplate; 1.5191 + paramTemplate = NULL; 1.5192 + paramDest = NULL; 1.5193 + lpk->keyType = NSSLOWKEYRSAKey; 1.5194 + prepare_low_rsa_priv_key_for_asn1(lpk); 1.5195 + break; 1.5196 + case SEC_OID_ANSIX9_DSA_SIGNATURE: 1.5197 + keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate; 1.5198 + paramTemplate = nsslowkey_PQGParamsTemplate; 1.5199 + paramDest = &(lpk->u.dsa.params); 1.5200 + lpk->keyType = NSSLOWKEYDSAKey; 1.5201 + prepare_low_dsa_priv_key_export_for_asn1(lpk); 1.5202 + prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params); 1.5203 + break; 1.5204 + /* case NSSLOWKEYDHKey: */ 1.5205 +#ifndef NSS_DISABLE_ECC 1.5206 + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: 1.5207 + keyTemplate = nsslowkey_ECPrivateKeyTemplate; 1.5208 + paramTemplate = NULL; 1.5209 + paramDest = &(lpk->u.ec.ecParams.DEREncoding); 1.5210 + lpk->keyType = NSSLOWKEYECKey; 1.5211 + prepare_low_ec_priv_key_for_asn1(lpk); 1.5212 + prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams); 1.5213 + break; 1.5214 +#endif /* NSS_DISABLE_ECC */ 1.5215 + default: 1.5216 + keyTemplate = NULL; 1.5217 + paramTemplate = NULL; 1.5218 + paramDest = NULL; 1.5219 + break; 1.5220 + } 1.5221 + 1.5222 + if(!keyTemplate) { 1.5223 + goto loser; 1.5224 + } 1.5225 + 1.5226 + /* decode the private key and any algorithm parameters */ 1.5227 + rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey); 1.5228 + 1.5229 +#ifndef NSS_DISABLE_ECC 1.5230 + if (lpk->keyType == NSSLOWKEYECKey) { 1.5231 + /* convert length in bits to length in bytes */ 1.5232 + lpk->u.ec.publicValue.len >>= 3; 1.5233 + rv = SECITEM_CopyItem(arena, 1.5234 + &(lpk->u.ec.ecParams.DEREncoding), 1.5235 + &(pki->algorithm.parameters)); 1.5236 + if(rv != SECSuccess) { 1.5237 + goto loser; 1.5238 + } 1.5239 + } 1.5240 +#endif /* NSS_DISABLE_ECC */ 1.5241 + 1.5242 + if(rv != SECSuccess) { 1.5243 + goto loser; 1.5244 + } 1.5245 + if(paramDest && paramTemplate) { 1.5246 + rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate, 1.5247 + &(pki->algorithm.parameters)); 1.5248 + if(rv != SECSuccess) { 1.5249 + goto loser; 1.5250 + } 1.5251 + } 1.5252 + 1.5253 + rv = SECFailure; 1.5254 + 1.5255 + switch (lpk->keyType) { 1.5256 + case NSSLOWKEYRSAKey: 1.5257 + keyType = CKK_RSA; 1.5258 + if(sftk_hasAttribute(key, CKA_NETSCAPE_DB)) { 1.5259 + sftk_DeleteAttributeType(key, CKA_NETSCAPE_DB); 1.5260 + } 1.5261 + crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, 1.5262 + sizeof(keyType)); 1.5263 + if(crv != CKR_OK) break; 1.5264 + crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue, 1.5265 + sizeof(CK_BBOOL)); 1.5266 + if(crv != CKR_OK) break; 1.5267 + crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue, 1.5268 + sizeof(CK_BBOOL)); 1.5269 + if(crv != CKR_OK) break; 1.5270 + crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, 1.5271 + sizeof(CK_BBOOL)); 1.5272 + if(crv != CKR_OK) break; 1.5273 + crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, 1.5274 + sizeof(CK_BBOOL)); 1.5275 + if(crv != CKR_OK) break; 1.5276 + crv = sftk_AddAttributeType(key, CKA_MODULUS, 1.5277 + sftk_item_expand(&lpk->u.rsa.modulus)); 1.5278 + if(crv != CKR_OK) break; 1.5279 + crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT, 1.5280 + sftk_item_expand(&lpk->u.rsa.publicExponent)); 1.5281 + if(crv != CKR_OK) break; 1.5282 + crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT, 1.5283 + sftk_item_expand(&lpk->u.rsa.privateExponent)); 1.5284 + if(crv != CKR_OK) break; 1.5285 + crv = sftk_AddAttributeType(key, CKA_PRIME_1, 1.5286 + sftk_item_expand(&lpk->u.rsa.prime1)); 1.5287 + if(crv != CKR_OK) break; 1.5288 + crv = sftk_AddAttributeType(key, CKA_PRIME_2, 1.5289 + sftk_item_expand(&lpk->u.rsa.prime2)); 1.5290 + if(crv != CKR_OK) break; 1.5291 + crv = sftk_AddAttributeType(key, CKA_EXPONENT_1, 1.5292 + sftk_item_expand(&lpk->u.rsa.exponent1)); 1.5293 + if(crv != CKR_OK) break; 1.5294 + crv = sftk_AddAttributeType(key, CKA_EXPONENT_2, 1.5295 + sftk_item_expand(&lpk->u.rsa.exponent2)); 1.5296 + if(crv != CKR_OK) break; 1.5297 + crv = sftk_AddAttributeType(key, CKA_COEFFICIENT, 1.5298 + sftk_item_expand(&lpk->u.rsa.coefficient)); 1.5299 + break; 1.5300 + case NSSLOWKEYDSAKey: 1.5301 + keyType = CKK_DSA; 1.5302 + crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : 1.5303 + CKR_KEY_TYPE_INCONSISTENT; 1.5304 + if(crv != CKR_OK) break; 1.5305 + crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, 1.5306 + sizeof(keyType)); 1.5307 + if(crv != CKR_OK) break; 1.5308 + crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, 1.5309 + sizeof(CK_BBOOL)); 1.5310 + if(crv != CKR_OK) break; 1.5311 + crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, 1.5312 + sizeof(CK_BBOOL)); 1.5313 + if(crv != CKR_OK) break; 1.5314 + crv = sftk_AddAttributeType(key, CKA_PRIME, 1.5315 + sftk_item_expand(&lpk->u.dsa.params.prime)); 1.5316 + if(crv != CKR_OK) break; 1.5317 + crv = sftk_AddAttributeType(key, CKA_SUBPRIME, 1.5318 + sftk_item_expand(&lpk->u.dsa.params.subPrime)); 1.5319 + if(crv != CKR_OK) break; 1.5320 + crv = sftk_AddAttributeType(key, CKA_BASE, 1.5321 + sftk_item_expand(&lpk->u.dsa.params.base)); 1.5322 + if(crv != CKR_OK) break; 1.5323 + crv = sftk_AddAttributeType(key, CKA_VALUE, 1.5324 + sftk_item_expand(&lpk->u.dsa.privateValue)); 1.5325 + if(crv != CKR_OK) break; 1.5326 + break; 1.5327 +#ifdef notdef 1.5328 + case NSSLOWKEYDHKey: 1.5329 + template = dhTemplate; 1.5330 + templateCount = sizeof(dhTemplate)/sizeof(CK_ATTRIBUTE); 1.5331 + keyType = CKK_DH; 1.5332 + break; 1.5333 +#endif 1.5334 + /* what about fortezza??? */ 1.5335 +#ifndef NSS_DISABLE_ECC 1.5336 + case NSSLOWKEYECKey: 1.5337 + keyType = CKK_EC; 1.5338 + crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : 1.5339 + CKR_KEY_TYPE_INCONSISTENT; 1.5340 + if(crv != CKR_OK) break; 1.5341 + crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, 1.5342 + sizeof(keyType)); 1.5343 + if(crv != CKR_OK) break; 1.5344 + crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, 1.5345 + sizeof(CK_BBOOL)); 1.5346 + if(crv != CKR_OK) break; 1.5347 + crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, 1.5348 + sizeof(CK_BBOOL)); 1.5349 + if(crv != CKR_OK) break; 1.5350 + crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue, 1.5351 + sizeof(CK_BBOOL)); 1.5352 + if(crv != CKR_OK) break; 1.5353 + crv = sftk_AddAttributeType(key, CKA_EC_PARAMS, 1.5354 + sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding)); 1.5355 + if(crv != CKR_OK) break; 1.5356 + crv = sftk_AddAttributeType(key, CKA_VALUE, 1.5357 + sftk_item_expand(&lpk->u.ec.privateValue)); 1.5358 + if(crv != CKR_OK) break; 1.5359 + /* XXX Do we need to decode the EC Params here ?? */ 1.5360 + break; 1.5361 +#endif /* NSS_DISABLE_ECC */ 1.5362 + default: 1.5363 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.5364 + break; 1.5365 + } 1.5366 + 1.5367 +loser: 1.5368 + if(lpk) { 1.5369 + nsslowkey_DestroyPrivateKey(lpk); 1.5370 + } 1.5371 + 1.5372 + if(crv != CKR_OK) { 1.5373 + return SECFailure; 1.5374 + } 1.5375 + 1.5376 + return SECSuccess; 1.5377 +} 1.5378 + 1.5379 + 1.5380 +/* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */ 1.5381 +CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession, 1.5382 + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, 1.5383 + CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, 1.5384 + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, 1.5385 + CK_OBJECT_HANDLE_PTR phKey) 1.5386 +{ 1.5387 + SFTKObject *key = NULL; 1.5388 + SFTKSession *session; 1.5389 + CK_ULONG key_length = 0; 1.5390 + unsigned char * buf = NULL; 1.5391 + CK_RV crv = CKR_OK; 1.5392 + int i; 1.5393 + CK_ULONG bsize = ulWrappedKeyLen; 1.5394 + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 1.5395 + SECItem bpki; 1.5396 + CK_OBJECT_CLASS target_type = CKO_SECRET_KEY; 1.5397 + 1.5398 + CHECK_FORK(); 1.5399 + 1.5400 + if (!slot) { 1.5401 + return CKR_SESSION_HANDLE_INVALID; 1.5402 + } 1.5403 + /* 1.5404 + * now lets create an object to hang the attributes off of 1.5405 + */ 1.5406 + key = sftk_NewObject(slot); /* fill in the handle later */ 1.5407 + if (key == NULL) { 1.5408 + return CKR_HOST_MEMORY; 1.5409 + } 1.5410 + 1.5411 + /* 1.5412 + * load the template values into the object 1.5413 + */ 1.5414 + for (i=0; i < (int) ulAttributeCount; i++) { 1.5415 + if (pTemplate[i].type == CKA_VALUE_LEN) { 1.5416 + key_length = *(CK_ULONG *)pTemplate[i].pValue; 1.5417 + continue; 1.5418 + } 1.5419 + if (pTemplate[i].type == CKA_CLASS) { 1.5420 + target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; 1.5421 + } 1.5422 + crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i])); 1.5423 + if (crv != CKR_OK) break; 1.5424 + } 1.5425 + if (crv != CKR_OK) { 1.5426 + sftk_FreeObject(key); 1.5427 + return crv; 1.5428 + } 1.5429 + 1.5430 + crv = sftk_CryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP, 1.5431 + CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE); 1.5432 + if (crv != CKR_OK) { 1.5433 + sftk_FreeObject(key); 1.5434 + return sftk_mapWrap(crv); 1.5435 + } 1.5436 + 1.5437 + /* allocate the buffer to decrypt into 1.5438 + * this assumes the unwrapped key is never larger than the 1.5439 + * wrapped key. For all the mechanisms we support this is true */ 1.5440 + buf = (unsigned char *)PORT_Alloc( ulWrappedKeyLen); 1.5441 + bsize = ulWrappedKeyLen; 1.5442 + 1.5443 + crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize); 1.5444 + if (crv != CKR_OK) { 1.5445 + sftk_FreeObject(key); 1.5446 + PORT_Free(buf); 1.5447 + return sftk_mapWrap(crv); 1.5448 + } 1.5449 + 1.5450 + switch(target_type) { 1.5451 + case CKO_SECRET_KEY: 1.5452 + if (!sftk_hasAttribute(key,CKA_KEY_TYPE)) { 1.5453 + crv = CKR_TEMPLATE_INCOMPLETE; 1.5454 + break; 1.5455 + } 1.5456 + 1.5457 + if (key_length == 0 || key_length > bsize) { 1.5458 + key_length = bsize; 1.5459 + } 1.5460 + if (key_length > MAX_KEY_LEN) { 1.5461 + crv = CKR_TEMPLATE_INCONSISTENT; 1.5462 + break; 1.5463 + } 1.5464 + 1.5465 + /* add the value */ 1.5466 + crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length); 1.5467 + break; 1.5468 + case CKO_PRIVATE_KEY: 1.5469 + bpki.data = (unsigned char *)buf; 1.5470 + bpki.len = bsize; 1.5471 + crv = CKR_OK; 1.5472 + if(sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) { 1.5473 + crv = CKR_TEMPLATE_INCOMPLETE; 1.5474 + } 1.5475 + break; 1.5476 + default: 1.5477 + crv = CKR_TEMPLATE_INCONSISTENT; 1.5478 + break; 1.5479 + } 1.5480 + 1.5481 + PORT_ZFree(buf, bsize); 1.5482 + if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } 1.5483 + 1.5484 + /* get the session */ 1.5485 + session = sftk_SessionFromHandle(hSession); 1.5486 + if (session == NULL) { 1.5487 + sftk_FreeObject(key); 1.5488 + return CKR_SESSION_HANDLE_INVALID; 1.5489 + } 1.5490 + 1.5491 + /* 1.5492 + * handle the base object stuff 1.5493 + */ 1.5494 + crv = sftk_handleObject(key,session); 1.5495 + *phKey = key->handle; 1.5496 + sftk_FreeSession(session); 1.5497 + sftk_FreeObject(key); 1.5498 + 1.5499 + return crv; 1.5500 + 1.5501 +} 1.5502 + 1.5503 +/* 1.5504 + * The SSL key gen mechanism create's lots of keys. This function handles the 1.5505 + * details of each of these key creation. 1.5506 + */ 1.5507 +static CK_RV 1.5508 +sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey, 1.5509 + PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize, 1.5510 + CK_OBJECT_HANDLE *keyHandle) 1.5511 +{ 1.5512 + SFTKObject *key; 1.5513 + SFTKSession *session; 1.5514 + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 1.5515 + CK_BBOOL cktrue = CK_TRUE; 1.5516 + CK_BBOOL ckfalse = CK_FALSE; 1.5517 + CK_RV crv = CKR_HOST_MEMORY; 1.5518 + 1.5519 + /* 1.5520 + * now lets create an object to hang the attributes off of 1.5521 + */ 1.5522 + *keyHandle = CK_INVALID_HANDLE; 1.5523 + key = sftk_NewObject(baseKey->slot); 1.5524 + if (key == NULL) return CKR_HOST_MEMORY; 1.5525 + sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE; 1.5526 + 1.5527 + crv = sftk_CopyObject(key,baseKey); 1.5528 + if (crv != CKR_OK) goto loser; 1.5529 + if (isMacKey) { 1.5530 + crv = sftk_forceAttribute(key,CKA_KEY_TYPE,&keyType,sizeof(keyType)); 1.5531 + if (crv != CKR_OK) goto loser; 1.5532 + crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL)); 1.5533 + if (crv != CKR_OK) goto loser; 1.5534 + crv = sftk_forceAttribute(key,CKA_ENCRYPT,&ckfalse,sizeof(CK_BBOOL)); 1.5535 + if (crv != CKR_OK) goto loser; 1.5536 + crv = sftk_forceAttribute(key,CKA_DECRYPT,&ckfalse,sizeof(CK_BBOOL)); 1.5537 + if (crv != CKR_OK) goto loser; 1.5538 + crv = sftk_forceAttribute(key,CKA_SIGN,&cktrue,sizeof(CK_BBOOL)); 1.5539 + if (crv != CKR_OK) goto loser; 1.5540 + crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL)); 1.5541 + if (crv != CKR_OK) goto loser; 1.5542 + crv = sftk_forceAttribute(key,CKA_WRAP,&ckfalse,sizeof(CK_BBOOL)); 1.5543 + if (crv != CKR_OK) goto loser; 1.5544 + crv = sftk_forceAttribute(key,CKA_UNWRAP,&ckfalse,sizeof(CK_BBOOL)); 1.5545 + if (crv != CKR_OK) goto loser; 1.5546 + } 1.5547 + crv = sftk_forceAttribute(key,CKA_VALUE,keyBlock,keySize); 1.5548 + if (crv != CKR_OK) goto loser; 1.5549 + 1.5550 + /* get the session */ 1.5551 + crv = CKR_HOST_MEMORY; 1.5552 + session = sftk_SessionFromHandle(hSession); 1.5553 + if (session == NULL) { goto loser; } 1.5554 + 1.5555 + crv = sftk_handleObject(key,session); 1.5556 + sftk_FreeSession(session); 1.5557 + *keyHandle = key->handle; 1.5558 +loser: 1.5559 + if (key) sftk_FreeObject(key); 1.5560 + return crv; 1.5561 +} 1.5562 + 1.5563 +/* 1.5564 + * if there is an error, we need to free the keys we already created in SSL 1.5565 + * This is the routine that will do it.. 1.5566 + */ 1.5567 +static void 1.5568 +sftk_freeSSLKeys(CK_SESSION_HANDLE session, 1.5569 + CK_SSL3_KEY_MAT_OUT *returnedMaterial ) 1.5570 +{ 1.5571 + if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) { 1.5572 + NSC_DestroyObject(session,returnedMaterial->hClientMacSecret); 1.5573 + } 1.5574 + if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) { 1.5575 + NSC_DestroyObject(session, returnedMaterial->hServerMacSecret); 1.5576 + } 1.5577 + if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) { 1.5578 + NSC_DestroyObject(session, returnedMaterial->hClientKey); 1.5579 + } 1.5580 + if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) { 1.5581 + NSC_DestroyObject(session, returnedMaterial->hServerKey); 1.5582 + } 1.5583 +} 1.5584 + 1.5585 +/* 1.5586 + * when deriving from sensitive and extractable keys, we need to preserve some 1.5587 + * of the semantics in the derived key. This helper routine maintains these 1.5588 + * semantics. 1.5589 + */ 1.5590 +static CK_RV 1.5591 +sftk_DeriveSensitiveCheck(SFTKObject *baseKey,SFTKObject *destKey) 1.5592 +{ 1.5593 + PRBool hasSensitive; 1.5594 + PRBool sensitive = PR_FALSE; 1.5595 + PRBool hasExtractable; 1.5596 + PRBool extractable = PR_TRUE; 1.5597 + CK_RV crv = CKR_OK; 1.5598 + SFTKAttribute *att; 1.5599 + 1.5600 + hasSensitive = PR_FALSE; 1.5601 + att = sftk_FindAttribute(destKey,CKA_SENSITIVE); 1.5602 + if (att) { 1.5603 + hasSensitive = PR_TRUE; 1.5604 + sensitive = (PRBool) *(CK_BBOOL *)att->attrib.pValue; 1.5605 + sftk_FreeAttribute(att); 1.5606 + } 1.5607 + 1.5608 + hasExtractable = PR_FALSE; 1.5609 + att = sftk_FindAttribute(destKey,CKA_EXTRACTABLE); 1.5610 + if (att) { 1.5611 + hasExtractable = PR_TRUE; 1.5612 + extractable = (PRBool) *(CK_BBOOL *)att->attrib.pValue; 1.5613 + sftk_FreeAttribute(att); 1.5614 + } 1.5615 + 1.5616 + 1.5617 + /* don't make a key more accessible */ 1.5618 + if (sftk_isTrue(baseKey,CKA_SENSITIVE) && hasSensitive && 1.5619 + (sensitive == PR_FALSE)) { 1.5620 + return CKR_KEY_FUNCTION_NOT_PERMITTED; 1.5621 + } 1.5622 + if (!sftk_isTrue(baseKey,CKA_EXTRACTABLE) && hasExtractable && 1.5623 + (extractable == PR_TRUE)) { 1.5624 + return CKR_KEY_FUNCTION_NOT_PERMITTED; 1.5625 + } 1.5626 + 1.5627 + /* inherit parent's sensitivity */ 1.5628 + if (!hasSensitive) { 1.5629 + att = sftk_FindAttribute(baseKey,CKA_SENSITIVE); 1.5630 + if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT; 1.5631 + crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib)); 1.5632 + sftk_FreeAttribute(att); 1.5633 + if (crv != CKR_OK) return crv; 1.5634 + } 1.5635 + if (!hasExtractable) { 1.5636 + att = sftk_FindAttribute(baseKey,CKA_EXTRACTABLE); 1.5637 + if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT; 1.5638 + crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib)); 1.5639 + sftk_FreeAttribute(att); 1.5640 + if (crv != CKR_OK) return crv; 1.5641 + } 1.5642 + 1.5643 + /* we should inherit the parent's always extractable/ never sensitive info, 1.5644 + * but handleObject always forces this attributes, so we would need to do 1.5645 + * something special. */ 1.5646 + return CKR_OK; 1.5647 +} 1.5648 + 1.5649 +/* 1.5650 + * make known fixed PKCS #11 key types to their sizes in bytes 1.5651 + */ 1.5652 +unsigned long 1.5653 +sftk_MapKeySize(CK_KEY_TYPE keyType) 1.5654 +{ 1.5655 + switch (keyType) { 1.5656 + case CKK_CDMF: 1.5657 + return 8; 1.5658 + case CKK_DES: 1.5659 + return 8; 1.5660 + case CKK_DES2: 1.5661 + return 16; 1.5662 + case CKK_DES3: 1.5663 + return 24; 1.5664 + /* IDEA and CAST need to be added */ 1.5665 + default: 1.5666 + break; 1.5667 + } 1.5668 + return 0; 1.5669 +} 1.5670 + 1.5671 +#ifndef NSS_DISABLE_ECC 1.5672 +/* Inputs: 1.5673 + * key_len: Length of derived key to be generated. 1.5674 + * SharedSecret: a shared secret that is the output of a key agreement primitive. 1.5675 + * SharedInfo: (Optional) some data shared by the entities computing the secret key. 1.5676 + * SharedInfoLen: the length in octets of SharedInfo 1.5677 + * Hash: The hash function to be used in the KDF 1.5678 + * HashLen: the length in octets of the output of Hash 1.5679 + * Output: 1.5680 + * key: Pointer to a buffer containing derived key, if return value is SECSuccess. 1.5681 + */ 1.5682 +static CK_RV sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret, 1.5683 + CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, 1.5684 + SECStatus Hash(unsigned char *, const unsigned char *, PRUint32), 1.5685 + CK_ULONG HashLen) 1.5686 +{ 1.5687 + unsigned char *buffer = NULL, *output_buffer = NULL; 1.5688 + PRUint32 buffer_len, max_counter, i; 1.5689 + SECStatus rv; 1.5690 + CK_RV crv; 1.5691 + 1.5692 + /* Check that key_len isn't too long. The maximum key length could be 1.5693 + * greatly increased if the code below did not limit the 4-byte counter 1.5694 + * to a maximum value of 255. */ 1.5695 + if (key_len > 254 * HashLen) 1.5696 + return CKR_ARGUMENTS_BAD; 1.5697 + 1.5698 + if (SharedInfo == NULL) 1.5699 + SharedInfoLen = 0; 1.5700 + 1.5701 + buffer_len = SharedSecret->len + 4 + SharedInfoLen; 1.5702 + buffer = (CK_BYTE *)PORT_Alloc(buffer_len); 1.5703 + if (buffer == NULL) { 1.5704 + crv = CKR_HOST_MEMORY; 1.5705 + goto loser; 1.5706 + } 1.5707 + 1.5708 + max_counter = key_len/HashLen; 1.5709 + if (key_len > max_counter * HashLen) 1.5710 + max_counter++; 1.5711 + 1.5712 + output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen); 1.5713 + if (output_buffer == NULL) { 1.5714 + crv = CKR_HOST_MEMORY; 1.5715 + goto loser; 1.5716 + } 1.5717 + 1.5718 + /* Populate buffer with SharedSecret || Counter || [SharedInfo] 1.5719 + * where Counter is 0x00000001 */ 1.5720 + PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len); 1.5721 + buffer[SharedSecret->len] = 0; 1.5722 + buffer[SharedSecret->len + 1] = 0; 1.5723 + buffer[SharedSecret->len + 2] = 0; 1.5724 + buffer[SharedSecret->len + 3] = 1; 1.5725 + if (SharedInfo) { 1.5726 + PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen); 1.5727 + } 1.5728 + 1.5729 + for(i=0; i < max_counter; i++) { 1.5730 + rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len); 1.5731 + if (rv != SECSuccess) { 1.5732 + /* 'Hash' should not fail. */ 1.5733 + crv = CKR_FUNCTION_FAILED; 1.5734 + goto loser; 1.5735 + } 1.5736 + 1.5737 + /* Increment counter (assumes max_counter < 255) */ 1.5738 + buffer[SharedSecret->len + 3]++; 1.5739 + } 1.5740 + 1.5741 + PORT_ZFree(buffer, buffer_len); 1.5742 + if (key_len < max_counter * HashLen) { 1.5743 + PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len); 1.5744 + } 1.5745 + *key = output_buffer; 1.5746 + 1.5747 + return CKR_OK; 1.5748 + 1.5749 + loser: 1.5750 + if (buffer) { 1.5751 + PORT_ZFree(buffer, buffer_len); 1.5752 + } 1.5753 + if (output_buffer) { 1.5754 + PORT_ZFree(output_buffer, max_counter * HashLen); 1.5755 + } 1.5756 + return crv; 1.5757 +} 1.5758 + 1.5759 +static CK_RV sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, 1.5760 + SECItem *SharedSecret, 1.5761 + CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, 1.5762 + CK_EC_KDF_TYPE kdf) 1.5763 +{ 1.5764 + if (kdf == CKD_SHA1_KDF) 1.5765 + return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, 1.5766 + SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH); 1.5767 + else if (kdf == CKD_SHA224_KDF) 1.5768 + return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, 1.5769 + SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH); 1.5770 + else if (kdf == CKD_SHA256_KDF) 1.5771 + return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, 1.5772 + SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH); 1.5773 + else if (kdf == CKD_SHA384_KDF) 1.5774 + return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, 1.5775 + SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH); 1.5776 + else if (kdf == CKD_SHA512_KDF) 1.5777 + return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, 1.5778 + SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH); 1.5779 + else 1.5780 + return CKR_MECHANISM_INVALID; 1.5781 +} 1.5782 +#endif /* NSS_DISABLE_ECC */ 1.5783 + 1.5784 +/* 1.5785 + * SSL Key generation given pre master secret 1.5786 + */ 1.5787 +#define NUM_MIXERS 9 1.5788 +static const char * const mixers[NUM_MIXERS] = { 1.5789 + "A", 1.5790 + "BB", 1.5791 + "CCC", 1.5792 + "DDDD", 1.5793 + "EEEEE", 1.5794 + "FFFFFF", 1.5795 + "GGGGGGG", 1.5796 + "HHHHHHHH", 1.5797 + "IIIIIIIII" }; 1.5798 +#define SSL3_PMS_LENGTH 48 1.5799 +#define SSL3_MASTER_SECRET_LENGTH 48 1.5800 +#define SSL3_RANDOM_LENGTH 32 1.5801 + 1.5802 + 1.5803 +/* NSC_DeriveKey derives a key from a base key, creating a new key object. */ 1.5804 +CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, 1.5805 + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, 1.5806 + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, 1.5807 + CK_OBJECT_HANDLE_PTR phKey) 1.5808 +{ 1.5809 + SFTKSession * session; 1.5810 + SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession); 1.5811 + SFTKObject * key; 1.5812 + SFTKObject * sourceKey; 1.5813 + SFTKAttribute * att = NULL; 1.5814 + SFTKAttribute * att2 = NULL; 1.5815 + unsigned char * buf; 1.5816 + SHA1Context * sha; 1.5817 + MD5Context * md5; 1.5818 + MD2Context * md2; 1.5819 + CK_ULONG macSize; 1.5820 + CK_ULONG tmpKeySize; 1.5821 + CK_ULONG IVSize; 1.5822 + CK_ULONG keySize = 0; 1.5823 + CK_RV crv = CKR_OK; 1.5824 + CK_BBOOL cktrue = CK_TRUE; 1.5825 + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 1.5826 + CK_OBJECT_CLASS classType = CKO_SECRET_KEY; 1.5827 + CK_KEY_DERIVATION_STRING_DATA *stringPtr; 1.5828 + PRBool isTLS = PR_FALSE; 1.5829 + PRBool isSHA256 = PR_FALSE; 1.5830 + PRBool isDH = PR_FALSE; 1.5831 + SECStatus rv; 1.5832 + int i; 1.5833 + unsigned int outLen; 1.5834 + unsigned char sha_out[SHA1_LENGTH]; 1.5835 + unsigned char key_block[NUM_MIXERS * MD5_LENGTH]; 1.5836 + unsigned char key_block2[MD5_LENGTH]; 1.5837 + PRBool isFIPS; 1.5838 + HASH_HashType hashType; 1.5839 + PRBool extractValue = PR_TRUE; 1.5840 + 1.5841 + CHECK_FORK(); 1.5842 + 1.5843 + if (!slot) { 1.5844 + return CKR_SESSION_HANDLE_INVALID; 1.5845 + } 1.5846 + /* 1.5847 + * now lets create an object to hang the attributes off of 1.5848 + */ 1.5849 + if (phKey) *phKey = CK_INVALID_HANDLE; 1.5850 + 1.5851 + key = sftk_NewObject(slot); /* fill in the handle later */ 1.5852 + if (key == NULL) { 1.5853 + return CKR_HOST_MEMORY; 1.5854 + } 1.5855 + isFIPS = (slot->slotID == FIPS_SLOT_ID); 1.5856 + 1.5857 + /* 1.5858 + * load the template values into the object 1.5859 + */ 1.5860 + for (i=0; i < (int) ulAttributeCount; i++) { 1.5861 + crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i])); 1.5862 + if (crv != CKR_OK) break; 1.5863 + 1.5864 + if (pTemplate[i].type == CKA_KEY_TYPE) { 1.5865 + keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue; 1.5866 + } 1.5867 + if (pTemplate[i].type == CKA_VALUE_LEN) { 1.5868 + keySize = *(CK_ULONG *)pTemplate[i].pValue; 1.5869 + } 1.5870 + } 1.5871 + if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } 1.5872 + 1.5873 + if (keySize == 0) { 1.5874 + keySize = sftk_MapKeySize(keyType); 1.5875 + } 1.5876 + 1.5877 + switch (pMechanism->mechanism) { 1.5878 + case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */ 1.5879 + case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */ 1.5880 + case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */ 1.5881 + case CKM_NSS_JPAKE_ROUND2_SHA512: 1.5882 + extractValue = PR_FALSE; 1.5883 + classType = CKO_PRIVATE_KEY; 1.5884 + break; 1.5885 + case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */ 1.5886 + case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */ 1.5887 + case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */ 1.5888 + case CKM_NSS_JPAKE_FINAL_SHA512: 1.5889 + extractValue = PR_FALSE; 1.5890 + /* fall through */ 1.5891 + default: 1.5892 + classType = CKO_SECRET_KEY; 1.5893 + } 1.5894 + 1.5895 + crv = sftk_forceAttribute (key,CKA_CLASS,&classType,sizeof(classType)); 1.5896 + if (crv != CKR_OK) { 1.5897 + sftk_FreeObject(key); 1.5898 + return crv; 1.5899 + } 1.5900 + 1.5901 + /* look up the base key we're deriving with */ 1.5902 + session = sftk_SessionFromHandle(hSession); 1.5903 + if (session == NULL) { 1.5904 + sftk_FreeObject(key); 1.5905 + return CKR_SESSION_HANDLE_INVALID; 1.5906 + } 1.5907 + 1.5908 + sourceKey = sftk_ObjectFromHandle(hBaseKey,session); 1.5909 + sftk_FreeSession(session); 1.5910 + if (sourceKey == NULL) { 1.5911 + sftk_FreeObject(key); 1.5912 + return CKR_KEY_HANDLE_INVALID; 1.5913 + } 1.5914 + 1.5915 + if (extractValue) { 1.5916 + /* get the value of the base key */ 1.5917 + att = sftk_FindAttribute(sourceKey,CKA_VALUE); 1.5918 + if (att == NULL) { 1.5919 + sftk_FreeObject(key); 1.5920 + sftk_FreeObject(sourceKey); 1.5921 + return CKR_KEY_HANDLE_INVALID; 1.5922 + } 1.5923 + } 1.5924 + 1.5925 + switch (pMechanism->mechanism) { 1.5926 + /* 1.5927 + * generate the master secret 1.5928 + */ 1.5929 + case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256: 1.5930 + case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: 1.5931 + isSHA256 = PR_TRUE; 1.5932 + /* fall thru */ 1.5933 + case CKM_TLS_MASTER_KEY_DERIVE: 1.5934 + case CKM_TLS_MASTER_KEY_DERIVE_DH: 1.5935 + isTLS = PR_TRUE; 1.5936 + /* fall thru */ 1.5937 + case CKM_SSL3_MASTER_KEY_DERIVE: 1.5938 + case CKM_SSL3_MASTER_KEY_DERIVE_DH: 1.5939 + { 1.5940 + CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; 1.5941 + SSL3RSAPreMasterSecret * rsa_pms; 1.5942 + unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; 1.5943 + 1.5944 + if ((pMechanism->mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || 1.5945 + (pMechanism->mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) || 1.5946 + (pMechanism->mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) 1.5947 + isDH = PR_TRUE; 1.5948 + 1.5949 + /* first do the consistancy checks */ 1.5950 + if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { 1.5951 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.5952 + break; 1.5953 + } 1.5954 + att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE); 1.5955 + if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != 1.5956 + CKK_GENERIC_SECRET)) { 1.5957 + if (att2) sftk_FreeAttribute(att2); 1.5958 + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; 1.5959 + break; 1.5960 + } 1.5961 + sftk_FreeAttribute(att2); 1.5962 + if (keyType != CKK_GENERIC_SECRET) { 1.5963 + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; 1.5964 + break; 1.5965 + } 1.5966 + if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { 1.5967 + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; 1.5968 + break; 1.5969 + } 1.5970 + 1.5971 + /* finally do the key gen */ 1.5972 + ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) 1.5973 + pMechanism->pParameter; 1.5974 + 1.5975 + PORT_Memcpy(crsrdata, 1.5976 + ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); 1.5977 + PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, 1.5978 + ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); 1.5979 + 1.5980 + if (ssl3_master->pVersion) { 1.5981 + SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); 1.5982 + rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue; 1.5983 + /* don't leak more key material then necessary for SSL to work */ 1.5984 + if ((sessKey == NULL) || sessKey->wasDerived) { 1.5985 + ssl3_master->pVersion->major = 0xff; 1.5986 + ssl3_master->pVersion->minor = 0xff; 1.5987 + } else { 1.5988 + ssl3_master->pVersion->major = rsa_pms->client_version[0]; 1.5989 + ssl3_master->pVersion->minor = rsa_pms->client_version[1]; 1.5990 + } 1.5991 + } 1.5992 + if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) { 1.5993 + crv = CKR_MECHANISM_PARAM_INVALID; 1.5994 + break; 1.5995 + } 1.5996 + if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) { 1.5997 + crv = CKR_MECHANISM_PARAM_INVALID; 1.5998 + break; 1.5999 + } 1.6000 + 1.6001 + if (isTLS) { 1.6002 + SECStatus status; 1.6003 + SECItem crsr = { siBuffer, NULL, 0 }; 1.6004 + SECItem master = { siBuffer, NULL, 0 }; 1.6005 + SECItem pms = { siBuffer, NULL, 0 }; 1.6006 + 1.6007 + crsr.data = crsrdata; 1.6008 + crsr.len = sizeof crsrdata; 1.6009 + master.data = key_block; 1.6010 + master.len = SSL3_MASTER_SECRET_LENGTH; 1.6011 + pms.data = (unsigned char*)att->attrib.pValue; 1.6012 + pms.len = att->attrib.ulValueLen; 1.6013 + 1.6014 + if (isSHA256) { 1.6015 + status = TLS_P_hash(HASH_AlgSHA256, &pms, "master secret", 1.6016 + &crsr, &master, isFIPS); 1.6017 + } else { 1.6018 + status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); 1.6019 + } 1.6020 + if (status != SECSuccess) { 1.6021 + crv = CKR_FUNCTION_FAILED; 1.6022 + break; 1.6023 + } 1.6024 + } else { 1.6025 + /* now allocate the hash contexts */ 1.6026 + md5 = MD5_NewContext(); 1.6027 + if (md5 == NULL) { 1.6028 + crv = CKR_HOST_MEMORY; 1.6029 + break; 1.6030 + } 1.6031 + sha = SHA1_NewContext(); 1.6032 + if (sha == NULL) { 1.6033 + PORT_Free(md5); 1.6034 + crv = CKR_HOST_MEMORY; 1.6035 + break; 1.6036 + } 1.6037 + for (i = 0; i < 3; i++) { 1.6038 + SHA1_Begin(sha); 1.6039 + SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i])); 1.6040 + SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, 1.6041 + att->attrib.ulValueLen); 1.6042 + SHA1_Update(sha, crsrdata, sizeof crsrdata); 1.6043 + SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); 1.6044 + PORT_Assert(outLen == SHA1_LENGTH); 1.6045 + 1.6046 + MD5_Begin(md5); 1.6047 + MD5_Update(md5, (const unsigned char*)att->attrib.pValue, 1.6048 + att->attrib.ulValueLen); 1.6049 + MD5_Update(md5, sha_out, outLen); 1.6050 + MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH); 1.6051 + PORT_Assert(outLen == MD5_LENGTH); 1.6052 + } 1.6053 + PORT_Free(md5); 1.6054 + PORT_Free(sha); 1.6055 + } 1.6056 + 1.6057 + /* store the results */ 1.6058 + crv = sftk_forceAttribute 1.6059 + (key,CKA_VALUE,key_block,SSL3_MASTER_SECRET_LENGTH); 1.6060 + if (crv != CKR_OK) break; 1.6061 + keyType = CKK_GENERIC_SECRET; 1.6062 + crv = sftk_forceAttribute (key,CKA_KEY_TYPE,&keyType,sizeof(keyType)); 1.6063 + if (isTLS) { 1.6064 + /* TLS's master secret is used to "sign" finished msgs with PRF. */ 1.6065 + /* XXX This seems like a hack. But SFTK_Derive only accepts 1.6066 + * one "operation" argument. */ 1.6067 + crv = sftk_forceAttribute(key,CKA_SIGN, &cktrue,sizeof(CK_BBOOL)); 1.6068 + if (crv != CKR_OK) break; 1.6069 + crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL)); 1.6070 + if (crv != CKR_OK) break; 1.6071 + /* While we're here, we might as well force this, too. */ 1.6072 + crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL)); 1.6073 + if (crv != CKR_OK) break; 1.6074 + } 1.6075 + break; 1.6076 + } 1.6077 + 1.6078 + case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: 1.6079 + isSHA256 = PR_TRUE; 1.6080 + /* fall thru */ 1.6081 + case CKM_TLS_KEY_AND_MAC_DERIVE: 1.6082 + isTLS = PR_TRUE; 1.6083 + /* fall thru */ 1.6084 + case CKM_SSL3_KEY_AND_MAC_DERIVE: 1.6085 + { 1.6086 + CK_SSL3_KEY_MAT_PARAMS *ssl3_keys; 1.6087 + CK_SSL3_KEY_MAT_OUT * ssl3_keys_out; 1.6088 + CK_ULONG effKeySize; 1.6089 + unsigned int block_needed; 1.6090 + unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; 1.6091 + unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; 1.6092 + 1.6093 + crv = sftk_DeriveSensitiveCheck(sourceKey,key); 1.6094 + if (crv != CKR_OK) break; 1.6095 + 1.6096 + if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) { 1.6097 + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; 1.6098 + break; 1.6099 + } 1.6100 + att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE); 1.6101 + if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != 1.6102 + CKK_GENERIC_SECRET)) { 1.6103 + if (att2) sftk_FreeAttribute(att2); 1.6104 + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; 1.6105 + break; 1.6106 + } 1.6107 + sftk_FreeAttribute(att2); 1.6108 + md5 = MD5_NewContext(); 1.6109 + if (md5 == NULL) { 1.6110 + crv = CKR_HOST_MEMORY; 1.6111 + break; 1.6112 + } 1.6113 + sha = SHA1_NewContext(); 1.6114 + if (sha == NULL) { 1.6115 + PORT_Free(md5); 1.6116 + crv = CKR_HOST_MEMORY; 1.6117 + break; 1.6118 + } 1.6119 + ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter; 1.6120 + 1.6121 + PORT_Memcpy(srcrdata, 1.6122 + ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); 1.6123 + PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, 1.6124 + ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); 1.6125 + 1.6126 + PORT_Memcpy(crsrdata, 1.6127 + ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); 1.6128 + PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, 1.6129 + ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); 1.6130 + 1.6131 + /* 1.6132 + * clear out our returned keys so we can recover on failure 1.6133 + */ 1.6134 + ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial; 1.6135 + ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE; 1.6136 + ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE; 1.6137 + ssl3_keys_out->hClientKey = CK_INVALID_HANDLE; 1.6138 + ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; 1.6139 + 1.6140 + /* 1.6141 + * How much key material do we need? 1.6142 + */ 1.6143 + macSize = ssl3_keys->ulMacSizeInBits/8; 1.6144 + effKeySize = ssl3_keys->ulKeySizeInBits/8; 1.6145 + IVSize = ssl3_keys->ulIVSizeInBits/8; 1.6146 + if (keySize == 0) { 1.6147 + effKeySize = keySize; 1.6148 + } 1.6149 + block_needed = 2 * (macSize + effKeySize + 1.6150 + ((!ssl3_keys->bIsExport) * IVSize)); 1.6151 + PORT_Assert(block_needed <= sizeof key_block); 1.6152 + if (block_needed > sizeof key_block) 1.6153 + block_needed = sizeof key_block; 1.6154 + 1.6155 + /* 1.6156 + * generate the key material: This looks amazingly similar to the 1.6157 + * PMS code, and is clearly crying out for a function to provide it. 1.6158 + */ 1.6159 + if (isTLS) { 1.6160 + SECStatus status; 1.6161 + SECItem srcr = { siBuffer, NULL, 0 }; 1.6162 + SECItem keyblk = { siBuffer, NULL, 0 }; 1.6163 + SECItem master = { siBuffer, NULL, 0 }; 1.6164 + 1.6165 + srcr.data = srcrdata; 1.6166 + srcr.len = sizeof srcrdata; 1.6167 + keyblk.data = key_block; 1.6168 + keyblk.len = block_needed; 1.6169 + master.data = (unsigned char*)att->attrib.pValue; 1.6170 + master.len = att->attrib.ulValueLen; 1.6171 + 1.6172 + if (isSHA256) { 1.6173 + status = TLS_P_hash(HASH_AlgSHA256, &master, "key expansion", 1.6174 + &srcr, &keyblk, isFIPS); 1.6175 + } else { 1.6176 + status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, 1.6177 + isFIPS); 1.6178 + } 1.6179 + if (status != SECSuccess) { 1.6180 + goto key_and_mac_derive_fail; 1.6181 + } 1.6182 + } else { 1.6183 + unsigned int block_bytes = 0; 1.6184 + /* key_block = 1.6185 + * MD5(master_secret + SHA('A' + master_secret + 1.6186 + * ServerHello.random + ClientHello.random)) + 1.6187 + * MD5(master_secret + SHA('BB' + master_secret + 1.6188 + * ServerHello.random + ClientHello.random)) + 1.6189 + * MD5(master_secret + SHA('CCC' + master_secret + 1.6190 + * ServerHello.random + ClientHello.random)) + 1.6191 + * [...]; 1.6192 + */ 1.6193 + for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) { 1.6194 + SHA1_Begin(sha); 1.6195 + SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i])); 1.6196 + SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, 1.6197 + att->attrib.ulValueLen); 1.6198 + SHA1_Update(sha, srcrdata, sizeof srcrdata); 1.6199 + SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); 1.6200 + PORT_Assert(outLen == SHA1_LENGTH); 1.6201 + MD5_Begin(md5); 1.6202 + MD5_Update(md5, (const unsigned char*)att->attrib.pValue, 1.6203 + att->attrib.ulValueLen); 1.6204 + MD5_Update(md5, sha_out, outLen); 1.6205 + MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH); 1.6206 + PORT_Assert(outLen == MD5_LENGTH); 1.6207 + block_bytes += outLen; 1.6208 + } 1.6209 + } 1.6210 + 1.6211 + /* 1.6212 + * Put the key material where it goes. 1.6213 + */ 1.6214 + i = 0; /* now shows how much consumed */ 1.6215 + 1.6216 + /* 1.6217 + * The key_block is partitioned as follows: 1.6218 + * client_write_MAC_secret[CipherSpec.hash_size] 1.6219 + */ 1.6220 + crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize, 1.6221 + &ssl3_keys_out->hClientMacSecret); 1.6222 + if (crv != CKR_OK) 1.6223 + goto key_and_mac_derive_fail; 1.6224 + 1.6225 + i += macSize; 1.6226 + 1.6227 + /* 1.6228 + * server_write_MAC_secret[CipherSpec.hash_size] 1.6229 + */ 1.6230 + crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize, 1.6231 + &ssl3_keys_out->hServerMacSecret); 1.6232 + if (crv != CKR_OK) { 1.6233 + goto key_and_mac_derive_fail; 1.6234 + } 1.6235 + i += macSize; 1.6236 + 1.6237 + if (keySize) { 1.6238 + if (!ssl3_keys->bIsExport) { 1.6239 + /* 1.6240 + ** Generate Domestic write keys and IVs. 1.6241 + ** client_write_key[CipherSpec.key_material] 1.6242 + */ 1.6243 + crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i], 1.6244 + keySize, &ssl3_keys_out->hClientKey); 1.6245 + if (crv != CKR_OK) { 1.6246 + goto key_and_mac_derive_fail; 1.6247 + } 1.6248 + i += keySize; 1.6249 + 1.6250 + /* 1.6251 + ** server_write_key[CipherSpec.key_material] 1.6252 + */ 1.6253 + crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i], 1.6254 + keySize, &ssl3_keys_out->hServerKey); 1.6255 + if (crv != CKR_OK) { 1.6256 + goto key_and_mac_derive_fail; 1.6257 + } 1.6258 + i += keySize; 1.6259 + 1.6260 + /* 1.6261 + ** client_write_IV[CipherSpec.IV_size] 1.6262 + */ 1.6263 + if (IVSize > 0) { 1.6264 + PORT_Memcpy(ssl3_keys_out->pIVClient, 1.6265 + &key_block[i], IVSize); 1.6266 + i += IVSize; 1.6267 + } 1.6268 + 1.6269 + /* 1.6270 + ** server_write_IV[CipherSpec.IV_size] 1.6271 + */ 1.6272 + if (IVSize > 0) { 1.6273 + PORT_Memcpy(ssl3_keys_out->pIVServer, 1.6274 + &key_block[i], IVSize); 1.6275 + i += IVSize; 1.6276 + } 1.6277 + PORT_Assert(i <= sizeof key_block); 1.6278 + 1.6279 + } else if (!isTLS) { 1.6280 + 1.6281 + /* 1.6282 + ** Generate SSL3 Export write keys and IVs. 1.6283 + ** client_write_key[CipherSpec.key_material] 1.6284 + ** final_client_write_key = MD5(client_write_key + 1.6285 + ** ClientHello.random + ServerHello.random); 1.6286 + */ 1.6287 + MD5_Begin(md5); 1.6288 + MD5_Update(md5, &key_block[i], effKeySize); 1.6289 + MD5_Update(md5, crsrdata, sizeof crsrdata); 1.6290 + MD5_End(md5, key_block2, &outLen, MD5_LENGTH); 1.6291 + i += effKeySize; 1.6292 + crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2, 1.6293 + keySize,&ssl3_keys_out->hClientKey); 1.6294 + if (crv != CKR_OK) { 1.6295 + goto key_and_mac_derive_fail; 1.6296 + } 1.6297 + 1.6298 + /* 1.6299 + ** server_write_key[CipherSpec.key_material] 1.6300 + ** final_server_write_key = MD5(server_write_key + 1.6301 + ** ServerHello.random + ClientHello.random); 1.6302 + */ 1.6303 + MD5_Begin(md5); 1.6304 + MD5_Update(md5, &key_block[i], effKeySize); 1.6305 + MD5_Update(md5, srcrdata, sizeof srcrdata); 1.6306 + MD5_End(md5, key_block2, &outLen, MD5_LENGTH); 1.6307 + i += effKeySize; 1.6308 + crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2, 1.6309 + keySize,&ssl3_keys_out->hServerKey); 1.6310 + if (crv != CKR_OK) { 1.6311 + goto key_and_mac_derive_fail; 1.6312 + } 1.6313 + 1.6314 + /* 1.6315 + ** client_write_IV = 1.6316 + ** MD5(ClientHello.random + ServerHello.random); 1.6317 + */ 1.6318 + MD5_Begin(md5); 1.6319 + MD5_Update(md5, crsrdata, sizeof crsrdata); 1.6320 + MD5_End(md5, key_block2, &outLen, MD5_LENGTH); 1.6321 + PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize); 1.6322 + 1.6323 + /* 1.6324 + ** server_write_IV = 1.6325 + ** MD5(ServerHello.random + ClientHello.random); 1.6326 + */ 1.6327 + MD5_Begin(md5); 1.6328 + MD5_Update(md5, srcrdata, sizeof srcrdata); 1.6329 + MD5_End(md5, key_block2, &outLen, MD5_LENGTH); 1.6330 + PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize); 1.6331 + 1.6332 + } else { 1.6333 + 1.6334 + /* 1.6335 + ** Generate TLS 1.0 Export write keys and IVs. 1.6336 + */ 1.6337 + SECStatus status; 1.6338 + SECItem secret = { siBuffer, NULL, 0 }; 1.6339 + SECItem crsr = { siBuffer, NULL, 0 }; 1.6340 + SECItem keyblk = { siBuffer, NULL, 0 }; 1.6341 + 1.6342 + /* 1.6343 + ** client_write_key[CipherSpec.key_material] 1.6344 + ** final_client_write_key = PRF(client_write_key, 1.6345 + ** "client write key", 1.6346 + ** client_random + server_random); 1.6347 + */ 1.6348 + secret.data = &key_block[i]; 1.6349 + secret.len = effKeySize; 1.6350 + i += effKeySize; 1.6351 + crsr.data = crsrdata; 1.6352 + crsr.len = sizeof crsrdata; 1.6353 + keyblk.data = key_block2; 1.6354 + keyblk.len = sizeof key_block2; 1.6355 + status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, 1.6356 + isFIPS); 1.6357 + if (status != SECSuccess) { 1.6358 + goto key_and_mac_derive_fail; 1.6359 + } 1.6360 + crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2, 1.6361 + keySize, &ssl3_keys_out->hClientKey); 1.6362 + if (crv != CKR_OK) { 1.6363 + goto key_and_mac_derive_fail; 1.6364 + } 1.6365 + 1.6366 + /* 1.6367 + ** server_write_key[CipherSpec.key_material] 1.6368 + ** final_server_write_key = PRF(server_write_key, 1.6369 + ** "server write key", 1.6370 + ** client_random + server_random); 1.6371 + */ 1.6372 + secret.data = &key_block[i]; 1.6373 + secret.len = effKeySize; 1.6374 + i += effKeySize; 1.6375 + keyblk.data = key_block2; 1.6376 + keyblk.len = sizeof key_block2; 1.6377 + status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, 1.6378 + isFIPS); 1.6379 + if (status != SECSuccess) { 1.6380 + goto key_and_mac_derive_fail; 1.6381 + } 1.6382 + crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2, 1.6383 + keySize, &ssl3_keys_out->hServerKey); 1.6384 + if (crv != CKR_OK) { 1.6385 + goto key_and_mac_derive_fail; 1.6386 + } 1.6387 + 1.6388 + /* 1.6389 + ** iv_block = PRF("", "IV block", 1.6390 + ** client_random + server_random); 1.6391 + ** client_write_IV[SecurityParameters.IV_size] 1.6392 + ** server_write_IV[SecurityParameters.IV_size] 1.6393 + */ 1.6394 + if (IVSize) { 1.6395 + secret.data = NULL; 1.6396 + secret.len = 0; 1.6397 + keyblk.data = &key_block[i]; 1.6398 + keyblk.len = 2 * IVSize; 1.6399 + status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, 1.6400 + isFIPS); 1.6401 + if (status != SECSuccess) { 1.6402 + goto key_and_mac_derive_fail; 1.6403 + } 1.6404 + PORT_Memcpy(ssl3_keys_out->pIVClient, keyblk.data, IVSize); 1.6405 + PORT_Memcpy(ssl3_keys_out->pIVServer, keyblk.data + IVSize, 1.6406 + IVSize); 1.6407 + } 1.6408 + } 1.6409 + } 1.6410 + 1.6411 + crv = CKR_OK; 1.6412 + 1.6413 + if (0) { 1.6414 +key_and_mac_derive_fail: 1.6415 + if (crv == CKR_OK) 1.6416 + crv = CKR_FUNCTION_FAILED; 1.6417 + sftk_freeSSLKeys(hSession, ssl3_keys_out); 1.6418 + } 1.6419 + MD5_DestroyContext(md5, PR_TRUE); 1.6420 + SHA1_DestroyContext(sha, PR_TRUE); 1.6421 + sftk_FreeObject(key); 1.6422 + key = NULL; 1.6423 + break; 1.6424 + } 1.6425 + 1.6426 + case CKM_CONCATENATE_BASE_AND_KEY: 1.6427 + { 1.6428 + SFTKObject *newKey; 1.6429 + 1.6430 + crv = sftk_DeriveSensitiveCheck(sourceKey,key); 1.6431 + if (crv != CKR_OK) break; 1.6432 + 1.6433 + session = sftk_SessionFromHandle(hSession); 1.6434 + if (session == NULL) { 1.6435 + crv = CKR_SESSION_HANDLE_INVALID; 1.6436 + break; 1.6437 + } 1.6438 + 1.6439 + newKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *) 1.6440 + pMechanism->pParameter,session); 1.6441 + sftk_FreeSession(session); 1.6442 + if ( newKey == NULL) { 1.6443 + crv = CKR_KEY_HANDLE_INVALID; 1.6444 + break; 1.6445 + } 1.6446 + 1.6447 + if (sftk_isTrue(newKey,CKA_SENSITIVE)) { 1.6448 + crv = sftk_forceAttribute(newKey,CKA_SENSITIVE,&cktrue, 1.6449 + sizeof(CK_BBOOL)); 1.6450 + if (crv != CKR_OK) { 1.6451 + sftk_FreeObject(newKey); 1.6452 + break; 1.6453 + } 1.6454 + } 1.6455 + 1.6456 + att2 = sftk_FindAttribute(newKey,CKA_VALUE); 1.6457 + if (att2 == NULL) { 1.6458 + sftk_FreeObject(newKey); 1.6459 + crv = CKR_KEY_HANDLE_INVALID; 1.6460 + break; 1.6461 + } 1.6462 + tmpKeySize = att->attrib.ulValueLen+att2->attrib.ulValueLen; 1.6463 + if (keySize == 0) keySize = tmpKeySize; 1.6464 + if (keySize > tmpKeySize) { 1.6465 + sftk_FreeObject(newKey); 1.6466 + sftk_FreeAttribute(att2); 1.6467 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6468 + break; 1.6469 + } 1.6470 + buf = (unsigned char*)PORT_Alloc(tmpKeySize); 1.6471 + if (buf == NULL) { 1.6472 + sftk_FreeAttribute(att2); 1.6473 + sftk_FreeObject(newKey); 1.6474 + crv = CKR_HOST_MEMORY; 1.6475 + break; 1.6476 + } 1.6477 + 1.6478 + PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen); 1.6479 + PORT_Memcpy(buf+att->attrib.ulValueLen, 1.6480 + att2->attrib.pValue,att2->attrib.ulValueLen); 1.6481 + 1.6482 + crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); 1.6483 + PORT_ZFree(buf,tmpKeySize); 1.6484 + sftk_FreeAttribute(att2); 1.6485 + sftk_FreeObject(newKey); 1.6486 + break; 1.6487 + } 1.6488 + 1.6489 + case CKM_CONCATENATE_BASE_AND_DATA: 1.6490 + crv = sftk_DeriveSensitiveCheck(sourceKey,key); 1.6491 + if (crv != CKR_OK) break; 1.6492 + 1.6493 + stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter; 1.6494 + tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen; 1.6495 + if (keySize == 0) keySize = tmpKeySize; 1.6496 + if (keySize > tmpKeySize) { 1.6497 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6498 + break; 1.6499 + } 1.6500 + buf = (unsigned char*)PORT_Alloc(tmpKeySize); 1.6501 + if (buf == NULL) { 1.6502 + crv = CKR_HOST_MEMORY; 1.6503 + break; 1.6504 + } 1.6505 + 1.6506 + PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen); 1.6507 + PORT_Memcpy(buf+att->attrib.ulValueLen,stringPtr->pData, 1.6508 + stringPtr->ulLen); 1.6509 + 1.6510 + crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); 1.6511 + PORT_ZFree(buf,tmpKeySize); 1.6512 + break; 1.6513 + case CKM_CONCATENATE_DATA_AND_BASE: 1.6514 + crv = sftk_DeriveSensitiveCheck(sourceKey,key); 1.6515 + if (crv != CKR_OK) break; 1.6516 + 1.6517 + stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; 1.6518 + tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen; 1.6519 + if (keySize == 0) keySize = tmpKeySize; 1.6520 + if (keySize > tmpKeySize) { 1.6521 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6522 + break; 1.6523 + } 1.6524 + buf = (unsigned char*)PORT_Alloc(tmpKeySize); 1.6525 + if (buf == NULL) { 1.6526 + crv = CKR_HOST_MEMORY; 1.6527 + break; 1.6528 + } 1.6529 + 1.6530 + PORT_Memcpy(buf,stringPtr->pData,stringPtr->ulLen); 1.6531 + PORT_Memcpy(buf+stringPtr->ulLen,att->attrib.pValue, 1.6532 + att->attrib.ulValueLen); 1.6533 + 1.6534 + crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); 1.6535 + PORT_ZFree(buf,tmpKeySize); 1.6536 + break; 1.6537 + case CKM_XOR_BASE_AND_DATA: 1.6538 + crv = sftk_DeriveSensitiveCheck(sourceKey,key); 1.6539 + if (crv != CKR_OK) break; 1.6540 + 1.6541 + stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; 1.6542 + tmpKeySize = PR_MIN(att->attrib.ulValueLen,stringPtr->ulLen); 1.6543 + if (keySize == 0) keySize = tmpKeySize; 1.6544 + if (keySize > tmpKeySize) { 1.6545 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6546 + break; 1.6547 + } 1.6548 + buf = (unsigned char*)PORT_Alloc(keySize); 1.6549 + if (buf == NULL) { 1.6550 + crv = CKR_HOST_MEMORY; 1.6551 + break; 1.6552 + } 1.6553 + 1.6554 + 1.6555 + PORT_Memcpy(buf,att->attrib.pValue,keySize); 1.6556 + for (i=0; i < (int)keySize; i++) { 1.6557 + buf[i] ^= stringPtr->pData[i]; 1.6558 + } 1.6559 + 1.6560 + crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); 1.6561 + PORT_ZFree(buf,keySize); 1.6562 + break; 1.6563 + 1.6564 + case CKM_EXTRACT_KEY_FROM_KEY: 1.6565 + { 1.6566 + /* the following assumes 8 bits per byte */ 1.6567 + CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter; 1.6568 + CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */ 1.6569 + CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */ 1.6570 + 1.6571 + crv = sftk_DeriveSensitiveCheck(sourceKey,key); 1.6572 + if (crv != CKR_OK) break; 1.6573 + 1.6574 + if (keySize == 0) { 1.6575 + crv = CKR_TEMPLATE_INCOMPLETE; 1.6576 + break; 1.6577 + } 1.6578 + /* make sure we have enough bits in the original key */ 1.6579 + if (att->attrib.ulValueLen < 1.6580 + (offset + keySize + ((shift != 0)? 1 :0)) ) { 1.6581 + crv = CKR_MECHANISM_PARAM_INVALID; 1.6582 + break; 1.6583 + } 1.6584 + buf = (unsigned char*)PORT_Alloc(keySize); 1.6585 + if (buf == NULL) { 1.6586 + crv = CKR_HOST_MEMORY; 1.6587 + break; 1.6588 + } 1.6589 + 1.6590 + /* copy the bits we need into the new key */ 1.6591 + for (i=0; i < (int)keySize; i++) { 1.6592 + unsigned char *value = 1.6593 + ((unsigned char *)att->attrib.pValue)+offset+i; 1.6594 + if (shift) { 1.6595 + buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift)); 1.6596 + } else { 1.6597 + buf[i] = value[0]; 1.6598 + } 1.6599 + } 1.6600 + 1.6601 + crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); 1.6602 + PORT_ZFree(buf,keySize); 1.6603 + break; 1.6604 + } 1.6605 + case CKM_MD2_KEY_DERIVATION: 1.6606 + if (keySize == 0) keySize = MD2_LENGTH; 1.6607 + if (keySize > MD2_LENGTH) { 1.6608 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6609 + break; 1.6610 + } 1.6611 + /* now allocate the hash contexts */ 1.6612 + md2 = MD2_NewContext(); 1.6613 + if (md2 == NULL) { 1.6614 + crv = CKR_HOST_MEMORY; 1.6615 + break; 1.6616 + } 1.6617 + MD2_Begin(md2); 1.6618 + MD2_Update(md2,(const unsigned char*)att->attrib.pValue, 1.6619 + att->attrib.ulValueLen); 1.6620 + MD2_End(md2,key_block,&outLen,MD2_LENGTH); 1.6621 + MD2_DestroyContext(md2, PR_TRUE); 1.6622 + 1.6623 + crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize); 1.6624 + break; 1.6625 + case CKM_MD5_KEY_DERIVATION: 1.6626 + if (keySize == 0) keySize = MD5_LENGTH; 1.6627 + if (keySize > MD5_LENGTH) { 1.6628 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6629 + break; 1.6630 + } 1.6631 + MD5_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, 1.6632 + att->attrib.ulValueLen); 1.6633 + 1.6634 + crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize); 1.6635 + break; 1.6636 + case CKM_SHA1_KEY_DERIVATION: 1.6637 + if (keySize == 0) keySize = SHA1_LENGTH; 1.6638 + if (keySize > SHA1_LENGTH) { 1.6639 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6640 + break; 1.6641 + } 1.6642 + SHA1_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, 1.6643 + att->attrib.ulValueLen); 1.6644 + 1.6645 + crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); 1.6646 + break; 1.6647 + 1.6648 + case CKM_SHA224_KEY_DERIVATION: 1.6649 + if (keySize == 0) keySize = SHA224_LENGTH; 1.6650 + if (keySize > SHA224_LENGTH) { 1.6651 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6652 + break; 1.6653 + } 1.6654 + SHA224_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, 1.6655 + att->attrib.ulValueLen); 1.6656 + 1.6657 + crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); 1.6658 + break; 1.6659 + 1.6660 + case CKM_SHA256_KEY_DERIVATION: 1.6661 + if (keySize == 0) keySize = SHA256_LENGTH; 1.6662 + if (keySize > SHA256_LENGTH) { 1.6663 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6664 + break; 1.6665 + } 1.6666 + SHA256_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, 1.6667 + att->attrib.ulValueLen); 1.6668 + 1.6669 + crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); 1.6670 + break; 1.6671 + 1.6672 + case CKM_SHA384_KEY_DERIVATION: 1.6673 + if (keySize == 0) keySize = SHA384_LENGTH; 1.6674 + if (keySize > SHA384_LENGTH) { 1.6675 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6676 + break; 1.6677 + } 1.6678 + SHA384_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, 1.6679 + att->attrib.ulValueLen); 1.6680 + 1.6681 + crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); 1.6682 + break; 1.6683 + 1.6684 + case CKM_SHA512_KEY_DERIVATION: 1.6685 + if (keySize == 0) keySize = SHA512_LENGTH; 1.6686 + if (keySize > SHA512_LENGTH) { 1.6687 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6688 + break; 1.6689 + } 1.6690 + SHA512_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, 1.6691 + att->attrib.ulValueLen); 1.6692 + 1.6693 + crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); 1.6694 + break; 1.6695 + 1.6696 + case CKM_DH_PKCS_DERIVE: 1.6697 + { 1.6698 + SECItem derived, dhPublic; 1.6699 + SECItem dhPrime, dhValue; 1.6700 + /* sourceKey - values for the local existing low key */ 1.6701 + /* get prime and value attributes */ 1.6702 + crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); 1.6703 + if (crv != SECSuccess) break; 1.6704 + crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); 1.6705 + if (crv != SECSuccess) { 1.6706 + PORT_Free(dhPrime.data); 1.6707 + break; 1.6708 + } 1.6709 + 1.6710 + dhPublic.data = pMechanism->pParameter; 1.6711 + dhPublic.len = pMechanism->ulParameterLen; 1.6712 + 1.6713 + /* calculate private value - oct */ 1.6714 + rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); 1.6715 + 1.6716 + PORT_Free(dhPrime.data); 1.6717 + PORT_Free(dhValue.data); 1.6718 + 1.6719 + if (rv == SECSuccess) { 1.6720 + sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); 1.6721 + PORT_ZFree(derived.data, derived.len); 1.6722 + } else 1.6723 + crv = CKR_HOST_MEMORY; 1.6724 + 1.6725 + break; 1.6726 + } 1.6727 + 1.6728 +#ifndef NSS_DISABLE_ECC 1.6729 + case CKM_ECDH1_DERIVE: 1.6730 + case CKM_ECDH1_COFACTOR_DERIVE: 1.6731 + { 1.6732 + SECItem ecScalar, ecPoint; 1.6733 + SECItem tmp; 1.6734 + PRBool withCofactor = PR_FALSE; 1.6735 + unsigned char *secret; 1.6736 + unsigned char *keyData = NULL; 1.6737 + int secretlen, curveLen, pubKeyLen; 1.6738 + CK_ECDH1_DERIVE_PARAMS *mechParams; 1.6739 + NSSLOWKEYPrivateKey *privKey; 1.6740 + PLArenaPool *arena = NULL; 1.6741 + 1.6742 + /* Check mechanism parameters */ 1.6743 + mechParams = (CK_ECDH1_DERIVE_PARAMS *) pMechanism->pParameter; 1.6744 + if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) || 1.6745 + ((mechParams->kdf == CKD_NULL) && 1.6746 + ((mechParams->ulSharedDataLen != 0) || 1.6747 + (mechParams->pSharedData != NULL)))) { 1.6748 + crv = CKR_MECHANISM_PARAM_INVALID; 1.6749 + break; 1.6750 + } 1.6751 + 1.6752 + privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv); 1.6753 + if (privKey == NULL) { 1.6754 + break; 1.6755 + } 1.6756 + 1.6757 + /* Now we are working with a non-NULL private key */ 1.6758 + SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue); 1.6759 + 1.6760 + ecPoint.data = mechParams->pPublicData; 1.6761 + ecPoint.len = mechParams->ulPublicDataLen; 1.6762 + 1.6763 + curveLen = (privKey->u.ec.ecParams.fieldID.size +7)/8; 1.6764 + pubKeyLen = (2*curveLen) + 1; 1.6765 + 1.6766 + /* if the len is too small, can't be a valid point */ 1.6767 + if (ecPoint.len < pubKeyLen) { 1.6768 + goto ec_loser; 1.6769 + } 1.6770 + /* if the len is too large, must be an encoded point (length is 1.6771 + * equal case just falls through */ 1.6772 + if (ecPoint.len > pubKeyLen) { 1.6773 + SECItem newPoint; 1.6774 + 1.6775 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.6776 + if (arena == NULL) { 1.6777 + goto ec_loser; 1.6778 + } 1.6779 + 1.6780 + rv = SEC_QuickDERDecodeItem(arena, &newPoint, 1.6781 + SEC_ASN1_GET(SEC_OctetStringTemplate), 1.6782 + &ecPoint); 1.6783 + if (rv != SECSuccess) { 1.6784 + goto ec_loser; 1.6785 + } 1.6786 + ecPoint = newPoint; 1.6787 + } 1.6788 + 1.6789 + if (pMechanism->mechanism == CKM_ECDH1_COFACTOR_DERIVE) { 1.6790 + withCofactor = PR_TRUE; 1.6791 + } else { 1.6792 + /* When not using cofactor derivation, one should 1.6793 + * validate the public key to avoid small subgroup 1.6794 + * attacks. 1.6795 + */ 1.6796 + if (EC_ValidatePublicKey(&privKey->u.ec.ecParams, &ecPoint) 1.6797 + != SECSuccess) { 1.6798 + goto ec_loser; 1.6799 + } 1.6800 + } 1.6801 + 1.6802 + rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, 1.6803 + withCofactor, &tmp); 1.6804 + PORT_Free(ecScalar.data); 1.6805 + ecScalar.data = NULL; 1.6806 + if (privKey != sourceKey->objectInfo) { 1.6807 + nsslowkey_DestroyPrivateKey(privKey); 1.6808 + privKey=NULL; 1.6809 + } 1.6810 + if (arena) { 1.6811 + PORT_FreeArena(arena,PR_FALSE); 1.6812 + arena=NULL; 1.6813 + } 1.6814 + 1.6815 + if (rv != SECSuccess) { 1.6816 + crv = sftk_MapCryptError(PORT_GetError()); 1.6817 + break; 1.6818 + } 1.6819 + 1.6820 + 1.6821 + /* 1.6822 + * apply the kdf function. 1.6823 + */ 1.6824 + if (mechParams->kdf == CKD_NULL) { 1.6825 + /* 1.6826 + * tmp is the raw data created by ECDH_Derive, 1.6827 + * secret and secretlen are the values we will 1.6828 + * eventually pass as our generated key. 1.6829 + */ 1.6830 + secret = tmp.data; 1.6831 + secretlen = tmp.len; 1.6832 + } else { 1.6833 + secretlen = keySize; 1.6834 + crv = sftk_ANSI_X9_63_kdf(&secret, keySize, 1.6835 + &tmp, mechParams->pSharedData, 1.6836 + mechParams->ulSharedDataLen, mechParams->kdf); 1.6837 + PORT_ZFree(tmp.data, tmp.len); 1.6838 + if (crv != CKR_OK) { 1.6839 + break; 1.6840 + } 1.6841 + tmp.data = secret; 1.6842 + tmp.len = secretlen; 1.6843 + } 1.6844 + 1.6845 + /* 1.6846 + * if keySize is supplied, then we are generating a key of a specific 1.6847 + * length. This is done by taking the least significant 'keySize' 1.6848 + * bytes from the unsigned value calculated by ECDH. Note: this may 1.6849 + * mean padding temp with extra leading zeros from what ECDH_Derive 1.6850 + * already returned (which itself may contain leading zeros). 1.6851 + */ 1.6852 + if (keySize) { 1.6853 + if (secretlen < keySize) { 1.6854 + keyData = PORT_ZAlloc(keySize); 1.6855 + if (!keyData) { 1.6856 + PORT_ZFree(tmp.data, tmp.len); 1.6857 + crv = CKR_HOST_MEMORY; 1.6858 + break; 1.6859 + } 1.6860 + PORT_Memcpy(&keyData[keySize-secretlen],secret,secretlen); 1.6861 + secret = keyData; 1.6862 + } else { 1.6863 + secret += (secretlen - keySize); 1.6864 + } 1.6865 + secretlen = keySize; 1.6866 + } 1.6867 + 1.6868 + sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); 1.6869 + PORT_ZFree(tmp.data, tmp.len); 1.6870 + if (keyData) { 1.6871 + PORT_ZFree(keyData, keySize); 1.6872 + } 1.6873 + break; 1.6874 + 1.6875 +ec_loser: 1.6876 + crv = CKR_ARGUMENTS_BAD; 1.6877 + PORT_Free(ecScalar.data); 1.6878 + if (privKey != sourceKey->objectInfo) 1.6879 + nsslowkey_DestroyPrivateKey(privKey); 1.6880 + if (arena) { 1.6881 + PORT_FreeArena(arena, PR_FALSE); 1.6882 + } 1.6883 + break; 1.6884 + 1.6885 + } 1.6886 +#endif /* NSS_DISABLE_ECC */ 1.6887 + 1.6888 + /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */ 1.6889 + case CKM_NSS_HKDF_SHA1: hashType = HASH_AlgSHA1; goto hkdf; 1.6890 + case CKM_NSS_HKDF_SHA256: hashType = HASH_AlgSHA256; goto hkdf; 1.6891 + case CKM_NSS_HKDF_SHA384: hashType = HASH_AlgSHA384; goto hkdf; 1.6892 + case CKM_NSS_HKDF_SHA512: hashType = HASH_AlgSHA512; goto hkdf; 1.6893 +hkdf: { 1.6894 + const CK_NSS_HKDFParams * params = 1.6895 + (const CK_NSS_HKDFParams *) pMechanism->pParameter; 1.6896 + const SECHashObject * rawHash; 1.6897 + unsigned hashLen; 1.6898 + CK_BYTE buf[HASH_LENGTH_MAX]; 1.6899 + CK_BYTE * prk; /* psuedo-random key */ 1.6900 + CK_ULONG prkLen; 1.6901 + CK_BYTE * okm; /* output keying material */ 1.6902 + 1.6903 + rawHash = HASH_GetRawHashObject(hashType); 1.6904 + if (rawHash == NULL || rawHash->length > sizeof buf) { 1.6905 + crv = CKR_FUNCTION_FAILED; 1.6906 + break; 1.6907 + } 1.6908 + hashLen = rawHash->length; 1.6909 + 1.6910 + if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams) || 1.6911 + !params || (!params->bExpand && !params->bExtract) || 1.6912 + (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) || 1.6913 + (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) { 1.6914 + crv = CKR_MECHANISM_PARAM_INVALID; 1.6915 + break; 1.6916 + } 1.6917 + if (keySize == 0 || keySize > sizeof key_block || 1.6918 + (!params->bExpand && keySize > hashLen) || 1.6919 + (params->bExpand && keySize > 255 * hashLen)) { 1.6920 + crv = CKR_TEMPLATE_INCONSISTENT; 1.6921 + break; 1.6922 + } 1.6923 + crv = sftk_DeriveSensitiveCheck(sourceKey, key); 1.6924 + if (crv != CKR_OK) 1.6925 + break; 1.6926 + 1.6927 + /* HKDF-Extract(salt, base key value) */ 1.6928 + if (params->bExtract) { 1.6929 + CK_BYTE * salt; 1.6930 + CK_ULONG saltLen; 1.6931 + HMACContext * hmac; 1.6932 + unsigned int bufLen; 1.6933 + 1.6934 + salt = params->pSalt; 1.6935 + saltLen = params->ulSaltLen; 1.6936 + if (salt == NULL) { 1.6937 + saltLen = hashLen; 1.6938 + salt = buf; 1.6939 + memset(salt, 0, saltLen); 1.6940 + } 1.6941 + hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS); 1.6942 + if (!hmac) { 1.6943 + crv = CKR_HOST_MEMORY; 1.6944 + break; 1.6945 + } 1.6946 + HMAC_Begin(hmac); 1.6947 + HMAC_Update(hmac, (const unsigned char*) att->attrib.pValue, 1.6948 + att->attrib.ulValueLen); 1.6949 + HMAC_Finish(hmac, buf, &bufLen, sizeof(buf)); 1.6950 + HMAC_Destroy(hmac, PR_TRUE); 1.6951 + PORT_Assert(bufLen == rawHash->length); 1.6952 + prk = buf; 1.6953 + prkLen = bufLen; 1.6954 + } else { 1.6955 + /* PRK = base key value */ 1.6956 + prk = (CK_BYTE*) att->attrib.pValue; 1.6957 + prkLen = att->attrib.ulValueLen; 1.6958 + } 1.6959 + 1.6960 + /* HKDF-Expand */ 1.6961 + if (!params->bExpand) { 1.6962 + okm = prk; 1.6963 + } else { 1.6964 + /* T(1) = HMAC-Hash(prk, "" | info | 0x01) 1.6965 + * T(n) = HMAC-Hash(prk, T(n-1) | info | n 1.6966 + * key material = T(1) | ... | T(n) 1.6967 + */ 1.6968 + HMACContext * hmac; 1.6969 + CK_BYTE i; 1.6970 + unsigned iterations = PR_ROUNDUP(keySize, hashLen) / hashLen; 1.6971 + hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS); 1.6972 + if (hmac == NULL) { 1.6973 + crv = CKR_HOST_MEMORY; 1.6974 + break; 1.6975 + } 1.6976 + for (i = 1; i <= iterations; ++i) { 1.6977 + unsigned len; 1.6978 + HMAC_Begin(hmac); 1.6979 + if (i > 1) { 1.6980 + HMAC_Update(hmac, key_block + ((i-2) * hashLen), hashLen); 1.6981 + } 1.6982 + if (params->ulInfoLen != 0) { 1.6983 + HMAC_Update(hmac, params->pInfo, params->ulInfoLen); 1.6984 + } 1.6985 + HMAC_Update(hmac, &i, 1); 1.6986 + HMAC_Finish(hmac, key_block + ((i-1) * hashLen), &len, 1.6987 + hashLen); 1.6988 + PORT_Assert(len == hashLen); 1.6989 + } 1.6990 + HMAC_Destroy(hmac, PR_TRUE); 1.6991 + okm = key_block; 1.6992 + } 1.6993 + /* key material = prk */ 1.6994 + crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize); 1.6995 + break; 1.6996 + } /* end of CKM_NSS_HKDF_* */ 1.6997 + 1.6998 + case CKM_NSS_JPAKE_ROUND2_SHA1: hashType = HASH_AlgSHA1; goto jpake2; 1.6999 + case CKM_NSS_JPAKE_ROUND2_SHA256: hashType = HASH_AlgSHA256; goto jpake2; 1.7000 + case CKM_NSS_JPAKE_ROUND2_SHA384: hashType = HASH_AlgSHA384; goto jpake2; 1.7001 + case CKM_NSS_JPAKE_ROUND2_SHA512: hashType = HASH_AlgSHA512; goto jpake2; 1.7002 +jpake2: 1.7003 + if (pMechanism->pParameter == NULL || 1.7004 + pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params)) 1.7005 + crv = CKR_MECHANISM_PARAM_INVALID; 1.7006 + if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN)) 1.7007 + crv = CKR_TEMPLATE_INCONSISTENT; 1.7008 + if (crv == CKR_OK) 1.7009 + crv = sftk_DeriveSensitiveCheck(sourceKey, key); 1.7010 + if (crv == CKR_OK) 1.7011 + crv = jpake_Round2(hashType, 1.7012 + (CK_NSS_JPAKERound2Params *) pMechanism->pParameter, 1.7013 + sourceKey, key); 1.7014 + break; 1.7015 + 1.7016 + case CKM_NSS_JPAKE_FINAL_SHA1: hashType = HASH_AlgSHA1; goto jpakeFinal; 1.7017 + case CKM_NSS_JPAKE_FINAL_SHA256: hashType = HASH_AlgSHA256; goto jpakeFinal; 1.7018 + case CKM_NSS_JPAKE_FINAL_SHA384: hashType = HASH_AlgSHA384; goto jpakeFinal; 1.7019 + case CKM_NSS_JPAKE_FINAL_SHA512: hashType = HASH_AlgSHA512; goto jpakeFinal; 1.7020 +jpakeFinal: 1.7021 + if (pMechanism->pParameter == NULL || 1.7022 + pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams)) 1.7023 + crv = CKR_MECHANISM_PARAM_INVALID; 1.7024 + /* We purposely do not do the derive sensitivity check; we want to be 1.7025 + able to derive non-sensitive keys while allowing the ROUND1 and 1.7026 + ROUND2 keys to be sensitive (which they always are, since they are 1.7027 + in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE 1.7028 + in the template in order for the resultant keyblock key to be 1.7029 + sensitive. 1.7030 + */ 1.7031 + if (crv == CKR_OK) 1.7032 + crv = jpake_Final(hashType, 1.7033 + (CK_NSS_JPAKEFinalParams *) pMechanism->pParameter, 1.7034 + sourceKey, key); 1.7035 + break; 1.7036 + 1.7037 + default: 1.7038 + crv = CKR_MECHANISM_INVALID; 1.7039 + } 1.7040 + if (att) { 1.7041 + sftk_FreeAttribute(att); 1.7042 + } 1.7043 + sftk_FreeObject(sourceKey); 1.7044 + if (crv != CKR_OK) { 1.7045 + if (key) sftk_FreeObject(key); 1.7046 + return crv; 1.7047 + } 1.7048 + 1.7049 + /* link the key object into the list */ 1.7050 + if (key) { 1.7051 + SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); 1.7052 + PORT_Assert(sessKey); 1.7053 + /* get the session */ 1.7054 + sessKey->wasDerived = PR_TRUE; 1.7055 + session = sftk_SessionFromHandle(hSession); 1.7056 + if (session == NULL) { 1.7057 + sftk_FreeObject(key); 1.7058 + return CKR_HOST_MEMORY; 1.7059 + } 1.7060 + 1.7061 + crv = sftk_handleObject(key,session); 1.7062 + sftk_FreeSession(session); 1.7063 + *phKey = key->handle; 1.7064 + sftk_FreeObject(key); 1.7065 + } 1.7066 + return crv; 1.7067 +} 1.7068 + 1.7069 + 1.7070 +/* NSC_GetFunctionStatus obtains an updated status of a function running 1.7071 + * in parallel with an application. */ 1.7072 +CK_RV NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession) 1.7073 +{ 1.7074 + CHECK_FORK(); 1.7075 + 1.7076 + return CKR_FUNCTION_NOT_PARALLEL; 1.7077 +} 1.7078 + 1.7079 +/* NSC_CancelFunction cancels a function running in parallel */ 1.7080 +CK_RV NSC_CancelFunction(CK_SESSION_HANDLE hSession) 1.7081 +{ 1.7082 + CHECK_FORK(); 1.7083 + 1.7084 + return CKR_FUNCTION_NOT_PARALLEL; 1.7085 +} 1.7086 + 1.7087 +/* NSC_GetOperationState saves the state of the cryptographic 1.7088 + *operation in a session. 1.7089 + * NOTE: This code only works for digest functions for now. eventually need 1.7090 + * to add full flatten/resurect to our state stuff so that all types of state 1.7091 + * can be saved */ 1.7092 +CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession, 1.7093 + CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) 1.7094 +{ 1.7095 + SFTKSessionContext *context; 1.7096 + SFTKSession *session; 1.7097 + CK_RV crv; 1.7098 + CK_ULONG pOSLen = *pulOperationStateLen; 1.7099 + 1.7100 + CHECK_FORK(); 1.7101 + 1.7102 + /* make sure we're legal */ 1.7103 + crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); 1.7104 + if (crv != CKR_OK) return crv; 1.7105 + 1.7106 + *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) 1.7107 + + sizeof(SFTKContextType); 1.7108 + if (pOperationState == NULL) { 1.7109 + sftk_FreeSession(session); 1.7110 + return CKR_OK; 1.7111 + } else { 1.7112 + if (pOSLen < *pulOperationStateLen) { 1.7113 + return CKR_BUFFER_TOO_SMALL; 1.7114 + } 1.7115 + } 1.7116 + PORT_Memcpy(pOperationState,&context->type,sizeof(SFTKContextType)); 1.7117 + pOperationState += sizeof(SFTKContextType); 1.7118 + PORT_Memcpy(pOperationState,&context->currentMech, 1.7119 + sizeof(CK_MECHANISM_TYPE)); 1.7120 + pOperationState += sizeof(CK_MECHANISM_TYPE); 1.7121 + PORT_Memcpy(pOperationState,context->cipherInfo,context->cipherInfoLen); 1.7122 + sftk_FreeSession(session); 1.7123 + return CKR_OK; 1.7124 +} 1.7125 + 1.7126 + 1.7127 +#define sftk_Decrement(stateSize,len) \ 1.7128 + stateSize = ((stateSize) > (CK_ULONG)(len)) ? \ 1.7129 + ((stateSize) - (CK_ULONG)(len)) : 0; 1.7130 + 1.7131 +/* NSC_SetOperationState restores the state of the cryptographic 1.7132 + * operation in a session. This is coded like it can restore lots of 1.7133 + * states, but it only works for truly flat cipher structures. */ 1.7134 +CK_RV NSC_SetOperationState(CK_SESSION_HANDLE hSession, 1.7135 + CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, 1.7136 + CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) 1.7137 +{ 1.7138 + SFTKSessionContext *context; 1.7139 + SFTKSession *session; 1.7140 + SFTKContextType type; 1.7141 + CK_MECHANISM mech; 1.7142 + CK_RV crv = CKR_OK; 1.7143 + 1.7144 + CHECK_FORK(); 1.7145 + 1.7146 + while (ulOperationStateLen != 0) { 1.7147 + /* get what type of state we're dealing with... */ 1.7148 + PORT_Memcpy(&type,pOperationState, sizeof(SFTKContextType)); 1.7149 + 1.7150 + /* fix up session contexts based on type */ 1.7151 + session = sftk_SessionFromHandle(hSession); 1.7152 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.7153 + context = sftk_ReturnContextByType(session, type); 1.7154 + sftk_SetContextByType(session, type, NULL); 1.7155 + if (context) { 1.7156 + sftk_FreeContext(context); 1.7157 + } 1.7158 + pOperationState += sizeof(SFTKContextType); 1.7159 + sftk_Decrement(ulOperationStateLen,sizeof(SFTKContextType)); 1.7160 + 1.7161 + 1.7162 + /* get the mechanism structure */ 1.7163 + PORT_Memcpy(&mech.mechanism,pOperationState,sizeof(CK_MECHANISM_TYPE)); 1.7164 + pOperationState += sizeof(CK_MECHANISM_TYPE); 1.7165 + sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE)); 1.7166 + /* should be filled in... but not necessary for hash */ 1.7167 + mech.pParameter = NULL; 1.7168 + mech.ulParameterLen = 0; 1.7169 + switch (type) { 1.7170 + case SFTK_HASH: 1.7171 + crv = NSC_DigestInit(hSession,&mech); 1.7172 + if (crv != CKR_OK) break; 1.7173 + crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, 1.7174 + NULL); 1.7175 + if (crv != CKR_OK) break; 1.7176 + PORT_Memcpy(context->cipherInfo,pOperationState, 1.7177 + context->cipherInfoLen); 1.7178 + pOperationState += context->cipherInfoLen; 1.7179 + sftk_Decrement(ulOperationStateLen,context->cipherInfoLen); 1.7180 + break; 1.7181 + default: 1.7182 + /* do sign/encrypt/decrypt later */ 1.7183 + crv = CKR_SAVED_STATE_INVALID; 1.7184 + } 1.7185 + sftk_FreeSession(session); 1.7186 + if (crv != CKR_OK) break; 1.7187 + } 1.7188 + return crv; 1.7189 +} 1.7190 + 1.7191 +/* Dual-function cryptographic operations */ 1.7192 + 1.7193 +/* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption 1.7194 + * operation. */ 1.7195 +CK_RV NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 1.7196 + CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, 1.7197 + CK_ULONG_PTR pulEncryptedPartLen) 1.7198 +{ 1.7199 + CK_RV crv; 1.7200 + 1.7201 + CHECK_FORK(); 1.7202 + 1.7203 + crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart, 1.7204 + pulEncryptedPartLen); 1.7205 + if (crv != CKR_OK) return crv; 1.7206 + crv = NSC_DigestUpdate(hSession,pPart,ulPartLen); 1.7207 + 1.7208 + return crv; 1.7209 +} 1.7210 + 1.7211 + 1.7212 +/* NSC_DecryptDigestUpdate continues a multiple-part decryption and 1.7213 + * digesting operation. */ 1.7214 +CK_RV NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, 1.7215 + CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, 1.7216 + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) 1.7217 +{ 1.7218 + CK_RV crv; 1.7219 + 1.7220 + CHECK_FORK(); 1.7221 + 1.7222 + crv = NSC_DecryptUpdate(hSession,pEncryptedPart, ulEncryptedPartLen, 1.7223 + pPart, pulPartLen); 1.7224 + if (crv != CKR_OK) return crv; 1.7225 + crv = NSC_DigestUpdate(hSession,pPart,*pulPartLen); 1.7226 + 1.7227 + return crv; 1.7228 +} 1.7229 + 1.7230 + 1.7231 +/* NSC_SignEncryptUpdate continues a multiple-part signing and 1.7232 + * encryption operation. */ 1.7233 +CK_RV NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 1.7234 + CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, 1.7235 + CK_ULONG_PTR pulEncryptedPartLen) 1.7236 +{ 1.7237 + CK_RV crv; 1.7238 + 1.7239 + CHECK_FORK(); 1.7240 + 1.7241 + crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart, 1.7242 + pulEncryptedPartLen); 1.7243 + if (crv != CKR_OK) return crv; 1.7244 + crv = NSC_SignUpdate(hSession,pPart,ulPartLen); 1.7245 + 1.7246 + return crv; 1.7247 +} 1.7248 + 1.7249 + 1.7250 +/* NSC_DecryptVerifyUpdate continues a multiple-part decryption 1.7251 + * and verify operation. */ 1.7252 +CK_RV NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, 1.7253 + CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, 1.7254 + CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 1.7255 +{ 1.7256 + CK_RV crv; 1.7257 + 1.7258 + CHECK_FORK(); 1.7259 + 1.7260 + crv = NSC_DecryptUpdate(hSession,pEncryptedData, ulEncryptedDataLen, 1.7261 + pData, pulDataLen); 1.7262 + if (crv != CKR_OK) return crv; 1.7263 + crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen); 1.7264 + 1.7265 + return crv; 1.7266 +} 1.7267 + 1.7268 +/* NSC_DigestKey continues a multi-part message-digesting operation, 1.7269 + * by digesting the value of a secret key as part of the data already digested. 1.7270 + */ 1.7271 +CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) 1.7272 +{ 1.7273 + SFTKSession *session = NULL; 1.7274 + SFTKObject *key = NULL; 1.7275 + SFTKAttribute *att; 1.7276 + CK_RV crv; 1.7277 + 1.7278 + CHECK_FORK(); 1.7279 + 1.7280 + session = sftk_SessionFromHandle(hSession); 1.7281 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.7282 + 1.7283 + key = sftk_ObjectFromHandle(hKey,session); 1.7284 + sftk_FreeSession(session); 1.7285 + if (key == NULL) return CKR_KEY_HANDLE_INVALID; 1.7286 + 1.7287 + /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */ 1.7288 + 1.7289 + /* make sure it's a valid key for this operation */ 1.7290 + if (key->objclass != CKO_SECRET_KEY) { 1.7291 + sftk_FreeObject(key); 1.7292 + return CKR_KEY_TYPE_INCONSISTENT; 1.7293 + } 1.7294 + /* get the key value */ 1.7295 + att = sftk_FindAttribute(key,CKA_VALUE); 1.7296 + sftk_FreeObject(key); 1.7297 + if (!att) { 1.7298 + return CKR_KEY_HANDLE_INVALID; 1.7299 + } 1.7300 + crv = NSC_DigestUpdate(hSession,(CK_BYTE_PTR)att->attrib.pValue, 1.7301 + att->attrib.ulValueLen); 1.7302 + sftk_FreeAttribute(att); 1.7303 + return crv; 1.7304 +}