Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: net/third_party/nss/ssl/derive.c

Issue 1882433002: Removing NSS files and USE_OPENSSL flag (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/third_party/nss/ssl/authcert.c ('k') | net/third_party/nss/ssl/dhe-param.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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, &params, 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, &param, 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 }
OLDNEW
« no previous file with comments | « net/third_party/nss/ssl/authcert.c ('k') | net/third_party/nss/ssl/dhe-param.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698