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