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