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