Revert "Merged all Chromoting Host code into remoting_core.dll (Windows)."
[chromium-blink-merge.git] / net / third_party / nss / ssl / derive.c
blobda62682b1988a6b6e64eea36e8b8f7a92cacb31d
1 /*
2 * Key Derivation that doesn't use PKCS11
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 /* $Id: derive.c,v 1.16 2012/06/11 02:38:30 emaldona%redhat.com Exp $ */
9 #include "ssl.h" /* prereq to sslimpl.h */
10 #include "certt.h" /* prereq to sslimpl.h */
11 #include "keythi.h" /* prereq to sslimpl.h */
12 #include "sslimpl.h"
13 #ifndef NO_PKCS11_BYPASS
14 #include "blapi.h"
15 #endif
17 #include "keyhi.h"
18 #include "pk11func.h"
19 #include "secasn1.h"
20 #include "cert.h"
21 #include "secmodt.h"
23 #include "sslproto.h"
24 #include "sslerr.h"
26 #ifndef NO_PKCS11_BYPASS
27 /* make this a macro! */
28 #ifdef NOT_A_MACRO
29 static void
30 buildSSLKey(unsigned char * keyBlock, unsigned int keyLen, SECItem * result,
31 const char * label)
33 result->type = siBuffer;
34 result->data = keyBlock;
35 result->len = keyLen;
36 PRINT_BUF(100, (NULL, label, keyBlock, keyLen));
38 #else
39 #define buildSSLKey(keyBlock, keyLen, result, label) \
40 { \
41 (result)->type = siBuffer; \
42 (result)->data = keyBlock; \
43 (result)->len = keyLen; \
44 PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); \
46 #endif
49 * SSL Key generation given pre master secret
51 #ifndef NUM_MIXERS
52 #define NUM_MIXERS 9
53 #endif
54 static const char * const mixers[NUM_MIXERS] = {
55 "A",
56 "BB",
57 "CCC",
58 "DDDD",
59 "EEEEE",
60 "FFFFFF",
61 "GGGGGGG",
62 "HHHHHHHH",
63 "IIIIIIIII"
67 SECStatus
68 ssl3_KeyAndMacDeriveBypass(
69 ssl3CipherSpec * pwSpec,
70 const unsigned char * cr,
71 const unsigned char * sr,
72 PRBool isTLS,
73 PRBool isExport)
75 const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
76 unsigned char * key_block = pwSpec->key_block;
77 unsigned char * key_block2 = NULL;
78 unsigned int block_bytes = 0;
79 unsigned int block_needed = 0;
80 unsigned int i;
81 unsigned int keySize; /* actual size of cipher keys */
82 unsigned int effKeySize; /* effective size of cipher keys */
83 unsigned int macSize; /* size of MAC secret */
84 unsigned int IVSize; /* size of IV */
85 SECStatus rv = SECFailure;
86 SECStatus status = SECSuccess;
87 PRBool isFIPS = PR_FALSE;
89 SECItem srcr;
90 SECItem crsr;
92 unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
93 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
94 PRUint64 md5buf[22];
95 PRUint64 shabuf[40];
97 #define md5Ctx ((MD5Context *)md5buf)
98 #define shaCtx ((SHA1Context *)shabuf)
100 static const SECItem zed = { siBuffer, NULL, 0 };
102 if (pwSpec->msItem.data == NULL ||
103 pwSpec->msItem.len != SSL3_MASTER_SECRET_LENGTH) {
104 PORT_SetError(SEC_ERROR_INVALID_ARGS);
105 return rv;
108 PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data,
109 pwSpec->msItem.len));
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 */
119 block_needed = 2 * (macSize + effKeySize + ((!isExport) * IVSize));
122 * clear out our returned keys so we can recover on failure
124 pwSpec->client.write_key_item = zed;
125 pwSpec->client.write_mac_key_item = zed;
126 pwSpec->server.write_key_item = zed;
127 pwSpec->server.write_mac_key_item = zed;
129 /* initialize the server random, client random block */
130 srcr.type = siBuffer;
131 srcr.data = srcrdata;
132 srcr.len = sizeof srcrdata;
133 PORT_Memcpy(srcrdata, sr, SSL3_RANDOM_LENGTH);
134 PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, cr, SSL3_RANDOM_LENGTH);
136 /* initialize the client random, server random block */
137 crsr.type = siBuffer;
138 crsr.data = crsrdata;
139 crsr.len = sizeof crsrdata;
140 PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
141 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
142 PRINT_BUF(100, (NULL, "Key & MAC CRSR", crsr.data, crsr.len));
145 * generate the key material:
147 if (isTLS) {
148 SECItem keyblk;
150 keyblk.type = siBuffer;
151 keyblk.data = key_block;
152 keyblk.len = block_needed;
154 status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk,
155 isFIPS);
156 if (status != SECSuccess) {
157 goto key_and_mac_derive_fail;
159 block_bytes = keyblk.len;
160 } else {
161 /* key_block =
162 * MD5(master_secret + SHA('A' + master_secret +
163 * ServerHello.random + ClientHello.random)) +
164 * MD5(master_secret + SHA('BB' + master_secret +
165 * ServerHello.random + ClientHello.random)) +
166 * MD5(master_secret + SHA('CCC' + master_secret +
167 * ServerHello.random + ClientHello.random)) +
168 * [...];
170 unsigned int made = 0;
171 for (i = 0; made < block_needed && i < NUM_MIXERS; ++i) {
172 unsigned int outLen;
173 unsigned char sha_out[SHA1_LENGTH];
175 SHA1_Begin(shaCtx);
176 SHA1_Update(shaCtx, (unsigned char*)(mixers[i]), i+1);
177 SHA1_Update(shaCtx, pwSpec->msItem.data, pwSpec->msItem.len);
178 SHA1_Update(shaCtx, srcr.data, srcr.len);
179 SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH);
180 PORT_Assert(outLen == SHA1_LENGTH);
182 MD5_Begin(md5Ctx);
183 MD5_Update(md5Ctx, pwSpec->msItem.data, pwSpec->msItem.len);
184 MD5_Update(md5Ctx, sha_out, outLen);
185 MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
186 PORT_Assert(outLen == MD5_LENGTH);
187 made += MD5_LENGTH;
189 block_bytes = made;
191 PORT_Assert(block_bytes >= block_needed);
192 PORT_Assert(block_bytes <= sizeof pwSpec->key_block);
193 PRINT_BUF(100, (NULL, "key block", key_block, block_bytes));
196 * Put the key material where it goes.
198 key_block2 = key_block + block_bytes;
199 i = 0; /* now shows how much consumed */
202 * The key_block is partitioned as follows:
203 * client_write_MAC_secret[CipherSpec.hash_size]
205 buildSSLKey(&key_block[i],macSize, &pwSpec->client.write_mac_key_item, \
206 "Client Write MAC Secret");
207 i += macSize;
210 * server_write_MAC_secret[CipherSpec.hash_size]
212 buildSSLKey(&key_block[i],macSize, &pwSpec->server.write_mac_key_item, \
213 "Server Write MAC Secret");
214 i += macSize;
216 if (!keySize) {
217 /* only MACing */
218 buildSSLKey(NULL, 0, &pwSpec->client.write_key_item, \
219 "Client Write Key (MAC only)");
220 buildSSLKey(NULL, 0, &pwSpec->server.write_key_item, \
221 "Server Write Key (MAC only)");
222 buildSSLKey(NULL, 0, &pwSpec->client.write_iv_item, \
223 "Client Write IV (MAC only)");
224 buildSSLKey(NULL, 0, &pwSpec->server.write_iv_item, \
225 "Server Write IV (MAC only)");
226 } else if (!isExport) {
228 ** Generate Domestic write keys and IVs.
229 ** client_write_key[CipherSpec.key_material]
231 buildSSLKey(&key_block[i], keySize, &pwSpec->client.write_key_item, \
232 "Domestic Client Write Key");
233 i += keySize;
236 ** server_write_key[CipherSpec.key_material]
238 buildSSLKey(&key_block[i], keySize, &pwSpec->server.write_key_item, \
239 "Domestic Server Write Key");
240 i += keySize;
242 if (IVSize > 0) {
244 ** client_write_IV[CipherSpec.IV_size]
246 buildSSLKey(&key_block[i], IVSize, &pwSpec->client.write_iv_item, \
247 "Domestic Client Write IV");
248 i += IVSize;
251 ** server_write_IV[CipherSpec.IV_size]
253 buildSSLKey(&key_block[i], IVSize, &pwSpec->server.write_iv_item, \
254 "Domestic Server Write IV");
255 i += IVSize;
257 PORT_Assert(i <= block_bytes);
259 } else if (!isTLS) {
261 ** Generate SSL3 Export write keys and IVs.
263 unsigned int outLen;
266 ** client_write_key[CipherSpec.key_material]
267 ** final_client_write_key = MD5(client_write_key +
268 ** ClientHello.random + ServerHello.random);
270 MD5_Begin(md5Ctx);
271 MD5_Update(md5Ctx, &key_block[i], effKeySize);
272 MD5_Update(md5Ctx, crsr.data, crsr.len);
273 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
274 i += effKeySize;
275 buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item, \
276 "SSL3 Export Client Write Key");
277 key_block2 += keySize;
280 ** server_write_key[CipherSpec.key_material]
281 ** final_server_write_key = MD5(server_write_key +
282 ** ServerHello.random + ClientHello.random);
284 MD5_Begin(md5Ctx);
285 MD5_Update(md5Ctx, &key_block[i], effKeySize);
286 MD5_Update(md5Ctx, srcr.data, srcr.len);
287 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
288 i += effKeySize;
289 buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item, \
290 "SSL3 Export Server Write Key");
291 key_block2 += keySize;
292 PORT_Assert(i <= block_bytes);
294 if (IVSize) {
296 ** client_write_IV =
297 ** MD5(ClientHello.random + ServerHello.random);
299 MD5_Begin(md5Ctx);
300 MD5_Update(md5Ctx, crsr.data, crsr.len);
301 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
302 buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item, \
303 "SSL3 Export Client Write IV");
304 key_block2 += IVSize;
307 ** server_write_IV =
308 ** MD5(ServerHello.random + ClientHello.random);
310 MD5_Begin(md5Ctx);
311 MD5_Update(md5Ctx, srcr.data, srcr.len);
312 MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
313 buildSSLKey(key_block2, IVSize, &pwSpec->server.write_iv_item, \
314 "SSL3 Export Server Write IV");
315 key_block2 += IVSize;
318 PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
319 } else {
321 ** Generate TLS Export write keys and IVs.
323 SECItem secret ;
324 SECItem keyblk ;
326 secret.type = siBuffer;
327 keyblk.type = siBuffer;
329 ** client_write_key[CipherSpec.key_material]
330 ** final_client_write_key = PRF(client_write_key,
331 ** "client write key",
332 ** client_random + server_random);
334 secret.data = &key_block[i];
335 secret.len = effKeySize;
336 i += effKeySize;
337 keyblk.data = key_block2;
338 keyblk.len = keySize;
339 status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS);
340 if (status != SECSuccess) {
341 goto key_and_mac_derive_fail;
343 buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item, \
344 "TLS Export Client Write Key");
345 key_block2 += keySize;
348 ** server_write_key[CipherSpec.key_material]
349 ** final_server_write_key = PRF(server_write_key,
350 ** "server write key",
351 ** client_random + server_random);
353 secret.data = &key_block[i];
354 secret.len = effKeySize;
355 i += effKeySize;
356 keyblk.data = key_block2;
357 keyblk.len = keySize;
358 status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS);
359 if (status != SECSuccess) {
360 goto key_and_mac_derive_fail;
362 buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item, \
363 "TLS Export Server Write Key");
364 key_block2 += keySize;
367 ** iv_block = PRF("", "IV block", client_random + server_random);
368 ** client_write_IV[SecurityParameters.IV_size]
369 ** server_write_IV[SecurityParameters.IV_size]
371 if (IVSize) {
372 secret.data = NULL;
373 secret.len = 0;
374 keyblk.data = key_block2;
375 keyblk.len = 2 * IVSize;
376 status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS);
377 if (status != SECSuccess) {
378 goto key_and_mac_derive_fail;
380 buildSSLKey(key_block2, IVSize, \
381 &pwSpec->client.write_iv_item, \
382 "TLS Export Client Write IV");
383 buildSSLKey(key_block2 + IVSize, IVSize, \
384 &pwSpec->server.write_iv_item, \
385 "TLS Export Server Write IV");
386 key_block2 += 2 * IVSize;
388 PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
390 rv = SECSuccess;
392 key_and_mac_derive_fail:
394 MD5_DestroyContext(md5Ctx, PR_FALSE);
395 SHA1_DestroyContext(shaCtx, PR_FALSE);
397 if (rv != SECSuccess) {
398 PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
401 return rv;
405 /* derive the Master Secret from the PMS */
406 /* Presently, this is only done wtih RSA PMS, and only on the server side,
407 * so isRSA is always true.
409 SECStatus
410 ssl3_MasterKeyDeriveBypass(
411 ssl3CipherSpec * pwSpec,
412 const unsigned char * cr,
413 const unsigned char * sr,
414 const SECItem * pms,
415 PRBool isTLS,
416 PRBool isRSA)
418 unsigned char * key_block = pwSpec->key_block;
419 SECStatus rv = SECSuccess;
420 PRBool isFIPS = PR_FALSE;
422 SECItem crsr;
424 unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
425 PRUint64 md5buf[22];
426 PRUint64 shabuf[40];
428 #define md5Ctx ((MD5Context *)md5buf)
429 #define shaCtx ((SHA1Context *)shabuf)
431 /* first do the consistancy checks */
432 if (isRSA) {
433 PORT_Assert(pms->len == SSL3_RSA_PMS_LENGTH);
434 if (pms->len != SSL3_RSA_PMS_LENGTH) {
435 PORT_SetError(SEC_ERROR_INVALID_ARGS);
436 return SECFailure;
438 /* caller must test PMS version for rollback */
441 /* initialize the client random, server random block */
442 crsr.type = siBuffer;
443 crsr.data = crsrdata;
444 crsr.len = sizeof crsrdata;
445 PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
446 PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
447 PRINT_BUF(100, (NULL, "Master Secret CRSR", crsr.data, crsr.len));
449 /* finally do the key gen */
450 if (isTLS) {
451 SECItem master = { siBuffer, NULL, 0 };
453 master.data = key_block;
454 master.len = SSL3_MASTER_SECRET_LENGTH;
456 rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS);
457 if (rv != SECSuccess) {
458 PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
460 } else {
461 int i;
462 unsigned int made = 0;
463 for (i = 0; i < 3; i++) {
464 unsigned int outLen;
465 unsigned char sha_out[SHA1_LENGTH];
467 SHA1_Begin(shaCtx);
468 SHA1_Update(shaCtx, (unsigned char*) mixers[i], i+1);
469 SHA1_Update(shaCtx, pms->data, pms->len);
470 SHA1_Update(shaCtx, crsr.data, crsr.len);
471 SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH);
472 PORT_Assert(outLen == SHA1_LENGTH);
474 MD5_Begin(md5Ctx);
475 MD5_Update(md5Ctx, pms->data, pms->len);
476 MD5_Update(md5Ctx, sha_out, outLen);
477 MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
478 PORT_Assert(outLen == MD5_LENGTH);
479 made += outLen;
483 /* store the results */
484 PORT_Memcpy(pwSpec->raw_master_secret, key_block,
485 SSL3_MASTER_SECRET_LENGTH);
486 pwSpec->msItem.data = pwSpec->raw_master_secret;
487 pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
488 PRINT_BUF(100, (NULL, "Master Secret", pwSpec->msItem.data,
489 pwSpec->msItem.len));
491 return rv;
494 static SECStatus
495 ssl_canExtractMS(PK11SymKey *pms, PRBool isTLS, PRBool isDH, PRBool *pcbp)
496 { SECStatus rv;
497 PK11SymKey * ms = NULL;
498 SECItem params = {siBuffer, NULL, 0};
499 CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;
500 unsigned char rand[SSL3_RANDOM_LENGTH];
501 CK_VERSION pms_version;
502 CK_MECHANISM_TYPE master_derive;
503 CK_MECHANISM_TYPE key_derive;
504 CK_FLAGS keyFlags;
506 if (pms == NULL)
507 return(SECFailure);
509 PORT_Memset(rand, 0, SSL3_RANDOM_LENGTH);
511 if (isTLS) {
512 if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
513 else master_derive = CKM_TLS_MASTER_KEY_DERIVE;
514 key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
515 keyFlags = CKF_SIGN | CKF_VERIFY;
516 } else {
517 if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH;
518 else master_derive = CKM_SSL3_MASTER_KEY_DERIVE;
519 key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
520 keyFlags = 0;
523 master_params.pVersion = &pms_version;
524 master_params.RandomInfo.pClientRandom = rand;
525 master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
526 master_params.RandomInfo.pServerRandom = rand;
527 master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
529 params.data = (unsigned char *) &master_params;
530 params.len = sizeof master_params;
532 ms = PK11_DeriveWithFlags(pms, master_derive, &params, key_derive,
533 CKA_DERIVE, 0, keyFlags);
534 if (ms == NULL)
535 return(SECFailure);
537 rv = PK11_ExtractKeyValue(ms);
538 *pcbp = (rv == SECSuccess);
539 PK11_FreeSymKey(ms);
541 return(rv);
544 #endif /* !NO_PKCS11_BYPASS */
546 /* Check the key exchange algorithm for each cipher in the list to see if
547 * a master secret key can be extracted. If the KEA will use keys from the
548 * specified cert make sure the extract operation is attempted from the slot
549 * where the private key resides.
550 * If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and
551 * SECSuccess is returned. In all other cases but one (*pcanbypass) is
552 * set to FALSE and SECFailure is returned.
553 * In that last case Derive() has been called successfully but the MS is null,
554 * CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the
555 * arguments were all valid but the slot cannot be bypassed.
558 /* XXX Add SSL_CBP_TLS1_1 and test it in protocolmask when setting isTLS. */
560 SECStatus
561 SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey,
562 PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites,
563 PRBool *pcanbypass, void *pwArg)
565 #ifdef NO_PKCS11_BYPASS
566 if (!pcanbypass) {
567 PORT_SetError(SEC_ERROR_INVALID_ARGS);
568 return SECFailure;
570 *pcanbypass = PR_FALSE;
571 return SECSuccess;
572 #else
573 SECStatus rv;
574 int i;
575 PRUint16 suite;
576 PK11SymKey * pms = NULL;
577 SECKEYPublicKey * srvPubkey = NULL;
578 KeyType privKeytype;
579 PK11SlotInfo * slot = NULL;
580 SECItem param;
581 CK_VERSION version;
582 CK_MECHANISM_TYPE mechanism_array[2];
583 SECItem enc_pms = {siBuffer, NULL, 0};
584 PRBool isTLS = PR_FALSE;
585 SSLCipherSuiteInfo csdef;
586 PRBool testrsa = PR_FALSE;
587 PRBool testrsa_export = PR_FALSE;
588 PRBool testecdh = PR_FALSE;
589 PRBool testecdhe = PR_FALSE;
590 #ifdef NSS_ENABLE_ECC
591 SECKEYECParams ecParams = { siBuffer, NULL, 0 };
592 #endif
594 if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) {
595 PORT_SetError(SEC_ERROR_INVALID_ARGS);
596 return SECFailure;
599 srvPubkey = CERT_ExtractPublicKey(cert);
600 if (!srvPubkey)
601 return SECFailure;
603 *pcanbypass = PR_TRUE;
604 rv = SECFailure;
606 /* determine which KEAs to test */
607 /* 0 (SSL_NULL_WITH_NULL_NULL) is used as a list terminator because
608 * SSL3 and TLS specs forbid negotiating that cipher suite number.
610 for (i=0; i < nsuites && (suite = *ciphersuites++) != 0; i++) {
611 /* skip SSL2 cipher suites and ones NSS doesn't support */
612 if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess
613 || SSL_IS_SSL2_CIPHER(suite) )
614 continue;
615 switch (csdef.keaType) {
616 case ssl_kea_rsa:
617 switch (csdef.cipherSuite) {
618 case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA:
619 case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA:
620 case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
621 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
622 testrsa_export = PR_TRUE;
624 if (!testrsa_export)
625 testrsa = PR_TRUE;
626 break;
627 case ssl_kea_ecdh:
628 if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */
629 testecdhe = PR_TRUE;
630 else
631 testecdh = PR_TRUE;
632 break;
633 case ssl_kea_dh:
634 /* this is actually DHE */
635 default:
636 continue;
640 /* For each protocol try to derive and extract an MS.
641 * Failure of function any function except MS extract means
642 * continue with the next cipher test. Stop testing when the list is
643 * exhausted or when the first MS extract--not derive--fails.
645 privKeytype = SECKEY_GetPrivateKeyType(srvPrivkey);
646 protocolmask &= SSL_CBP_SSL3|SSL_CBP_TLS1_0;
647 while (protocolmask) {
648 if (protocolmask & SSL_CBP_SSL3) {
649 isTLS = PR_FALSE;
650 protocolmask ^= SSL_CBP_SSL3;
651 } else {
652 isTLS = PR_TRUE;
653 protocolmask ^= SSL_CBP_TLS1_0;
656 if (privKeytype == rsaKey && testrsa_export) {
657 if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) {
658 *pcanbypass = PR_FALSE;
659 rv = SECSuccess;
660 break;
661 } else
662 testrsa = PR_TRUE;
664 for (; privKeytype == rsaKey && testrsa; ) {
665 /* TLS_RSA */
666 unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
667 unsigned int outLen = 0;
668 CK_MECHANISM_TYPE target;
669 SECStatus irv;
671 mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
672 mechanism_array[1] = CKM_RSA_PKCS;
674 slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
675 if (slot == NULL) {
676 PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
677 break;
680 /* Generate the pre-master secret ... (client side) */
681 version.major = 3 /*MSB(clientHelloVersion)*/;
682 version.minor = 0 /*LSB(clientHelloVersion)*/;
683 param.data = (unsigned char *)&version;
684 param.len = sizeof version;
685 pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, &param, 0, pwArg);
686 PK11_FreeSlot(slot);
687 if (!pms)
688 break;
689 /* now wrap it */
690 enc_pms.len = SECKEY_PublicKeyStrength(srvPubkey);
691 enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len);
692 if (enc_pms.data == NULL) {
693 PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
694 break;
696 irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms);
697 if (irv != SECSuccess)
698 break;
699 PK11_FreeSymKey(pms);
700 pms = NULL;
701 /* now do the server side--check the triple bypass first */
702 rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen,
703 sizeof rsaPmsBuf,
704 (unsigned char *)enc_pms.data,
705 enc_pms.len);
706 /* if decrypt worked we're done with the RSA test */
707 if (rv == SECSuccess) {
708 *pcanbypass = PR_TRUE;
709 break;
711 /* check for fallback to double bypass */
712 target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE
713 : CKM_SSL3_MASTER_KEY_DERIVE;
714 pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms,
715 target, CKA_DERIVE, 0);
716 rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass);
717 if (rv == SECSuccess && *pcanbypass == PR_FALSE)
718 goto done;
719 break;
722 /* Check for NULL to avoid double free.
723 * SECItem_FreeItem sets data NULL in secitem.c#265
725 if (enc_pms.data != NULL) {
726 SECITEM_FreeItem(&enc_pms, PR_FALSE);
728 #ifdef NSS_ENABLE_ECC
729 for (; (privKeytype == ecKey && ( testecdh || testecdhe)) ||
730 (privKeytype == rsaKey && testecdhe); ) {
731 CK_MECHANISM_TYPE target;
732 SECKEYPublicKey *keapub = NULL;
733 SECKEYPrivateKey *keapriv;
734 SECKEYPublicKey *cpub = NULL; /* client's ephemeral ECDH keys */
735 SECKEYPrivateKey *cpriv = NULL;
736 SECKEYECParams *pecParams = NULL;
738 if (privKeytype == ecKey && testecdhe) {
739 /* TLS_ECDHE_ECDSA */
740 pecParams = &srvPubkey->u.ec.DEREncodedParams;
741 } else if (privKeytype == rsaKey && testecdhe) {
742 /* TLS_ECDHE_RSA */
743 ECName ec_curve;
744 int serverKeyStrengthInBits;
745 int signatureKeyStrength;
746 int requiredECCbits;
748 /* find a curve of equivalent strength to the RSA key's */
749 requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey);
750 if (requiredECCbits < 0)
751 break;
752 requiredECCbits *= BPB;
753 serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len;
754 if (srvPubkey->u.rsa.modulus.data[0] == 0) {
755 serverKeyStrengthInBits--;
757 /* convert to strength in bits */
758 serverKeyStrengthInBits *= BPB;
760 signatureKeyStrength =
761 SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
763 if ( requiredECCbits > signatureKeyStrength )
764 requiredECCbits = signatureKeyStrength;
766 ec_curve =
767 ssl3_GetCurveWithECKeyStrength(SSL3_SUPPORTED_CURVES_MASK,
768 requiredECCbits);
769 rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams);
770 if (rv == SECFailure) {
771 break;
773 pecParams = &ecParams;
776 if (testecdhe) {
777 /* generate server's ephemeral keys */
778 keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL);
779 if (!keapriv || !keapub) {
780 if (keapriv)
781 SECKEY_DestroyPrivateKey(keapriv);
782 if (keapub)
783 SECKEY_DestroyPublicKey(keapub);
784 PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
785 rv = SECFailure;
786 break;
788 } else {
789 /* TLS_ECDH_ECDSA */
790 keapub = srvPubkey;
791 keapriv = srvPrivkey;
792 pecParams = &srvPubkey->u.ec.DEREncodedParams;
795 /* perform client side ops */
796 /* generate a pair of ephemeral keys using server's parms */
797 cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL);
798 if (!cpriv || !cpub) {
799 if (testecdhe) {
800 SECKEY_DestroyPrivateKey(keapriv);
801 SECKEY_DestroyPublicKey(keapub);
803 PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
804 rv = SECFailure;
805 break;
807 /* now do the server side */
808 /* determine the PMS using client's public value */
809 target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH
810 : CKM_SSL3_MASTER_KEY_DERIVE_DH;
811 pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL,
812 CKM_ECDH1_DERIVE,
813 target,
814 CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
815 rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass);
816 SECKEY_DestroyPrivateKey(cpriv);
817 SECKEY_DestroyPublicKey(cpub);
818 if (testecdhe) {
819 SECKEY_DestroyPrivateKey(keapriv);
820 SECKEY_DestroyPublicKey(keapub);
822 if (rv == SECSuccess && *pcanbypass == PR_FALSE)
823 goto done;
824 break;
826 /* Check for NULL to avoid double free. */
827 if (ecParams.data != NULL) {
828 PORT_Free(ecParams.data);
829 ecParams.data = NULL;
831 #endif /* NSS_ENABLE_ECC */
832 if (pms)
833 PK11_FreeSymKey(pms);
836 /* *pcanbypass has been set */
837 rv = SECSuccess;
839 done:
840 if (pms)
841 PK11_FreeSymKey(pms);
843 /* Check for NULL to avoid double free.
844 * SECItem_FreeItem sets data NULL in secitem.c#265
846 if (enc_pms.data != NULL) {
847 SECITEM_FreeItem(&enc_pms, PR_FALSE);
849 #ifdef NSS_ENABLE_ECC
850 if (ecParams.data != NULL) {
851 PORT_Free(ecParams.data);
852 ecParams.data = NULL;
854 #endif /* NSS_ENABLE_ECC */
856 if (srvPubkey) {
857 SECKEY_DestroyPublicKey(srvPubkey);
858 srvPubkey = NULL;
862 return rv;
863 #endif /* NO_PKCS11_BYPASS */