| OLD | NEW |
| (Empty) |
| 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, pwAr
g); | |
| 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 | |
| OLD | NEW |