1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/ssl/derive.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,896 @@ 1.4 +/* 1.5 + * Key Derivation that doesn't use PKCS11 1.6 + * 1.7 + * This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#include "ssl.h" /* prereq to sslimpl.h */ 1.12 +#include "certt.h" /* prereq to sslimpl.h */ 1.13 +#include "keythi.h" /* prereq to sslimpl.h */ 1.14 +#include "sslimpl.h" 1.15 +#ifndef NO_PKCS11_BYPASS 1.16 +#include "blapi.h" 1.17 +#endif 1.18 + 1.19 +#include "keyhi.h" 1.20 +#include "pk11func.h" 1.21 +#include "secasn1.h" 1.22 +#include "cert.h" 1.23 +#include "secmodt.h" 1.24 + 1.25 +#include "sslproto.h" 1.26 +#include "sslerr.h" 1.27 + 1.28 +#ifndef NO_PKCS11_BYPASS 1.29 +/* make this a macro! */ 1.30 +#ifdef NOT_A_MACRO 1.31 +static void 1.32 +buildSSLKey(unsigned char * keyBlock, unsigned int keyLen, SECItem * result, 1.33 + const char * label) 1.34 +{ 1.35 + result->type = siBuffer; 1.36 + result->data = keyBlock; 1.37 + result->len = keyLen; 1.38 + PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); 1.39 +} 1.40 +#else 1.41 +#define buildSSLKey(keyBlock, keyLen, result, label) \ 1.42 +{ \ 1.43 + (result)->type = siBuffer; \ 1.44 + (result)->data = keyBlock; \ 1.45 + (result)->len = keyLen; \ 1.46 + PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); \ 1.47 +} 1.48 +#endif 1.49 + 1.50 +/* 1.51 + * SSL Key generation given pre master secret 1.52 + */ 1.53 +#ifndef NUM_MIXERS 1.54 +#define NUM_MIXERS 9 1.55 +#endif 1.56 +static const char * const mixers[NUM_MIXERS] = { 1.57 + "A", 1.58 + "BB", 1.59 + "CCC", 1.60 + "DDDD", 1.61 + "EEEEE", 1.62 + "FFFFFF", 1.63 + "GGGGGGG", 1.64 + "HHHHHHHH", 1.65 + "IIIIIIIII" 1.66 +}; 1.67 + 1.68 + 1.69 +SECStatus 1.70 +ssl3_KeyAndMacDeriveBypass( 1.71 + ssl3CipherSpec * pwSpec, 1.72 + const unsigned char * cr, 1.73 + const unsigned char * sr, 1.74 + PRBool isTLS, 1.75 + PRBool isExport) 1.76 +{ 1.77 + const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def; 1.78 + unsigned char * key_block = pwSpec->key_block; 1.79 + unsigned char * key_block2 = NULL; 1.80 + unsigned int block_bytes = 0; 1.81 + unsigned int block_needed = 0; 1.82 + unsigned int i; 1.83 + unsigned int keySize; /* actual size of cipher keys */ 1.84 + unsigned int effKeySize; /* effective size of cipher keys */ 1.85 + unsigned int macSize; /* size of MAC secret */ 1.86 + unsigned int IVSize; /* size of IV */ 1.87 + PRBool explicitIV = PR_FALSE; 1.88 + SECStatus rv = SECFailure; 1.89 + SECStatus status = SECSuccess; 1.90 + PRBool isFIPS = PR_FALSE; 1.91 + PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2; 1.92 + 1.93 + SECItem srcr; 1.94 + SECItem crsr; 1.95 + 1.96 + unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; 1.97 + unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; 1.98 + PRUint64 md5buf[22]; 1.99 + PRUint64 shabuf[40]; 1.100 + 1.101 +#define md5Ctx ((MD5Context *)md5buf) 1.102 +#define shaCtx ((SHA1Context *)shabuf) 1.103 + 1.104 + static const SECItem zed = { siBuffer, NULL, 0 }; 1.105 + 1.106 + if (pwSpec->msItem.data == NULL || 1.107 + pwSpec->msItem.len != SSL3_MASTER_SECRET_LENGTH) { 1.108 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.109 + return rv; 1.110 + } 1.111 + 1.112 + PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data, 1.113 + pwSpec->msItem.len)); 1.114 + 1.115 + /* figure out how much is needed */ 1.116 + macSize = pwSpec->mac_size; 1.117 + keySize = cipher_def->key_size; 1.118 + effKeySize = cipher_def->secret_key_size; 1.119 + IVSize = cipher_def->iv_size; 1.120 + if (keySize == 0) { 1.121 + effKeySize = IVSize = 0; /* only MACing */ 1.122 + } 1.123 + if (cipher_def->type == type_block && 1.124 + pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { 1.125 + /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */ 1.126 + explicitIV = PR_TRUE; 1.127 + } 1.128 + block_needed = 1.129 + 2 * (macSize + effKeySize + ((!isExport && !explicitIV) * IVSize)); 1.130 + 1.131 + /* 1.132 + * clear out our returned keys so we can recover on failure 1.133 + */ 1.134 + pwSpec->client.write_key_item = zed; 1.135 + pwSpec->client.write_mac_key_item = zed; 1.136 + pwSpec->server.write_key_item = zed; 1.137 + pwSpec->server.write_mac_key_item = zed; 1.138 + 1.139 + /* initialize the server random, client random block */ 1.140 + srcr.type = siBuffer; 1.141 + srcr.data = srcrdata; 1.142 + srcr.len = sizeof srcrdata; 1.143 + PORT_Memcpy(srcrdata, sr, SSL3_RANDOM_LENGTH); 1.144 + PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, cr, SSL3_RANDOM_LENGTH); 1.145 + 1.146 + /* initialize the client random, server random block */ 1.147 + crsr.type = siBuffer; 1.148 + crsr.data = crsrdata; 1.149 + crsr.len = sizeof crsrdata; 1.150 + PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH); 1.151 + PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH); 1.152 + PRINT_BUF(100, (NULL, "Key & MAC CRSR", crsr.data, crsr.len)); 1.153 + 1.154 + /* 1.155 + * generate the key material: 1.156 + */ 1.157 + if (isTLS) { 1.158 + SECItem keyblk; 1.159 + 1.160 + keyblk.type = siBuffer; 1.161 + keyblk.data = key_block; 1.162 + keyblk.len = block_needed; 1.163 + 1.164 + if (isTLS12) { 1.165 + status = TLS_P_hash(HASH_AlgSHA256, &pwSpec->msItem, 1.166 + "key expansion", &srcr, &keyblk, isFIPS); 1.167 + } else { 1.168 + status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk, 1.169 + isFIPS); 1.170 + } 1.171 + if (status != SECSuccess) { 1.172 + goto key_and_mac_derive_fail; 1.173 + } 1.174 + block_bytes = keyblk.len; 1.175 + } else { 1.176 + /* key_block = 1.177 + * MD5(master_secret + SHA('A' + master_secret + 1.178 + * ServerHello.random + ClientHello.random)) + 1.179 + * MD5(master_secret + SHA('BB' + master_secret + 1.180 + * ServerHello.random + ClientHello.random)) + 1.181 + * MD5(master_secret + SHA('CCC' + master_secret + 1.182 + * ServerHello.random + ClientHello.random)) + 1.183 + * [...]; 1.184 + */ 1.185 + unsigned int made = 0; 1.186 + for (i = 0; made < block_needed && i < NUM_MIXERS; ++i) { 1.187 + unsigned int outLen; 1.188 + unsigned char sha_out[SHA1_LENGTH]; 1.189 + 1.190 + SHA1_Begin(shaCtx); 1.191 + SHA1_Update(shaCtx, (unsigned char*)(mixers[i]), i+1); 1.192 + SHA1_Update(shaCtx, pwSpec->msItem.data, pwSpec->msItem.len); 1.193 + SHA1_Update(shaCtx, srcr.data, srcr.len); 1.194 + SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH); 1.195 + PORT_Assert(outLen == SHA1_LENGTH); 1.196 + 1.197 + MD5_Begin(md5Ctx); 1.198 + MD5_Update(md5Ctx, pwSpec->msItem.data, pwSpec->msItem.len); 1.199 + MD5_Update(md5Ctx, sha_out, outLen); 1.200 + MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH); 1.201 + PORT_Assert(outLen == MD5_LENGTH); 1.202 + made += MD5_LENGTH; 1.203 + } 1.204 + block_bytes = made; 1.205 + } 1.206 + PORT_Assert(block_bytes >= block_needed); 1.207 + PORT_Assert(block_bytes <= sizeof pwSpec->key_block); 1.208 + PRINT_BUF(100, (NULL, "key block", key_block, block_bytes)); 1.209 + 1.210 + /* 1.211 + * Put the key material where it goes. 1.212 + */ 1.213 + key_block2 = key_block + block_bytes; 1.214 + i = 0; /* now shows how much consumed */ 1.215 + 1.216 + /* 1.217 + * The key_block is partitioned as follows: 1.218 + * client_write_MAC_secret[CipherSpec.hash_size] 1.219 + */ 1.220 + buildSSLKey(&key_block[i],macSize, &pwSpec->client.write_mac_key_item, \ 1.221 + "Client Write MAC Secret"); 1.222 + i += macSize; 1.223 + 1.224 + /* 1.225 + * server_write_MAC_secret[CipherSpec.hash_size] 1.226 + */ 1.227 + buildSSLKey(&key_block[i],macSize, &pwSpec->server.write_mac_key_item, \ 1.228 + "Server Write MAC Secret"); 1.229 + i += macSize; 1.230 + 1.231 + if (!keySize) { 1.232 + /* only MACing */ 1.233 + buildSSLKey(NULL, 0, &pwSpec->client.write_key_item, \ 1.234 + "Client Write Key (MAC only)"); 1.235 + buildSSLKey(NULL, 0, &pwSpec->server.write_key_item, \ 1.236 + "Server Write Key (MAC only)"); 1.237 + buildSSLKey(NULL, 0, &pwSpec->client.write_iv_item, \ 1.238 + "Client Write IV (MAC only)"); 1.239 + buildSSLKey(NULL, 0, &pwSpec->server.write_iv_item, \ 1.240 + "Server Write IV (MAC only)"); 1.241 + } else if (!isExport) { 1.242 + /* 1.243 + ** Generate Domestic write keys and IVs. 1.244 + ** client_write_key[CipherSpec.key_material] 1.245 + */ 1.246 + buildSSLKey(&key_block[i], keySize, &pwSpec->client.write_key_item, \ 1.247 + "Domestic Client Write Key"); 1.248 + i += keySize; 1.249 + 1.250 + /* 1.251 + ** server_write_key[CipherSpec.key_material] 1.252 + */ 1.253 + buildSSLKey(&key_block[i], keySize, &pwSpec->server.write_key_item, \ 1.254 + "Domestic Server Write Key"); 1.255 + i += keySize; 1.256 + 1.257 + if (IVSize > 0) { 1.258 + if (explicitIV) { 1.259 + static unsigned char zero_block[32]; 1.260 + PORT_Assert(IVSize <= sizeof zero_block); 1.261 + buildSSLKey(&zero_block[0], IVSize, \ 1.262 + &pwSpec->client.write_iv_item, \ 1.263 + "Domestic Client Write IV"); 1.264 + buildSSLKey(&zero_block[0], IVSize, \ 1.265 + &pwSpec->server.write_iv_item, \ 1.266 + "Domestic Server Write IV"); 1.267 + } else { 1.268 + /* 1.269 + ** client_write_IV[CipherSpec.IV_size] 1.270 + */ 1.271 + buildSSLKey(&key_block[i], IVSize, \ 1.272 + &pwSpec->client.write_iv_item, \ 1.273 + "Domestic Client Write IV"); 1.274 + i += IVSize; 1.275 + 1.276 + /* 1.277 + ** server_write_IV[CipherSpec.IV_size] 1.278 + */ 1.279 + buildSSLKey(&key_block[i], IVSize, \ 1.280 + &pwSpec->server.write_iv_item, \ 1.281 + "Domestic Server Write IV"); 1.282 + i += IVSize; 1.283 + } 1.284 + } 1.285 + PORT_Assert(i <= block_bytes); 1.286 + } else if (!isTLS) { 1.287 + /* 1.288 + ** Generate SSL3 Export write keys and IVs. 1.289 + */ 1.290 + unsigned int outLen; 1.291 + 1.292 + /* 1.293 + ** client_write_key[CipherSpec.key_material] 1.294 + ** final_client_write_key = MD5(client_write_key + 1.295 + ** ClientHello.random + ServerHello.random); 1.296 + */ 1.297 + MD5_Begin(md5Ctx); 1.298 + MD5_Update(md5Ctx, &key_block[i], effKeySize); 1.299 + MD5_Update(md5Ctx, crsr.data, crsr.len); 1.300 + MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); 1.301 + i += effKeySize; 1.302 + buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item, \ 1.303 + "SSL3 Export Client Write Key"); 1.304 + key_block2 += keySize; 1.305 + 1.306 + /* 1.307 + ** server_write_key[CipherSpec.key_material] 1.308 + ** final_server_write_key = MD5(server_write_key + 1.309 + ** ServerHello.random + ClientHello.random); 1.310 + */ 1.311 + MD5_Begin(md5Ctx); 1.312 + MD5_Update(md5Ctx, &key_block[i], effKeySize); 1.313 + MD5_Update(md5Ctx, srcr.data, srcr.len); 1.314 + MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); 1.315 + i += effKeySize; 1.316 + buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item, \ 1.317 + "SSL3 Export Server Write Key"); 1.318 + key_block2 += keySize; 1.319 + PORT_Assert(i <= block_bytes); 1.320 + 1.321 + if (IVSize) { 1.322 + /* 1.323 + ** client_write_IV = 1.324 + ** MD5(ClientHello.random + ServerHello.random); 1.325 + */ 1.326 + MD5_Begin(md5Ctx); 1.327 + MD5_Update(md5Ctx, crsr.data, crsr.len); 1.328 + MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); 1.329 + buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item, \ 1.330 + "SSL3 Export Client Write IV"); 1.331 + key_block2 += IVSize; 1.332 + 1.333 + /* 1.334 + ** server_write_IV = 1.335 + ** MD5(ServerHello.random + ClientHello.random); 1.336 + */ 1.337 + MD5_Begin(md5Ctx); 1.338 + MD5_Update(md5Ctx, srcr.data, srcr.len); 1.339 + MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); 1.340 + buildSSLKey(key_block2, IVSize, &pwSpec->server.write_iv_item, \ 1.341 + "SSL3 Export Server Write IV"); 1.342 + key_block2 += IVSize; 1.343 + } 1.344 + 1.345 + PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block); 1.346 + } else { 1.347 + /* 1.348 + ** Generate TLS Export write keys and IVs. 1.349 + */ 1.350 + SECItem secret ; 1.351 + SECItem keyblk ; 1.352 + 1.353 + secret.type = siBuffer; 1.354 + keyblk.type = siBuffer; 1.355 + /* 1.356 + ** client_write_key[CipherSpec.key_material] 1.357 + ** final_client_write_key = PRF(client_write_key, 1.358 + ** "client write key", 1.359 + ** client_random + server_random); 1.360 + */ 1.361 + secret.data = &key_block[i]; 1.362 + secret.len = effKeySize; 1.363 + i += effKeySize; 1.364 + keyblk.data = key_block2; 1.365 + keyblk.len = keySize; 1.366 + status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS); 1.367 + if (status != SECSuccess) { 1.368 + goto key_and_mac_derive_fail; 1.369 + } 1.370 + buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item, \ 1.371 + "TLS Export Client Write Key"); 1.372 + key_block2 += keySize; 1.373 + 1.374 + /* 1.375 + ** server_write_key[CipherSpec.key_material] 1.376 + ** final_server_write_key = PRF(server_write_key, 1.377 + ** "server write key", 1.378 + ** client_random + server_random); 1.379 + */ 1.380 + secret.data = &key_block[i]; 1.381 + secret.len = effKeySize; 1.382 + i += effKeySize; 1.383 + keyblk.data = key_block2; 1.384 + keyblk.len = keySize; 1.385 + status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS); 1.386 + if (status != SECSuccess) { 1.387 + goto key_and_mac_derive_fail; 1.388 + } 1.389 + buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item, \ 1.390 + "TLS Export Server Write Key"); 1.391 + key_block2 += keySize; 1.392 + 1.393 + /* 1.394 + ** iv_block = PRF("", "IV block", client_random + server_random); 1.395 + ** client_write_IV[SecurityParameters.IV_size] 1.396 + ** server_write_IV[SecurityParameters.IV_size] 1.397 + */ 1.398 + if (IVSize) { 1.399 + secret.data = NULL; 1.400 + secret.len = 0; 1.401 + keyblk.data = key_block2; 1.402 + keyblk.len = 2 * IVSize; 1.403 + status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS); 1.404 + if (status != SECSuccess) { 1.405 + goto key_and_mac_derive_fail; 1.406 + } 1.407 + buildSSLKey(key_block2, IVSize, \ 1.408 + &pwSpec->client.write_iv_item, \ 1.409 + "TLS Export Client Write IV"); 1.410 + buildSSLKey(key_block2 + IVSize, IVSize, \ 1.411 + &pwSpec->server.write_iv_item, \ 1.412 + "TLS Export Server Write IV"); 1.413 + key_block2 += 2 * IVSize; 1.414 + } 1.415 + PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block); 1.416 + } 1.417 + rv = SECSuccess; 1.418 + 1.419 +key_and_mac_derive_fail: 1.420 + 1.421 + MD5_DestroyContext(md5Ctx, PR_FALSE); 1.422 + SHA1_DestroyContext(shaCtx, PR_FALSE); 1.423 + 1.424 + if (rv != SECSuccess) { 1.425 + PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); 1.426 + } 1.427 + 1.428 + return rv; 1.429 +} 1.430 + 1.431 + 1.432 +/* derive the Master Secret from the PMS */ 1.433 +/* Presently, this is only done wtih RSA PMS, and only on the server side, 1.434 + * so isRSA is always true. 1.435 + */ 1.436 +SECStatus 1.437 +ssl3_MasterKeyDeriveBypass( 1.438 + ssl3CipherSpec * pwSpec, 1.439 + const unsigned char * cr, 1.440 + const unsigned char * sr, 1.441 + const SECItem * pms, 1.442 + PRBool isTLS, 1.443 + PRBool isRSA) 1.444 +{ 1.445 + unsigned char * key_block = pwSpec->key_block; 1.446 + SECStatus rv = SECSuccess; 1.447 + PRBool isFIPS = PR_FALSE; 1.448 + PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2; 1.449 + 1.450 + SECItem crsr; 1.451 + 1.452 + unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; 1.453 + PRUint64 md5buf[22]; 1.454 + PRUint64 shabuf[40]; 1.455 + 1.456 +#define md5Ctx ((MD5Context *)md5buf) 1.457 +#define shaCtx ((SHA1Context *)shabuf) 1.458 + 1.459 + /* first do the consistancy checks */ 1.460 + if (isRSA) { 1.461 + PORT_Assert(pms->len == SSL3_RSA_PMS_LENGTH); 1.462 + if (pms->len != SSL3_RSA_PMS_LENGTH) { 1.463 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.464 + return SECFailure; 1.465 + } 1.466 + /* caller must test PMS version for rollback */ 1.467 + } 1.468 + 1.469 + /* initialize the client random, server random block */ 1.470 + crsr.type = siBuffer; 1.471 + crsr.data = crsrdata; 1.472 + crsr.len = sizeof crsrdata; 1.473 + PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH); 1.474 + PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH); 1.475 + PRINT_BUF(100, (NULL, "Master Secret CRSR", crsr.data, crsr.len)); 1.476 + 1.477 + /* finally do the key gen */ 1.478 + if (isTLS) { 1.479 + SECItem master = { siBuffer, NULL, 0 }; 1.480 + 1.481 + master.data = key_block; 1.482 + master.len = SSL3_MASTER_SECRET_LENGTH; 1.483 + 1.484 + if (isTLS12) { 1.485 + rv = TLS_P_hash(HASH_AlgSHA256, pms, "master secret", &crsr, 1.486 + &master, isFIPS); 1.487 + } else { 1.488 + rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS); 1.489 + } 1.490 + if (rv != SECSuccess) { 1.491 + PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); 1.492 + } 1.493 + } else { 1.494 + int i; 1.495 + unsigned int made = 0; 1.496 + for (i = 0; i < 3; i++) { 1.497 + unsigned int outLen; 1.498 + unsigned char sha_out[SHA1_LENGTH]; 1.499 + 1.500 + SHA1_Begin(shaCtx); 1.501 + SHA1_Update(shaCtx, (unsigned char*) mixers[i], i+1); 1.502 + SHA1_Update(shaCtx, pms->data, pms->len); 1.503 + SHA1_Update(shaCtx, crsr.data, crsr.len); 1.504 + SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH); 1.505 + PORT_Assert(outLen == SHA1_LENGTH); 1.506 + 1.507 + MD5_Begin(md5Ctx); 1.508 + MD5_Update(md5Ctx, pms->data, pms->len); 1.509 + MD5_Update(md5Ctx, sha_out, outLen); 1.510 + MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH); 1.511 + PORT_Assert(outLen == MD5_LENGTH); 1.512 + made += outLen; 1.513 + } 1.514 + } 1.515 + 1.516 + /* store the results */ 1.517 + PORT_Memcpy(pwSpec->raw_master_secret, key_block, 1.518 + SSL3_MASTER_SECRET_LENGTH); 1.519 + pwSpec->msItem.data = pwSpec->raw_master_secret; 1.520 + pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH; 1.521 + PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data, 1.522 + pwSpec->msItem.len)); 1.523 + 1.524 + return rv; 1.525 +} 1.526 + 1.527 +static SECStatus 1.528 +ssl_canExtractMS(PK11SymKey *pms, PRBool isTLS, PRBool isDH, PRBool *pcbp) 1.529 +{ SECStatus rv; 1.530 + PK11SymKey * ms = NULL; 1.531 + SECItem params = {siBuffer, NULL, 0}; 1.532 + CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params; 1.533 + unsigned char rand[SSL3_RANDOM_LENGTH]; 1.534 + CK_VERSION pms_version; 1.535 + CK_MECHANISM_TYPE master_derive; 1.536 + CK_MECHANISM_TYPE key_derive; 1.537 + CK_FLAGS keyFlags; 1.538 + 1.539 + if (pms == NULL) 1.540 + return(SECFailure); 1.541 + 1.542 + PORT_Memset(rand, 0, SSL3_RANDOM_LENGTH); 1.543 + 1.544 + if (isTLS) { 1.545 + if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH; 1.546 + else master_derive = CKM_TLS_MASTER_KEY_DERIVE; 1.547 + key_derive = CKM_TLS_KEY_AND_MAC_DERIVE; 1.548 + keyFlags = CKF_SIGN | CKF_VERIFY; 1.549 + } else { 1.550 + if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH; 1.551 + else master_derive = CKM_SSL3_MASTER_KEY_DERIVE; 1.552 + key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE; 1.553 + keyFlags = 0; 1.554 + } 1.555 + 1.556 + master_params.pVersion = &pms_version; 1.557 + master_params.RandomInfo.pClientRandom = rand; 1.558 + master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH; 1.559 + master_params.RandomInfo.pServerRandom = rand; 1.560 + master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH; 1.561 + 1.562 + params.data = (unsigned char *) &master_params; 1.563 + params.len = sizeof master_params; 1.564 + 1.565 + ms = PK11_DeriveWithFlags(pms, master_derive, ¶ms, key_derive, 1.566 + CKA_DERIVE, 0, keyFlags); 1.567 + if (ms == NULL) 1.568 + return(SECFailure); 1.569 + 1.570 + rv = PK11_ExtractKeyValue(ms); 1.571 + *pcbp = (rv == SECSuccess); 1.572 + PK11_FreeSymKey(ms); 1.573 + 1.574 + return(rv); 1.575 + 1.576 +} 1.577 +#endif /* !NO_PKCS11_BYPASS */ 1.578 + 1.579 +/* Check the key exchange algorithm for each cipher in the list to see if 1.580 + * a master secret key can be extracted. If the KEA will use keys from the 1.581 + * specified cert make sure the extract operation is attempted from the slot 1.582 + * where the private key resides. 1.583 + * If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and 1.584 + * SECSuccess is returned. In all other cases but one (*pcanbypass) is 1.585 + * set to FALSE and SECFailure is returned. 1.586 + * In that last case Derive() has been called successfully but the MS is null, 1.587 + * CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the 1.588 + * arguments were all valid but the slot cannot be bypassed. 1.589 + */ 1.590 + 1.591 +/* XXX Add SSL_CBP_TLS1_1 and test it in protocolmask when setting isTLS. */ 1.592 + 1.593 +SECStatus 1.594 +SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey, 1.595 + PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites, 1.596 + PRBool *pcanbypass, void *pwArg) 1.597 +{ 1.598 +#ifdef NO_PKCS11_BYPASS 1.599 + if (!pcanbypass) { 1.600 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.601 + return SECFailure; 1.602 + } 1.603 + *pcanbypass = PR_FALSE; 1.604 + return SECSuccess; 1.605 +#else 1.606 + SECStatus rv; 1.607 + int i; 1.608 + PRUint16 suite; 1.609 + PK11SymKey * pms = NULL; 1.610 + SECKEYPublicKey * srvPubkey = NULL; 1.611 + KeyType privKeytype; 1.612 + PK11SlotInfo * slot = NULL; 1.613 + SECItem param; 1.614 + CK_VERSION version; 1.615 + CK_MECHANISM_TYPE mechanism_array[2]; 1.616 + SECItem enc_pms = {siBuffer, NULL, 0}; 1.617 + PRBool isTLS = PR_FALSE; 1.618 + SSLCipherSuiteInfo csdef; 1.619 + PRBool testrsa = PR_FALSE; 1.620 + PRBool testrsa_export = PR_FALSE; 1.621 + PRBool testecdh = PR_FALSE; 1.622 + PRBool testecdhe = PR_FALSE; 1.623 +#ifndef NSS_DISABLE_ECC 1.624 + SECKEYECParams ecParams = { siBuffer, NULL, 0 }; 1.625 +#endif 1.626 + 1.627 + if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) { 1.628 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.629 + return SECFailure; 1.630 + } 1.631 + 1.632 + srvPubkey = CERT_ExtractPublicKey(cert); 1.633 + if (!srvPubkey) 1.634 + return SECFailure; 1.635 + 1.636 + *pcanbypass = PR_TRUE; 1.637 + rv = SECFailure; 1.638 + 1.639 + /* determine which KEAs to test */ 1.640 + /* 0 (TLS_NULL_WITH_NULL_NULL) is used as a list terminator because 1.641 + * SSL3 and TLS specs forbid negotiating that cipher suite number. 1.642 + */ 1.643 + for (i=0; i < nsuites && (suite = *ciphersuites++) != 0; i++) { 1.644 + /* skip SSL2 cipher suites and ones NSS doesn't support */ 1.645 + if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess 1.646 + || SSL_IS_SSL2_CIPHER(suite) ) 1.647 + continue; 1.648 + switch (csdef.keaType) { 1.649 + case ssl_kea_rsa: 1.650 + switch (csdef.cipherSuite) { 1.651 + case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA: 1.652 + case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA: 1.653 + case TLS_RSA_EXPORT_WITH_RC4_40_MD5: 1.654 + case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5: 1.655 + testrsa_export = PR_TRUE; 1.656 + } 1.657 + if (!testrsa_export) 1.658 + testrsa = PR_TRUE; 1.659 + break; 1.660 + case ssl_kea_ecdh: 1.661 + if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */ 1.662 + testecdhe = PR_TRUE; 1.663 + else 1.664 + testecdh = PR_TRUE; 1.665 + break; 1.666 + case ssl_kea_dh: 1.667 + /* this is actually DHE */ 1.668 + default: 1.669 + continue; 1.670 + } 1.671 + } 1.672 + 1.673 + /* For each protocol try to derive and extract an MS. 1.674 + * Failure of function any function except MS extract means 1.675 + * continue with the next cipher test. Stop testing when the list is 1.676 + * exhausted or when the first MS extract--not derive--fails. 1.677 + */ 1.678 + privKeytype = SECKEY_GetPrivateKeyType(srvPrivkey); 1.679 + protocolmask &= SSL_CBP_SSL3|SSL_CBP_TLS1_0; 1.680 + while (protocolmask) { 1.681 + if (protocolmask & SSL_CBP_SSL3) { 1.682 + isTLS = PR_FALSE; 1.683 + protocolmask ^= SSL_CBP_SSL3; 1.684 + } else { 1.685 + isTLS = PR_TRUE; 1.686 + protocolmask ^= SSL_CBP_TLS1_0; 1.687 + } 1.688 + 1.689 + if (privKeytype == rsaKey && testrsa_export) { 1.690 + if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) { 1.691 + *pcanbypass = PR_FALSE; 1.692 + rv = SECSuccess; 1.693 + break; 1.694 + } else 1.695 + testrsa = PR_TRUE; 1.696 + } 1.697 + for (; privKeytype == rsaKey && testrsa; ) { 1.698 + /* TLS_RSA */ 1.699 + unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH]; 1.700 + unsigned int outLen = 0; 1.701 + CK_MECHANISM_TYPE target; 1.702 + SECStatus irv; 1.703 + 1.704 + mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN; 1.705 + mechanism_array[1] = CKM_RSA_PKCS; 1.706 + 1.707 + slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg); 1.708 + if (slot == NULL) { 1.709 + PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND); 1.710 + break; 1.711 + } 1.712 + 1.713 + /* Generate the pre-master secret ... (client side) */ 1.714 + version.major = 3 /*MSB(clientHelloVersion)*/; 1.715 + version.minor = 0 /*LSB(clientHelloVersion)*/; 1.716 + param.data = (unsigned char *)&version; 1.717 + param.len = sizeof version; 1.718 + pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, ¶m, 0, pwArg); 1.719 + PK11_FreeSlot(slot); 1.720 + if (!pms) 1.721 + break; 1.722 + /* now wrap it */ 1.723 + enc_pms.len = SECKEY_PublicKeyStrength(srvPubkey); 1.724 + enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len); 1.725 + if (enc_pms.data == NULL) { 1.726 + PORT_SetError(PR_OUT_OF_MEMORY_ERROR); 1.727 + break; 1.728 + } 1.729 + irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms); 1.730 + if (irv != SECSuccess) 1.731 + break; 1.732 + PK11_FreeSymKey(pms); 1.733 + pms = NULL; 1.734 + /* now do the server side--check the triple bypass first */ 1.735 + rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen, 1.736 + sizeof rsaPmsBuf, 1.737 + (unsigned char *)enc_pms.data, 1.738 + enc_pms.len); 1.739 + /* if decrypt worked we're done with the RSA test */ 1.740 + if (rv == SECSuccess) { 1.741 + *pcanbypass = PR_TRUE; 1.742 + break; 1.743 + } 1.744 + /* check for fallback to double bypass */ 1.745 + target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE 1.746 + : CKM_SSL3_MASTER_KEY_DERIVE; 1.747 + pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms, 1.748 + target, CKA_DERIVE, 0); 1.749 + rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass); 1.750 + if (rv == SECSuccess && *pcanbypass == PR_FALSE) 1.751 + goto done; 1.752 + break; 1.753 + } 1.754 + 1.755 + /* Check for NULL to avoid double free. 1.756 + * SECItem_FreeItem sets data NULL in secitem.c#265 1.757 + */ 1.758 + if (enc_pms.data != NULL) { 1.759 + SECITEM_FreeItem(&enc_pms, PR_FALSE); 1.760 + } 1.761 +#ifndef NSS_DISABLE_ECC 1.762 + for (; (privKeytype == ecKey && ( testecdh || testecdhe)) || 1.763 + (privKeytype == rsaKey && testecdhe); ) { 1.764 + CK_MECHANISM_TYPE target; 1.765 + SECKEYPublicKey *keapub = NULL; 1.766 + SECKEYPrivateKey *keapriv; 1.767 + SECKEYPublicKey *cpub = NULL; /* client's ephemeral ECDH keys */ 1.768 + SECKEYPrivateKey *cpriv = NULL; 1.769 + SECKEYECParams *pecParams = NULL; 1.770 + 1.771 + if (privKeytype == ecKey && testecdhe) { 1.772 + /* TLS_ECDHE_ECDSA */ 1.773 + pecParams = &srvPubkey->u.ec.DEREncodedParams; 1.774 + } else if (privKeytype == rsaKey && testecdhe) { 1.775 + /* TLS_ECDHE_RSA */ 1.776 + ECName ec_curve; 1.777 + int serverKeyStrengthInBits; 1.778 + int signatureKeyStrength; 1.779 + int requiredECCbits; 1.780 + 1.781 + /* find a curve of equivalent strength to the RSA key's */ 1.782 + requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey); 1.783 + if (requiredECCbits < 0) 1.784 + break; 1.785 + requiredECCbits *= BPB; 1.786 + serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len; 1.787 + if (srvPubkey->u.rsa.modulus.data[0] == 0) { 1.788 + serverKeyStrengthInBits--; 1.789 + } 1.790 + /* convert to strength in bits */ 1.791 + serverKeyStrengthInBits *= BPB; 1.792 + 1.793 + signatureKeyStrength = 1.794 + SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits); 1.795 + 1.796 + if ( requiredECCbits > signatureKeyStrength ) 1.797 + requiredECCbits = signatureKeyStrength; 1.798 + 1.799 + ec_curve = 1.800 + ssl3_GetCurveWithECKeyStrength( 1.801 + ssl3_GetSupportedECCurveMask(NULL), 1.802 + requiredECCbits); 1.803 + rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams); 1.804 + if (rv == SECFailure) { 1.805 + break; 1.806 + } 1.807 + pecParams = &ecParams; 1.808 + } 1.809 + 1.810 + if (testecdhe) { 1.811 + /* generate server's ephemeral keys */ 1.812 + keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL); 1.813 + if (!keapriv || !keapub) { 1.814 + if (keapriv) 1.815 + SECKEY_DestroyPrivateKey(keapriv); 1.816 + if (keapub) 1.817 + SECKEY_DestroyPublicKey(keapub); 1.818 + PORT_SetError(SEC_ERROR_KEYGEN_FAIL); 1.819 + rv = SECFailure; 1.820 + break; 1.821 + } 1.822 + } else { 1.823 + /* TLS_ECDH_ECDSA */ 1.824 + keapub = srvPubkey; 1.825 + keapriv = srvPrivkey; 1.826 + pecParams = &srvPubkey->u.ec.DEREncodedParams; 1.827 + } 1.828 + 1.829 + /* perform client side ops */ 1.830 + /* generate a pair of ephemeral keys using server's parms */ 1.831 + cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL); 1.832 + if (!cpriv || !cpub) { 1.833 + if (testecdhe) { 1.834 + SECKEY_DestroyPrivateKey(keapriv); 1.835 + SECKEY_DestroyPublicKey(keapub); 1.836 + } 1.837 + PORT_SetError(SEC_ERROR_KEYGEN_FAIL); 1.838 + rv = SECFailure; 1.839 + break; 1.840 + } 1.841 + /* now do the server side */ 1.842 + /* determine the PMS using client's public value */ 1.843 + target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH 1.844 + : CKM_SSL3_MASTER_KEY_DERIVE_DH; 1.845 + pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL, 1.846 + CKM_ECDH1_DERIVE, 1.847 + target, 1.848 + CKA_DERIVE, 0, CKD_NULL, NULL, NULL); 1.849 + rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass); 1.850 + SECKEY_DestroyPrivateKey(cpriv); 1.851 + SECKEY_DestroyPublicKey(cpub); 1.852 + if (testecdhe) { 1.853 + SECKEY_DestroyPrivateKey(keapriv); 1.854 + SECKEY_DestroyPublicKey(keapub); 1.855 + } 1.856 + if (rv == SECSuccess && *pcanbypass == PR_FALSE) 1.857 + goto done; 1.858 + break; 1.859 + } 1.860 + /* Check for NULL to avoid double free. */ 1.861 + if (ecParams.data != NULL) { 1.862 + PORT_Free(ecParams.data); 1.863 + ecParams.data = NULL; 1.864 + } 1.865 +#endif /* NSS_DISABLE_ECC */ 1.866 + if (pms) 1.867 + PK11_FreeSymKey(pms); 1.868 + } 1.869 + 1.870 + /* *pcanbypass has been set */ 1.871 + rv = SECSuccess; 1.872 + 1.873 + done: 1.874 + if (pms) 1.875 + PK11_FreeSymKey(pms); 1.876 + 1.877 + /* Check for NULL to avoid double free. 1.878 + * SECItem_FreeItem sets data NULL in secitem.c#265 1.879 + */ 1.880 + if (enc_pms.data != NULL) { 1.881 + SECITEM_FreeItem(&enc_pms, PR_FALSE); 1.882 + } 1.883 +#ifndef NSS_DISABLE_ECC 1.884 + if (ecParams.data != NULL) { 1.885 + PORT_Free(ecParams.data); 1.886 + ecParams.data = NULL; 1.887 + } 1.888 +#endif /* NSS_DISABLE_ECC */ 1.889 + 1.890 + if (srvPubkey) { 1.891 + SECKEY_DestroyPublicKey(srvPubkey); 1.892 + srvPubkey = NULL; 1.893 + } 1.894 + 1.895 + 1.896 + return rv; 1.897 +#endif /* NO_PKCS11_BYPASS */ 1.898 +} 1.899 +