1 /* 2 * Key Derivation that doesn't use PKCS11 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "ssl.h" /* prereq to sslimpl.h */ 9 #include "certt.h" /* prereq to sslimpl.h */ 10 #include "keythi.h" /* prereq to sslimpl.h */ 11 #include "sslimpl.h" 12 #ifndef NO_PKCS11_BYPASS 13 #include "blapi.h" 14 #endif 15 16 #include "keyhi.h" 17 #include "pk11func.h" 18 #include "secasn1.h" 19 #include "cert.h" 20 #include "secmodt.h" 21 22 #include "sslproto.h" 23 #include "sslerr.h" 24 25 #ifndef NO_PKCS11_BYPASS 26 /* make this a macro! */ 27 #ifdef NOT_A_MACRO 28 static void 29 buildSSLKey(unsigned char * keyBlock, unsigned int keyLen, SECItem * result, 30 const char * label) 31 { 32 result->type = siBuffer; 33 result->data = keyBlock; 34 result->len = keyLen; 35 PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); 36 } 37 #else 38 #define buildSSLKey(keyBlock, keyLen, result, label) \ 39 { \ 40 (result)->type = siBuffer; \ 41 (result)->data = keyBlock; \ 42 (result)->len = keyLen; \ 43 PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); \ 44 } 45 #endif 46 47 /* 48 * SSL Key generation given pre master secret 49 */ 50 #ifndef NUM_MIXERS 51 #define NUM_MIXERS 9 52 #endif 53 static const char * const mixers[NUM_MIXERS] = { 54 "A", 55 "BB", 56 "CCC", 57 "DDDD", 58 "EEEEE", 59 "FFFFFF", 60 "GGGGGGG", 61 "HHHHHHHH", 62 "IIIIIIIII" 63 }; 64 65 66 SECStatus 67 ssl3_KeyAndMacDeriveBypass( 68 ssl3CipherSpec * pwSpec, 69 const unsigned char * cr, 70 const unsigned char * sr, 71 PRBool isTLS, 72 PRBool isExport) 73 { 74 const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def; 75 unsigned char * key_block = pwSpec->key_block; 76 unsigned char * key_block2 = NULL; 77 unsigned int block_bytes = 0; 78 unsigned int block_needed = 0; 79 unsigned int i; 80 unsigned int keySize; /* actual size of cipher keys */ 81 unsigned int effKeySize; /* effective size of cipher keys */ 82 unsigned int macSize; /* size of MAC secret */ 83 unsigned int IVSize; /* size of IV */ 84 PRBool explicitIV = PR_FALSE; 85 SECStatus rv = SECFailure; 86 SECStatus status = SECSuccess; 87 PRBool isFIPS = PR_FALSE; 88 PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2; 89 90 SECItem srcr; 91 SECItem crsr; 92 93 unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; 94 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; 95 PRUint64 md5buf[22]; 96 PRUint64 shabuf[40]; 97 98 #define md5Ctx ((MD5Context *)md5buf) 99 #define shaCtx ((SHA1Context *)shabuf) 100 101 static const SECItem zed = { siBuffer, NULL, 0 }; 102 103 if (pwSpec->msItem.data == NULL || 104 pwSpec->msItem.len != SSL3_MASTER_SECRET_LENGTH) { 105 PORT_SetError(SEC_ERROR_INVALID_ARGS); 106 return rv; 107 } 108 109 PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data, 110 pwSpec->msItem.len)); 111 112 /* figure out how much is needed */ 113 macSize = pwSpec->mac_size; 114 keySize = cipher_def->key_size; 115 effKeySize = cipher_def->secret_key_size; 116 IVSize = cipher_def->iv_size; 117 if (keySize == 0) { 118 effKeySize = IVSize = 0; /* only MACing */ 119 } 120 if (cipher_def->type == type_block && 121 pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { 122 /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */ 123 explicitIV = PR_TRUE; 124 } 125 block_needed = 126 2 * (macSize + effKeySize + ((!isExport && !explicitIV) * IVSize)); 127 128 /* 129 * clear out our returned keys so we can recover on failure 130 */ 131 pwSpec->client.write_key_item = zed; 132 pwSpec->client.write_mac_key_item = zed; 133 pwSpec->server.write_key_item = zed; 134 pwSpec->server.write_mac_key_item = zed; 135 136 /* initialize the server random, client random block */ 137 srcr.type = siBuffer; 138 srcr.data = srcrdata; 139 srcr.len = sizeof srcrdata; 140 PORT_Memcpy(srcrdata, sr, SSL3_RANDOM_LENGTH); 141 PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, cr, SSL3_RANDOM_LENGTH); 142 143 /* initialize the client random, server random block */ 144 crsr.type = siBuffer; 145 crsr.data = crsrdata; 146 crsr.len = sizeof crsrdata; 147 PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH); 148 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH); 149 PRINT_BUF(100, (NULL, "Key & MAC CRSR", crsr.data, crsr.len)); 150 151 /* 152 * generate the key material: 153 */ 154 if (isTLS) { 155 SECItem keyblk; 156 157 keyblk.type = siBuffer; 158 keyblk.data = key_block; 159 keyblk.len = block_needed; 160 161 if (isTLS12) { 162 status = TLS_P_hash(HASH_AlgSHA256, &pwSpec->msItem, 163 "key expansion", &srcr, &keyblk, isFIPS); 164 } else { 165 status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk, 166 isFIPS); 167 } 168 if (status != SECSuccess) { 169 goto key_and_mac_derive_fail; 170 } 171 block_bytes = keyblk.len; 172 } else { 173 /* key_block = 174 * MD5(master_secret + SHA('A' + master_secret + 175 * ServerHello.random + ClientHello.random)) + 176 * MD5(master_secret + SHA('BB' + master_secret + 177 * ServerHello.random + ClientHello.random)) + 178 * MD5(master_secret + SHA('CCC' + master_secret + 179 * ServerHello.random + ClientHello.random)) + 180 * [...]; 181 */ 182 unsigned int made = 0; 183 for (i = 0; made < block_needed && i < NUM_MIXERS; ++i) { 184 unsigned int outLen; 185 unsigned char sha_out[SHA1_LENGTH]; 186 187 SHA1_Begin(shaCtx); 188 SHA1_Update(shaCtx, (unsigned char*)(mixers[i]), i+1); 189 SHA1_Update(shaCtx, pwSpec->msItem.data, pwSpec->msItem.len); 190 SHA1_Update(shaCtx, srcr.data, srcr.len); 191 SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH); 192 PORT_Assert(outLen == SHA1_LENGTH); 193 194 MD5_Begin(md5Ctx); 195 MD5_Update(md5Ctx, pwSpec->msItem.data, pwSpec->msItem.len); 196 MD5_Update(md5Ctx, sha_out, outLen); 197 MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH); 198 PORT_Assert(outLen == MD5_LENGTH); 199 made += MD5_LENGTH; 200 } 201 block_bytes = made; 202 } 203 PORT_Assert(block_bytes >= block_needed); 204 PORT_Assert(block_bytes <= sizeof pwSpec->key_block); 205 PRINT_BUF(100, (NULL, "key block", key_block, block_bytes)); 206 207 /* 208 * Put the key material where it goes. 209 */ 210 key_block2 = key_block + block_bytes; 211 i = 0; /* now shows how much consumed */ 212 213 /* 214 * The key_block is partitioned as follows: 215 * client_write_MAC_secret[CipherSpec.hash_size] 216 */ 217 buildSSLKey(&key_block[i],macSize, &pwSpec->client.write_mac_key_item, \ 218 "Client Write MAC Secret"); 219 i += macSize; 220 221 /* 222 * server_write_MAC_secret[CipherSpec.hash_size] 223 */ 224 buildSSLKey(&key_block[i],macSize, &pwSpec->server.write_mac_key_item, \ 225 "Server Write MAC Secret"); 226 i += macSize; 227 228 if (!keySize) { 229 /* only MACing */ 230 buildSSLKey(NULL, 0, &pwSpec->client.write_key_item, \ 231 "Client Write Key (MAC only)"); 232 buildSSLKey(NULL, 0, &pwSpec->server.write_key_item, \ 233 "Server Write Key (MAC only)"); 234 buildSSLKey(NULL, 0, &pwSpec->client.write_iv_item, \ 235 "Client Write IV (MAC only)"); 236 buildSSLKey(NULL, 0, &pwSpec->server.write_iv_item, \ 237 "Server Write IV (MAC only)"); 238 } else if (!isExport) { 239 /* 240 ** Generate Domestic write keys and IVs. 241 ** client_write_key[CipherSpec.key_material] 242 */ 243 buildSSLKey(&key_block[i], keySize, &pwSpec->client.write_key_item, \ 244 "Domestic Client Write Key"); 245 i += keySize; 246 247 /* 248 ** server_write_key[CipherSpec.key_material] 249 */ 250 buildSSLKey(&key_block[i], keySize, &pwSpec->server.write_key_item, \ 251 "Domestic Server Write Key"); 252 i += keySize; 253 254 if (IVSize > 0) { 255 if (explicitIV) { 256 static unsigned char zero_block[32]; 257 PORT_Assert(IVSize <= sizeof zero_block); 258 buildSSLKey(&zero_block[0], IVSize, \ 259 &pwSpec->client.write_iv_item, \ 260 "Domestic Client Write IV"); 261 buildSSLKey(&zero_block[0], IVSize, \ 262 &pwSpec->server.write_iv_item, \ 263 "Domestic Server Write IV"); 264 } else { 265 /* 266 ** client_write_IV[CipherSpec.IV_size] 267 */ 268 buildSSLKey(&key_block[i], IVSize, \ 269 &pwSpec->client.write_iv_item, \ 270 "Domestic Client Write IV"); 271 i += IVSize; 272 273 /* 274 ** server_write_IV[CipherSpec.IV_size] 275 */ 276 buildSSLKey(&key_block[i], IVSize, \ 277 &pwSpec->server.write_iv_item, \ 278 "Domestic Server Write IV"); 279 i += IVSize; 280 } 281 } 282 PORT_Assert(i <= block_bytes); 283 } else if (!isTLS) { 284 /* 285 ** Generate SSL3 Export write keys and IVs. 286 */ 287 unsigned int outLen; 288 289 /* 290 ** client_write_key[CipherSpec.key_material] 291 ** final_client_write_key = MD5(client_write_key + 292 ** ClientHello.random + ServerHello.random); 293 */ 294 MD5_Begin(md5Ctx); 295 MD5_Update(md5Ctx, &key_block[i], effKeySize); 296 MD5_Update(md5Ctx, crsr.data, crsr.len); 297 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); 298 i += effKeySize; 299 buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item, \ 300 "SSL3 Export Client Write Key"); 301 key_block2 += keySize; 302 303 /* 304 ** server_write_key[CipherSpec.key_material] 305 ** final_server_write_key = MD5(server_write_key + 306 ** ServerHello.random + ClientHello.random); 307 */ 308 MD5_Begin(md5Ctx); 309 MD5_Update(md5Ctx, &key_block[i], effKeySize); 310 MD5_Update(md5Ctx, srcr.data, srcr.len); 311 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); 312 i += effKeySize; 313 buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item, \ 314 "SSL3 Export Server Write Key"); 315 key_block2 += keySize; 316 PORT_Assert(i <= block_bytes); 317 318 if (IVSize) { 319 /* 320 ** client_write_IV = 321 ** MD5(ClientHello.random + ServerHello.random); 322 */ 323 MD5_Begin(md5Ctx); 324 MD5_Update(md5Ctx, crsr.data, crsr.len); 325 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); 326 buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item, \ 327 "SSL3 Export Client Write IV"); 328 key_block2 += IVSize; 329 330 /* 331 ** server_write_IV = 332 ** MD5(ServerHello.random + ClientHello.random); 333 */ 334 MD5_Begin(md5Ctx); 335 MD5_Update(md5Ctx, srcr.data, srcr.len); 336 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); 337 buildSSLKey(key_block2, IVSize, &pwSpec->server.write_iv_item, \ 338 "SSL3 Export Server Write IV"); 339 key_block2 += IVSize; 340 } 341 342 PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block); 343 } else { 344 /* 345 ** Generate TLS Export write keys and IVs. 346 */ 347 SECItem secret ; 348 SECItem keyblk ; 349 350 secret.type = siBuffer; 351 keyblk.type = siBuffer; 352 /* 353 ** client_write_key[CipherSpec.key_material] 354 ** final_client_write_key = PRF(client_write_key, 355 ** "client write key", 356 ** client_random + server_random); 357 */ 358 secret.data = &key_block[i]; 359 secret.len = effKeySize; 360 i += effKeySize; 361 keyblk.data = key_block2; 362 keyblk.len = keySize; 363 status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS); 364 if (status != SECSuccess) { 365 goto key_and_mac_derive_fail; 366 } 367 buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item, \ 368 "TLS Export Client Write Key"); 369 key_block2 += keySize; 370 371 /* 372 ** server_write_key[CipherSpec.key_material] 373 ** final_server_write_key = PRF(server_write_key, 374 ** "server write key", 375 ** client_random + server_random); 376 */ 377 secret.data = &key_block[i]; 378 secret.len = effKeySize; 379 i += effKeySize; 380 keyblk.data = key_block2; 381 keyblk.len = keySize; 382 status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS); 383 if (status != SECSuccess) { 384 goto key_and_mac_derive_fail; 385 } 386 buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item, \ 387 "TLS Export Server Write Key"); 388 key_block2 += keySize; 389 390 /* 391 ** iv_block = PRF("", "IV block", client_random + server_random); 392 ** client_write_IV[SecurityParameters.IV_size] 393 ** server_write_IV[SecurityParameters.IV_size] 394 */ 395 if (IVSize) { 396 secret.data = NULL; 397 secret.len = 0; 398 keyblk.data = key_block2; 399 keyblk.len = 2 * IVSize; 400 status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS); 401 if (status != SECSuccess) { 402 goto key_and_mac_derive_fail; 403 } 404 buildSSLKey(key_block2, IVSize, \ 405 &pwSpec->client.write_iv_item, \ 406 "TLS Export Client Write IV"); 407 buildSSLKey(key_block2 + IVSize, IVSize, \ 408 &pwSpec->server.write_iv_item, \ 409 "TLS Export Server Write IV"); 410 key_block2 += 2 * IVSize; 411 } 412 PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block); 413 } 414 rv = SECSuccess; 415 416 key_and_mac_derive_fail: 417 418 MD5_DestroyContext(md5Ctx, PR_FALSE); 419 SHA1_DestroyContext(shaCtx, PR_FALSE); 420 421 if (rv != SECSuccess) { 422 PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); 423 } 424 425 return rv; 426 } 427 428 429 /* derive the Master Secret from the PMS */ 430 /* Presently, this is only done wtih RSA PMS, and only on the server side, 431 * so isRSA is always true. 432 */ 433 SECStatus 434 ssl3_MasterKeyDeriveBypass( 435 ssl3CipherSpec * pwSpec, 436 const unsigned char * cr, 437 const unsigned char * sr, 438 const SECItem * pms, 439 PRBool isTLS, 440 PRBool isRSA) 441 { 442 unsigned char * key_block = pwSpec->key_block; 443 SECStatus rv = SECSuccess; 444 PRBool isFIPS = PR_FALSE; 445 PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2; 446 447 SECItem crsr; 448 449 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; 450 PRUint64 md5buf[22]; 451 PRUint64 shabuf[40]; 452 453 #define md5Ctx ((MD5Context *)md5buf) 454 #define shaCtx ((SHA1Context *)shabuf) 455 456 /* first do the consistancy checks */ 457 if (isRSA) { 458 PORT_Assert(pms->len == SSL3_RSA_PMS_LENGTH); 459 if (pms->len != SSL3_RSA_PMS_LENGTH) { 460 PORT_SetError(SEC_ERROR_INVALID_ARGS); 461 return SECFailure; 462 } 463 /* caller must test PMS version for rollback */ 464 } 465 466 /* initialize the client random, server random block */ 467 crsr.type = siBuffer; 468 crsr.data = crsrdata; 469 crsr.len = sizeof crsrdata; 470 PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH); 471 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH); 472 PRINT_BUF(100, (NULL, "Master Secret CRSR", crsr.data, crsr.len)); 473 474 /* finally do the key gen */ 475 if (isTLS) { 476 SECItem master = { siBuffer, NULL, 0 }; 477 478 master.data = key_block; 479 master.len = SSL3_MASTER_SECRET_LENGTH; 480 481 if (isTLS12) { 482 rv = TLS_P_hash(HASH_AlgSHA256, pms, "master secret", &crsr, 483 &master, isFIPS); 484 } else { 485 rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS); 486 } 487 if (rv != SECSuccess) { 488 PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); 489 } 490 } else { 491 int i; 492 unsigned int made = 0; 493 for (i = 0; i < 3; i++) { 494 unsigned int outLen; 495 unsigned char sha_out[SHA1_LENGTH]; 496 497 SHA1_Begin(shaCtx); 498 SHA1_Update(shaCtx, (unsigned char*) mixers[i], i+1); 499 SHA1_Update(shaCtx, pms->data, pms->len); 500 SHA1_Update(shaCtx, crsr.data, crsr.len); 501 SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH); 502 PORT_Assert(outLen == SHA1_LENGTH); 503 504 MD5_Begin(md5Ctx); 505 MD5_Update(md5Ctx, pms->data, pms->len); 506 MD5_Update(md5Ctx, sha_out, outLen); 507 MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH); 508 PORT_Assert(outLen == MD5_LENGTH); 509 made += outLen; 510 } 511 } 512 513 /* store the results */ 514 PORT_Memcpy(pwSpec->raw_master_secret, key_block, 515 SSL3_MASTER_SECRET_LENGTH); 516 pwSpec->msItem.data = pwSpec->raw_master_secret; 517 pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH; 518 PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data, 519 pwSpec->msItem.len)); 520 521 return rv; 522 } 523 524 static SECStatus 525 ssl_canExtractMS(PK11SymKey *pms, PRBool isTLS, PRBool isDH, PRBool *pcbp) 526 { SECStatus rv; 527 PK11SymKey * ms = NULL; 528 SECItem params = {siBuffer, NULL, 0}; 529 CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params; 530 unsigned char rand[SSL3_RANDOM_LENGTH]; 531 CK_VERSION pms_version; 532 CK_MECHANISM_TYPE master_derive; 533 CK_MECHANISM_TYPE key_derive; 534 CK_FLAGS keyFlags; 535 536 if (pms == NULL) 537 return(SECFailure); 538 539 PORT_Memset(rand, 0, SSL3_RANDOM_LENGTH); 540 541 if (isTLS) { 542 if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH; 543 else master_derive = CKM_TLS_MASTER_KEY_DERIVE; 544 key_derive = CKM_TLS_KEY_AND_MAC_DERIVE; 545 keyFlags = CKF_SIGN | CKF_VERIFY; 546 } else { 547 if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH; 548 else master_derive = CKM_SSL3_MASTER_KEY_DERIVE; 549 key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE; 550 keyFlags = 0; 551 } 552 553 master_params.pVersion = &pms_version; 554 master_params.RandomInfo.pClientRandom = rand; 555 master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH; 556 master_params.RandomInfo.pServerRandom = rand; 557 master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH; 558 559 params.data = (unsigned char *) &master_params; 560 params.len = sizeof master_params; 561 562 ms = PK11_DeriveWithFlags(pms, master_derive, ¶ms, key_derive, 563 CKA_DERIVE, 0, keyFlags); 564 if (ms == NULL) 565 return(SECFailure); 566 567 rv = PK11_ExtractKeyValue(ms); 568 *pcbp = (rv == SECSuccess); 569 PK11_FreeSymKey(ms); 570 571 return(rv); 572 573 } 574 #endif /* !NO_PKCS11_BYPASS */ 575 576 /* Check the key exchange algorithm for each cipher in the list to see if 577 * a master secret key can be extracted. If the KEA will use keys from the 578 * specified cert make sure the extract operation is attempted from the slot 579 * where the private key resides. 580 * If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and 581 * SECSuccess is returned. In all other cases but one (*pcanbypass) is 582 * set to FALSE and SECFailure is returned. 583 * In that last case Derive() has been called successfully but the MS is null, 584 * CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the 585 * arguments were all valid but the slot cannot be bypassed. 586 */ 587 588 /* XXX Add SSL_CBP_TLS1_1 and test it in protocolmask when setting isTLS. */ 589 590 SECStatus 591 SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey, 592 PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites, 593 PRBool *pcanbypass, void *pwArg) 594 { 595 #ifdef NO_PKCS11_BYPASS 596 if (!pcanbypass) { 597 PORT_SetError(SEC_ERROR_INVALID_ARGS); 598 return SECFailure; 599 } 600 *pcanbypass = PR_FALSE; 601 return SECSuccess; 602 #else 603 SECStatus rv; 604 int i; 605 PRUint16 suite; 606 PK11SymKey * pms = NULL; 607 SECKEYPublicKey * srvPubkey = NULL; 608 KeyType privKeytype; 609 PK11SlotInfo * slot = NULL; 610 SECItem param; 611 CK_VERSION version; 612 CK_MECHANISM_TYPE mechanism_array[2]; 613 SECItem enc_pms = {siBuffer, NULL, 0}; 614 PRBool isTLS = PR_FALSE; 615 SSLCipherSuiteInfo csdef; 616 PRBool testrsa = PR_FALSE; 617 PRBool testrsa_export = PR_FALSE; 618 PRBool testecdh = PR_FALSE; 619 PRBool testecdhe = PR_FALSE; 620 #ifdef NSS_ENABLE_ECC 621 SECKEYECParams ecParams = { siBuffer, NULL, 0 }; 622 #endif 623 624 if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) { 625 PORT_SetError(SEC_ERROR_INVALID_ARGS); 626 return SECFailure; 627 } 628 629 srvPubkey = CERT_ExtractPublicKey(cert); 630 if (!srvPubkey) 631 return SECFailure; 632 633 *pcanbypass = PR_TRUE; 634 rv = SECFailure; 635 636 /* determine which KEAs to test */ 637 /* 0 (SSL_NULL_WITH_NULL_NULL) is used as a list terminator because 638 * SSL3 and TLS specs forbid negotiating that cipher suite number. 639 */ 640 for (i=0; i < nsuites && (suite = *ciphersuites++) != 0; i++) { 641 /* skip SSL2 cipher suites and ones NSS doesn't support */ 642 if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess 643 || SSL_IS_SSL2_CIPHER(suite) ) 644 continue; 645 switch (csdef.keaType) { 646 case ssl_kea_rsa: 647 switch (csdef.cipherSuite) { 648 case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA: 649 case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA: 650 case SSL_RSA_EXPORT_WITH_RC4_40_MD5: 651 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: 652 testrsa_export = PR_TRUE; 653 } 654 if (!testrsa_export) 655 testrsa = PR_TRUE; 656 break; 657 case ssl_kea_ecdh: 658 if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */ 659 testecdhe = PR_TRUE; 660 else 661 testecdh = PR_TRUE; 662 break; 663 case ssl_kea_dh: 664 /* this is actually DHE */ 665 default: 666 continue; 667 } 668 } 669 670 /* For each protocol try to derive and extract an MS. 671 * Failure of function any function except MS extract means 672 * continue with the next cipher test. Stop testing when the list is 673 * exhausted or when the first MS extract--not derive--fails. 674 */ 675 privKeytype = SECKEY_GetPrivateKeyType(srvPrivkey); 676 protocolmask &= SSL_CBP_SSL3|SSL_CBP_TLS1_0; 677 while (protocolmask) { 678 if (protocolmask & SSL_CBP_SSL3) { 679 isTLS = PR_FALSE; 680 protocolmask ^= SSL_CBP_SSL3; 681 } else { 682 isTLS = PR_TRUE; 683 protocolmask ^= SSL_CBP_TLS1_0; 684 } 685 686 if (privKeytype == rsaKey && testrsa_export) { 687 if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) { 688 *pcanbypass = PR_FALSE; 689 rv = SECSuccess; 690 break; 691 } else 692 testrsa = PR_TRUE; 693 } 694 for (; privKeytype == rsaKey && testrsa; ) { 695 /* TLS_RSA */ 696 unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH]; 697 unsigned int outLen = 0; 698 CK_MECHANISM_TYPE target; 699 SECStatus irv; 700 701 mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN; 702 mechanism_array[1] = CKM_RSA_PKCS; 703 704 slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg); 705 if (slot == NULL) { 706 PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND); 707 break; 708 } 709 710 /* Generate the pre-master secret ... (client side) */ 711 version.major = 3 /*MSB(clientHelloVersion)*/; 712 version.minor = 0 /*LSB(clientHelloVersion)*/; 713 param.data = (unsigned char *)&version; 714 param.len = sizeof version; 715 pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, ¶m, 0, pwArg); 716 PK11_FreeSlot(slot); 717 if (!pms) 718 break; 719 /* now wrap it */ 720 enc_pms.len = SECKEY_PublicKeyStrength(srvPubkey); 721 enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len); 722 if (enc_pms.data == NULL) { 723 PORT_SetError(PR_OUT_OF_MEMORY_ERROR); 724 break; 725 } 726 irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms); 727 if (irv != SECSuccess) 728 break; 729 PK11_FreeSymKey(pms); 730 pms = NULL; 731 /* now do the server side--check the triple bypass first */ 732 rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen, 733 sizeof rsaPmsBuf, 734 (unsigned char *)enc_pms.data, 735 enc_pms.len); 736 /* if decrypt worked we're done with the RSA test */ 737 if (rv == SECSuccess) { 738 *pcanbypass = PR_TRUE; 739 break; 740 } 741 /* check for fallback to double bypass */ 742 target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE 743 : CKM_SSL3_MASTER_KEY_DERIVE; 744 pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms, 745 target, CKA_DERIVE, 0); 746 rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass); 747 if (rv == SECSuccess && *pcanbypass == PR_FALSE) 748 goto done; 749 break; 750 } 751 752 /* Check for NULL to avoid double free. 753 * SECItem_FreeItem sets data NULL in secitem.c#265 754 */ 755 if (enc_pms.data != NULL) { 756 SECITEM_FreeItem(&enc_pms, PR_FALSE); 757 } 758 #ifdef NSS_ENABLE_ECC 759 for (; (privKeytype == ecKey && ( testecdh || testecdhe)) || 760 (privKeytype == rsaKey && testecdhe); ) { 761 CK_MECHANISM_TYPE target; 762 SECKEYPublicKey *keapub = NULL; 763 SECKEYPrivateKey *keapriv; 764 SECKEYPublicKey *cpub = NULL; /* client's ephemeral ECDH keys */ 765 SECKEYPrivateKey *cpriv = NULL; 766 SECKEYECParams *pecParams = NULL; 767 768 if (privKeytype == ecKey && testecdhe) { 769 /* TLS_ECDHE_ECDSA */ 770 pecParams = &srvPubkey->u.ec.DEREncodedParams; 771 } else if (privKeytype == rsaKey && testecdhe) { 772 /* TLS_ECDHE_RSA */ 773 ECName ec_curve; 774 int serverKeyStrengthInBits; 775 int signatureKeyStrength; 776 int requiredECCbits; 777 778 /* find a curve of equivalent strength to the RSA key's */ 779 requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey); 780 if (requiredECCbits < 0) 781 break; 782 requiredECCbits *= BPB; 783 serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len; 784 if (srvPubkey->u.rsa.modulus.data[0] == 0) { 785 serverKeyStrengthInBits--; 786 } 787 /* convert to strength in bits */ 788 serverKeyStrengthInBits *= BPB; 789 790 signatureKeyStrength = 791 SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits); 792 793 if ( requiredECCbits > signatureKeyStrength ) 794 requiredECCbits = signatureKeyStrength; 795 796 ec_curve = 797 ssl3_GetCurveWithECKeyStrength( 798 ssl3_GetSupportedECCurveMask(NULL), 799 requiredECCbits); 800 rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams); 801 if (rv == SECFailure) { 802 break; 803 } 804 pecParams = &ecParams; 805 } 806 807 if (testecdhe) { 808 /* generate server's ephemeral keys */ 809 keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL); 810 if (!keapriv || !keapub) { 811 if (keapriv) 812 SECKEY_DestroyPrivateKey(keapriv); 813 if (keapub) 814 SECKEY_DestroyPublicKey(keapub); 815 PORT_SetError(SEC_ERROR_KEYGEN_FAIL); 816 rv = SECFailure; 817 break; 818 } 819 } else { 820 /* TLS_ECDH_ECDSA */ 821 keapub = srvPubkey; 822 keapriv = srvPrivkey; 823 pecParams = &srvPubkey->u.ec.DEREncodedParams; 824 } 825 826 /* perform client side ops */ 827 /* generate a pair of ephemeral keys using server's parms */ 828 cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL); 829 if (!cpriv || !cpub) { 830 if (testecdhe) { 831 SECKEY_DestroyPrivateKey(keapriv); 832 SECKEY_DestroyPublicKey(keapub); 833 } 834 PORT_SetError(SEC_ERROR_KEYGEN_FAIL); 835 rv = SECFailure; 836 break; 837 } 838 /* now do the server side */ 839 /* determine the PMS using client's public value */ 840 target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH 841 : CKM_SSL3_MASTER_KEY_DERIVE_DH; 842 pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL, 843 CKM_ECDH1_DERIVE, 844 target, 845 CKA_DERIVE, 0, CKD_NULL, NULL, NULL); 846 rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass); 847 SECKEY_DestroyPrivateKey(cpriv); 848 SECKEY_DestroyPublicKey(cpub); 849 if (testecdhe) { 850 SECKEY_DestroyPrivateKey(keapriv); 851 SECKEY_DestroyPublicKey(keapub); 852 } 853 if (rv == SECSuccess && *pcanbypass == PR_FALSE) 854 goto done; 855 break; 856 } 857 /* Check for NULL to avoid double free. */ 858 if (ecParams.data != NULL) { 859 PORT_Free(ecParams.data); 860 ecParams.data = NULL; 861 } 862 #endif /* NSS_ENABLE_ECC */ 863 if (pms) 864 PK11_FreeSymKey(pms); 865 } 866 867 /* *pcanbypass has been set */ 868 rv = SECSuccess; 869 870 done: 871 if (pms) 872 PK11_FreeSymKey(pms); 873 874 /* Check for NULL to avoid double free. 875 * SECItem_FreeItem sets data NULL in secitem.c#265 876 */ 877 if (enc_pms.data != NULL) { 878 SECITEM_FreeItem(&enc_pms, PR_FALSE); 879 } 880 #ifdef NSS_ENABLE_ECC 881 if (ecParams.data != NULL) { 882 PORT_Free(ecParams.data); 883 ecParams.data = NULL; 884 } 885 #endif /* NSS_ENABLE_ECC */ 886 887 if (srvPubkey) { 888 SECKEY_DestroyPublicKey(srvPubkey); 889 srvPubkey = NULL; 890 } 891 892 893 return rv; 894 #endif /* NO_PKCS11_BYPASS */ 895 } 896 897