2 * Key Derivation that doesn't use PKCS11
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is the Netscape security libraries.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1994-2005
22 * the Initial Developer. All Rights Reserved.
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
39 /* $Id: derive.c,v 1.12 2008/06/06 01:16:31 wtc%google.com Exp $ */
41 #include "ssl.h" /* prereq to sslimpl.h */
42 #include "certt.h" /* prereq to sslimpl.h */
43 #include "keythi.h" /* prereq to sslimpl.h */
56 /* make this a macro! */
59 buildSSLKey(unsigned char * keyBlock
, unsigned int keyLen
, SECItem
* result
,
62 result
->type
= siBuffer
;
63 result
->data
= keyBlock
;
65 PRINT_BUF(100, (NULL
, label
, keyBlock
, keyLen
));
68 #define buildSSLKey(keyBlock, keyLen, result, label) \
70 (result)->type = siBuffer; \
71 (result)->data = keyBlock; \
72 (result)->len = keyLen; \
73 PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); \
78 * SSL Key generation given pre master secret
83 static const char * const mixers
[NUM_MIXERS
] = {
97 ssl3_KeyAndMacDeriveBypass(
98 ssl3CipherSpec
* pwSpec
,
99 const unsigned char * cr
,
100 const unsigned char * sr
,
104 const ssl3BulkCipherDef
*cipher_def
= pwSpec
->cipher_def
;
105 unsigned char * key_block
= pwSpec
->key_block
;
106 unsigned char * key_block2
= NULL
;
107 unsigned int block_bytes
= 0;
108 unsigned int block_needed
= 0;
110 unsigned int keySize
; /* actual size of cipher keys */
111 unsigned int effKeySize
; /* effective size of cipher keys */
112 unsigned int macSize
; /* size of MAC secret */
113 unsigned int IVSize
; /* size of IV */
114 SECStatus rv
= SECFailure
;
115 SECStatus status
= SECSuccess
;
116 PRBool isFIPS
= PR_FALSE
;
121 unsigned char srcrdata
[SSL3_RANDOM_LENGTH
* 2];
122 unsigned char crsrdata
[SSL3_RANDOM_LENGTH
* 2];
126 #define md5Ctx ((MD5Context *)md5buf)
127 #define shaCtx ((SHA1Context *)shabuf)
129 static const SECItem zed
= { siBuffer
, NULL
, 0 };
131 if (pwSpec
->msItem
.data
== NULL
||
132 pwSpec
->msItem
.len
!= SSL3_MASTER_SECRET_LENGTH
) {
133 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
137 PRINT_BUF(100, (NULL
, "Master Secret", pwSpec
->msItem
.data
,
138 pwSpec
->msItem
.len
));
140 /* figure out how much is needed */
141 macSize
= pwSpec
->mac_size
;
142 keySize
= cipher_def
->key_size
;
143 effKeySize
= cipher_def
->secret_key_size
;
144 IVSize
= cipher_def
->iv_size
;
146 effKeySize
= IVSize
= 0; /* only MACing */
148 block_needed
= 2 * (macSize
+ effKeySize
+ ((!isExport
) * IVSize
));
151 * clear out our returned keys so we can recover on failure
153 pwSpec
->client
.write_key_item
= zed
;
154 pwSpec
->client
.write_mac_key_item
= zed
;
155 pwSpec
->server
.write_key_item
= zed
;
156 pwSpec
->server
.write_mac_key_item
= zed
;
158 /* initialize the server random, client random block */
159 srcr
.type
= siBuffer
;
160 srcr
.data
= srcrdata
;
161 srcr
.len
= sizeof srcrdata
;
162 PORT_Memcpy(srcrdata
, sr
, SSL3_RANDOM_LENGTH
);
163 PORT_Memcpy(srcrdata
+ SSL3_RANDOM_LENGTH
, cr
, SSL3_RANDOM_LENGTH
);
165 /* initialize the client random, server random block */
166 crsr
.type
= siBuffer
;
167 crsr
.data
= crsrdata
;
168 crsr
.len
= sizeof crsrdata
;
169 PORT_Memcpy(crsrdata
, cr
, SSL3_RANDOM_LENGTH
);
170 PORT_Memcpy(crsrdata
+ SSL3_RANDOM_LENGTH
, sr
, SSL3_RANDOM_LENGTH
);
171 PRINT_BUF(100, (NULL
, "Key & MAC CRSR", crsr
.data
, crsr
.len
));
174 * generate the key material:
179 keyblk
.type
= siBuffer
;
180 keyblk
.data
= key_block
;
181 keyblk
.len
= block_needed
;
183 status
= TLS_PRF(&pwSpec
->msItem
, "key expansion", &srcr
, &keyblk
,
185 if (status
!= SECSuccess
) {
186 goto key_and_mac_derive_fail
;
188 block_bytes
= keyblk
.len
;
191 * MD5(master_secret + SHA('A' + master_secret +
192 * ServerHello.random + ClientHello.random)) +
193 * MD5(master_secret + SHA('BB' + master_secret +
194 * ServerHello.random + ClientHello.random)) +
195 * MD5(master_secret + SHA('CCC' + master_secret +
196 * ServerHello.random + ClientHello.random)) +
199 unsigned int made
= 0;
200 for (i
= 0; made
< block_needed
&& i
< NUM_MIXERS
; ++i
) {
202 unsigned char sha_out
[SHA1_LENGTH
];
205 SHA1_Update(shaCtx
, (unsigned char*)(mixers
[i
]), i
+1);
206 SHA1_Update(shaCtx
, pwSpec
->msItem
.data
, pwSpec
->msItem
.len
);
207 SHA1_Update(shaCtx
, srcr
.data
, srcr
.len
);
208 SHA1_End(shaCtx
, sha_out
, &outLen
, SHA1_LENGTH
);
209 PORT_Assert(outLen
== SHA1_LENGTH
);
212 MD5_Update(md5Ctx
, pwSpec
->msItem
.data
, pwSpec
->msItem
.len
);
213 MD5_Update(md5Ctx
, sha_out
, outLen
);
214 MD5_End(md5Ctx
, key_block
+ made
, &outLen
, MD5_LENGTH
);
215 PORT_Assert(outLen
== MD5_LENGTH
);
220 PORT_Assert(block_bytes
>= block_needed
);
221 PORT_Assert(block_bytes
<= sizeof pwSpec
->key_block
);
222 PRINT_BUF(100, (NULL
, "key block", key_block
, block_bytes
));
225 * Put the key material where it goes.
227 key_block2
= key_block
+ block_bytes
;
228 i
= 0; /* now shows how much consumed */
231 * The key_block is partitioned as follows:
232 * client_write_MAC_secret[CipherSpec.hash_size]
234 buildSSLKey(&key_block
[i
],macSize
, &pwSpec
->client
.write_mac_key_item
, \
235 "Client Write MAC Secret");
239 * server_write_MAC_secret[CipherSpec.hash_size]
241 buildSSLKey(&key_block
[i
],macSize
, &pwSpec
->server
.write_mac_key_item
, \
242 "Server Write MAC Secret");
247 buildSSLKey(NULL
, 0, &pwSpec
->client
.write_key_item
, \
248 "Client Write Key (MAC only)");
249 buildSSLKey(NULL
, 0, &pwSpec
->server
.write_key_item
, \
250 "Server Write Key (MAC only)");
251 buildSSLKey(NULL
, 0, &pwSpec
->client
.write_iv_item
, \
252 "Client Write IV (MAC only)");
253 buildSSLKey(NULL
, 0, &pwSpec
->server
.write_iv_item
, \
254 "Server Write IV (MAC only)");
255 } else if (!isExport
) {
257 ** Generate Domestic write keys and IVs.
258 ** client_write_key[CipherSpec.key_material]
260 buildSSLKey(&key_block
[i
], keySize
, &pwSpec
->client
.write_key_item
, \
261 "Domestic Client Write Key");
265 ** server_write_key[CipherSpec.key_material]
267 buildSSLKey(&key_block
[i
], keySize
, &pwSpec
->server
.write_key_item
, \
268 "Domestic Server Write Key");
273 ** client_write_IV[CipherSpec.IV_size]
275 buildSSLKey(&key_block
[i
], IVSize
, &pwSpec
->client
.write_iv_item
, \
276 "Domestic Client Write IV");
280 ** server_write_IV[CipherSpec.IV_size]
282 buildSSLKey(&key_block
[i
], IVSize
, &pwSpec
->server
.write_iv_item
, \
283 "Domestic Server Write IV");
286 PORT_Assert(i
<= block_bytes
);
290 ** Generate SSL3 Export write keys and IVs.
295 ** client_write_key[CipherSpec.key_material]
296 ** final_client_write_key = MD5(client_write_key +
297 ** ClientHello.random + ServerHello.random);
300 MD5_Update(md5Ctx
, &key_block
[i
], effKeySize
);
301 MD5_Update(md5Ctx
, crsr
.data
, crsr
.len
);
302 MD5_End(md5Ctx
, key_block2
, &outLen
, MD5_LENGTH
);
304 buildSSLKey(key_block2
, keySize
, &pwSpec
->client
.write_key_item
, \
305 "SSL3 Export Client Write Key");
306 key_block2
+= keySize
;
309 ** server_write_key[CipherSpec.key_material]
310 ** final_server_write_key = MD5(server_write_key +
311 ** ServerHello.random + ClientHello.random);
314 MD5_Update(md5Ctx
, &key_block
[i
], effKeySize
);
315 MD5_Update(md5Ctx
, srcr
.data
, srcr
.len
);
316 MD5_End(md5Ctx
, key_block2
, &outLen
, MD5_LENGTH
);
318 buildSSLKey(key_block2
, keySize
, &pwSpec
->server
.write_key_item
, \
319 "SSL3 Export Server Write Key");
320 key_block2
+= keySize
;
321 PORT_Assert(i
<= block_bytes
);
326 ** MD5(ClientHello.random + ServerHello.random);
329 MD5_Update(md5Ctx
, crsr
.data
, crsr
.len
);
330 MD5_End(md5Ctx
, key_block2
, &outLen
, MD5_LENGTH
);
331 buildSSLKey(key_block2
, IVSize
, &pwSpec
->client
.write_iv_item
, \
332 "SSL3 Export Client Write IV");
333 key_block2
+= IVSize
;
337 ** MD5(ServerHello.random + ClientHello.random);
340 MD5_Update(md5Ctx
, srcr
.data
, srcr
.len
);
341 MD5_End(md5Ctx
, key_block2
, &outLen
, MD5_LENGTH
);
342 buildSSLKey(key_block2
, IVSize
, &pwSpec
->server
.write_iv_item
, \
343 "SSL3 Export Server Write IV");
344 key_block2
+= IVSize
;
347 PORT_Assert(key_block2
- key_block
<= sizeof pwSpec
->key_block
);
350 ** Generate TLS Export write keys and IVs.
355 secret
.type
= siBuffer
;
356 keyblk
.type
= siBuffer
;
358 ** client_write_key[CipherSpec.key_material]
359 ** final_client_write_key = PRF(client_write_key,
360 ** "client write key",
361 ** client_random + server_random);
363 secret
.data
= &key_block
[i
];
364 secret
.len
= effKeySize
;
366 keyblk
.data
= key_block2
;
367 keyblk
.len
= keySize
;
368 status
= TLS_PRF(&secret
, "client write key", &crsr
, &keyblk
, isFIPS
);
369 if (status
!= SECSuccess
) {
370 goto key_and_mac_derive_fail
;
372 buildSSLKey(key_block2
, keySize
, &pwSpec
->client
.write_key_item
, \
373 "TLS Export Client Write Key");
374 key_block2
+= keySize
;
377 ** server_write_key[CipherSpec.key_material]
378 ** final_server_write_key = PRF(server_write_key,
379 ** "server write key",
380 ** client_random + server_random);
382 secret
.data
= &key_block
[i
];
383 secret
.len
= effKeySize
;
385 keyblk
.data
= key_block2
;
386 keyblk
.len
= keySize
;
387 status
= TLS_PRF(&secret
, "server write key", &crsr
, &keyblk
, isFIPS
);
388 if (status
!= SECSuccess
) {
389 goto key_and_mac_derive_fail
;
391 buildSSLKey(key_block2
, keySize
, &pwSpec
->server
.write_key_item
, \
392 "TLS Export Server Write Key");
393 key_block2
+= keySize
;
396 ** iv_block = PRF("", "IV block", client_random + server_random);
397 ** client_write_IV[SecurityParameters.IV_size]
398 ** server_write_IV[SecurityParameters.IV_size]
403 keyblk
.data
= key_block2
;
404 keyblk
.len
= 2 * IVSize
;
405 status
= TLS_PRF(&secret
, "IV block", &crsr
, &keyblk
, isFIPS
);
406 if (status
!= SECSuccess
) {
407 goto key_and_mac_derive_fail
;
409 buildSSLKey(key_block2
, IVSize
, \
410 &pwSpec
->client
.write_iv_item
, \
411 "TLS Export Client Write IV");
412 buildSSLKey(key_block2
+ IVSize
, IVSize
, \
413 &pwSpec
->server
.write_iv_item
, \
414 "TLS Export Server Write IV");
415 key_block2
+= 2 * IVSize
;
417 PORT_Assert(key_block2
- key_block
<= sizeof pwSpec
->key_block
);
421 key_and_mac_derive_fail
:
423 MD5_DestroyContext(md5Ctx
, PR_FALSE
);
424 SHA1_DestroyContext(shaCtx
, PR_FALSE
);
426 if (rv
!= SECSuccess
) {
427 PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE
);
434 /* derive the Master Secret from the PMS */
435 /* Presently, this is only done wtih RSA PMS, and only on the server side,
436 * so isRSA is always true.
439 ssl3_MasterKeyDeriveBypass(
440 ssl3CipherSpec
* pwSpec
,
441 const unsigned char * cr
,
442 const unsigned char * sr
,
447 unsigned char * key_block
= pwSpec
->key_block
;
448 SECStatus rv
= SECSuccess
;
449 PRBool isFIPS
= PR_FALSE
;
453 unsigned char crsrdata
[SSL3_RANDOM_LENGTH
* 2];
457 #define md5Ctx ((MD5Context *)md5buf)
458 #define shaCtx ((SHA1Context *)shabuf)
460 /* first do the consistancy checks */
462 PORT_Assert(pms
->len
== SSL3_RSA_PMS_LENGTH
);
463 if (pms
->len
!= SSL3_RSA_PMS_LENGTH
) {
464 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
467 /* caller must test PMS version for rollback */
470 /* initialize the client random, server random block */
471 crsr
.type
= siBuffer
;
472 crsr
.data
= crsrdata
;
473 crsr
.len
= sizeof crsrdata
;
474 PORT_Memcpy(crsrdata
, cr
, SSL3_RANDOM_LENGTH
);
475 PORT_Memcpy(crsrdata
+ SSL3_RANDOM_LENGTH
, sr
, SSL3_RANDOM_LENGTH
);
476 PRINT_BUF(100, (NULL
, "Master Secret CRSR", crsr
.data
, crsr
.len
));
478 /* finally do the key gen */
480 SECItem master
= { siBuffer
, NULL
, 0 };
482 master
.data
= key_block
;
483 master
.len
= SSL3_MASTER_SECRET_LENGTH
;
485 rv
= TLS_PRF(pms
, "master secret", &crsr
, &master
, isFIPS
);
486 if (rv
!= SECSuccess
) {
487 PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE
);
491 unsigned int made
= 0;
492 for (i
= 0; i
< 3; i
++) {
494 unsigned char sha_out
[SHA1_LENGTH
];
497 SHA1_Update(shaCtx
, (unsigned char*) mixers
[i
], i
+1);
498 SHA1_Update(shaCtx
, pms
->data
, pms
->len
);
499 SHA1_Update(shaCtx
, crsr
.data
, crsr
.len
);
500 SHA1_End(shaCtx
, sha_out
, &outLen
, SHA1_LENGTH
);
501 PORT_Assert(outLen
== SHA1_LENGTH
);
504 MD5_Update(md5Ctx
, pms
->data
, pms
->len
);
505 MD5_Update(md5Ctx
, sha_out
, outLen
);
506 MD5_End(md5Ctx
, key_block
+ made
, &outLen
, MD5_LENGTH
);
507 PORT_Assert(outLen
== MD5_LENGTH
);
512 /* store the results */
513 PORT_Memcpy(pwSpec
->raw_master_secret
, key_block
,
514 SSL3_MASTER_SECRET_LENGTH
);
515 pwSpec
->msItem
.data
= pwSpec
->raw_master_secret
;
516 pwSpec
->msItem
.len
= SSL3_MASTER_SECRET_LENGTH
;
517 PRINT_BUF(100, (NULL
, "Master Secret", pwSpec
->msItem
.data
,
518 pwSpec
->msItem
.len
));
524 ssl_canExtractMS(PK11SymKey
*pms
, PRBool isTLS
, PRBool isDH
, PRBool
*pcbp
)
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
;
538 PORT_Memset(rand
, 0, SSL3_RANDOM_LENGTH
);
541 if(isDH
) master_derive
= CKM_TLS_MASTER_KEY_DERIVE_DH
;
542 else master_derive
= CKM_TLS_MASTER_KEY_DERIVE
;
543 key_derive
= CKM_TLS_KEY_AND_MAC_DERIVE
;
544 keyFlags
= CKF_SIGN
| CKF_VERIFY
;
546 if (isDH
) master_derive
= CKM_SSL3_MASTER_KEY_DERIVE_DH
;
547 else master_derive
= CKM_SSL3_MASTER_KEY_DERIVE
;
548 key_derive
= CKM_SSL3_KEY_AND_MAC_DERIVE
;
552 master_params
.pVersion
= &pms_version
;
553 master_params
.RandomInfo
.pClientRandom
= rand
;
554 master_params
.RandomInfo
.ulClientRandomLen
= SSL3_RANDOM_LENGTH
;
555 master_params
.RandomInfo
.pServerRandom
= rand
;
556 master_params
.RandomInfo
.ulServerRandomLen
= SSL3_RANDOM_LENGTH
;
558 params
.data
= (unsigned char *) &master_params
;
559 params
.len
= sizeof master_params
;
561 ms
= PK11_DeriveWithFlags(pms
, master_derive
, ¶ms
, key_derive
,
562 CKA_DERIVE
, 0, keyFlags
);
566 rv
= PK11_ExtractKeyValue(ms
);
567 *pcbp
= (rv
== SECSuccess
);
574 /* Check the key exchange algorithm for each cipher in the list to see if
575 * a master secret key can be extracted. If the KEA will use keys from the
576 * specified cert make sure the extract operation is attempted from the slot
577 * where the private key resides.
578 * If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and
579 * SECSuccess is returned. In all other cases but one (*pcanbypass) is
580 * set to FALSE and SECFailure is returned.
581 * In that last case Derive() has been called successfully but the MS is null,
582 * CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the
583 * arguments were all valid but the slot cannot be bypassed.
587 SSL_CanBypass(CERTCertificate
*cert
, SECKEYPrivateKey
*srvPrivkey
,
588 PRUint32 protocolmask
, PRUint16
*ciphersuites
, int nsuites
,
589 PRBool
*pcanbypass
, void *pwArg
)
593 PK11SymKey
* pms
= NULL
;
594 SECKEYPublicKey
* srvPubkey
= NULL
;
596 PK11SlotInfo
* slot
= NULL
;
599 CK_MECHANISM_TYPE mechanism_array
[2];
600 SECItem enc_pms
= {siBuffer
, NULL
, 0};
601 PRBool isTLS
= PR_FALSE
;
602 SSLCipherSuiteInfo csdef
;
603 PRBool testrsa
= PR_FALSE
;
604 PRBool testrsa_export
= PR_FALSE
;
605 PRBool testecdh
= PR_FALSE
;
606 PRBool testecdhe
= PR_FALSE
;
608 if (!cert
|| !srvPrivkey
|| !ciphersuites
|| !pcanbypass
) {
609 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
613 srvPubkey
= CERT_ExtractPublicKey(cert
);
617 *pcanbypass
= PR_TRUE
;
620 /* determine which KEAs to test */
621 /* 0 (SSL_NULL_WITH_NULL_NULL) is used as a list terminator because
622 * SSL3 and TLS specs forbid negotiating that cipher suite number.
624 for (i
=0; i
< nsuites
&& (suite
= *ciphersuites
++) != 0; i
++) {
625 /* skip SSL2 cipher suites and ones NSS doesn't support */
626 if (SSL_GetCipherSuiteInfo(suite
, &csdef
, sizeof(csdef
)) != SECSuccess
627 || SSL_IS_SSL2_CIPHER(suite
) )
629 switch (csdef
.keaType
) {
631 switch (csdef
.cipherSuite
) {
632 case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA
:
633 case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA
:
634 case SSL_RSA_EXPORT_WITH_RC4_40_MD5
:
635 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
:
636 testrsa_export
= PR_TRUE
;
642 if (strcmp(csdef
.keaTypeName
, "ECDHE") == 0) /* ephemeral? */
648 /* this is actually DHE */
654 /* For each protocol try to derive and extract an MS.
655 * Failure of function any function except MS extract means
656 * continue with the next cipher test. Stop testing when the list is
657 * exhausted or when the first MS extract--not derive--fails.
659 privKeytype
= SECKEY_GetPrivateKeyType(srvPrivkey
);
660 protocolmask
&= SSL_CBP_SSL3
|SSL_CBP_TLS1_0
;
661 while (protocolmask
) {
662 if (protocolmask
& SSL_CBP_SSL3
) {
664 protocolmask
^= SSL_CBP_SSL3
;
667 protocolmask
^= SSL_CBP_TLS1_0
;
670 if (privKeytype
== rsaKey
&& testrsa_export
) {
671 if (PK11_GetPrivateModulusLen(srvPrivkey
) > EXPORT_RSA_KEY_LENGTH
) {
672 *pcanbypass
= PR_FALSE
;
678 for (; privKeytype
== rsaKey
&& testrsa
; ) {
680 unsigned char rsaPmsBuf
[SSL3_RSA_PMS_LENGTH
];
681 unsigned int outLen
= 0;
682 CK_MECHANISM_TYPE target
;
685 mechanism_array
[0] = CKM_SSL3_PRE_MASTER_KEY_GEN
;
686 mechanism_array
[1] = CKM_RSA_PKCS
;
688 slot
= PK11_GetBestSlotMultiple(mechanism_array
, 2, pwArg
);
690 PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND
);
694 /* Generate the pre-master secret ... (client side) */
695 version
.major
= 3 /*MSB(clientHelloVersion)*/;
696 version
.minor
= 0 /*LSB(clientHelloVersion)*/;
697 param
.data
= (unsigned char *)&version
;
698 param
.len
= sizeof version
;
699 pms
= PK11_KeyGen(slot
, CKM_SSL3_PRE_MASTER_KEY_GEN
, ¶m
, 0, pwArg
);
704 enc_pms
.len
= SECKEY_PublicKeyStrength(srvPubkey
);
705 enc_pms
.data
= (unsigned char*)PORT_Alloc(enc_pms
.len
);
706 irv
= PK11_PubWrapSymKey(CKM_RSA_PKCS
, srvPubkey
, pms
, &enc_pms
);
707 if (irv
!= SECSuccess
)
709 PK11_FreeSymKey(pms
);
710 /* now do the server side--check the triple bypass first */
711 rv
= PK11_PrivDecryptPKCS1(srvPrivkey
, rsaPmsBuf
, &outLen
,
713 (unsigned char *)enc_pms
.data
,
715 /* if decrypt worked we're done with the RSA test */
716 if (rv
== SECSuccess
) {
717 *pcanbypass
= PR_TRUE
;
720 /* check for fallback to double bypass */
721 target
= isTLS
? CKM_TLS_MASTER_KEY_DERIVE
722 : CKM_SSL3_MASTER_KEY_DERIVE
;
723 pms
= PK11_PubUnwrapSymKey(srvPrivkey
, &enc_pms
,
724 target
, CKA_DERIVE
, 0);
725 rv
= ssl_canExtractMS(pms
, isTLS
, PR_FALSE
, pcanbypass
);
726 if (rv
== SECSuccess
&& *pcanbypass
== PR_FALSE
)
730 #ifdef NSS_ENABLE_ECC
731 for (; (privKeytype
== ecKey
&& ( testecdh
|| testecdhe
)) ||
732 (privKeytype
== rsaKey
&& testecdhe
); ) {
733 CK_MECHANISM_TYPE target
;
734 SECKEYPublicKey
*keapub
= NULL
;
735 SECKEYPrivateKey
*keapriv
;
736 SECKEYPublicKey
*cpub
= NULL
; /* client's ephemeral ECDH keys */
737 SECKEYPrivateKey
*cpriv
= NULL
;
738 SECKEYECParams ecParams
= { siBuffer
, NULL
, 0 },
741 if (privKeytype
== ecKey
&& testecdhe
) {
742 /* TLS_ECDHE_ECDSA */
743 pecParams
= &srvPubkey
->u
.ec
.DEREncodedParams
;
744 } else if (privKeytype
== rsaKey
&& testecdhe
) {
747 int serverKeyStrengthInBits
;
748 int signatureKeyStrength
;
751 /* find a curve of equivalent strength to the RSA key's */
752 requiredECCbits
= PK11_GetPrivateModulusLen(srvPrivkey
);
753 if (requiredECCbits
< 0)
755 requiredECCbits
*= BPB
;
756 serverKeyStrengthInBits
= srvPubkey
->u
.rsa
.modulus
.len
;
757 if (srvPubkey
->u
.rsa
.modulus
.data
[0] == 0) {
758 serverKeyStrengthInBits
--;
760 /* convert to strength in bits */
761 serverKeyStrengthInBits
*= BPB
;
763 signatureKeyStrength
=
764 SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits
);
766 if ( requiredECCbits
> signatureKeyStrength
)
767 requiredECCbits
= signatureKeyStrength
;
770 ssl3_GetCurveWithECKeyStrength(SSL3_SUPPORTED_CURVES_MASK
,
772 rv
= ssl3_ECName2Params(NULL
, ec_curve
, &ecParams
);
773 if (rv
== SECFailure
) {
776 pecParams
= &ecParams
;
780 /* generate server's ephemeral keys */
781 keapriv
= SECKEY_CreateECPrivateKey(pecParams
, &keapub
, NULL
);
782 if (!keapriv
|| !keapub
) {
784 SECKEY_DestroyPrivateKey(keapriv
);
786 SECKEY_DestroyPublicKey(keapub
);
787 PORT_SetError(SEC_ERROR_KEYGEN_FAIL
);
794 keapriv
= srvPrivkey
;
795 pecParams
= &srvPubkey
->u
.ec
.DEREncodedParams
;
798 /* perform client side ops */
799 /* generate a pair of ephemeral keys using server's parms */
800 cpriv
= SECKEY_CreateECPrivateKey(pecParams
, &cpub
, NULL
);
801 if (!cpriv
|| !cpub
) {
803 SECKEY_DestroyPrivateKey(keapriv
);
804 SECKEY_DestroyPublicKey(keapub
);
806 PORT_SetError(SEC_ERROR_KEYGEN_FAIL
);
810 /* now do the server side */
811 /* determine the PMS using client's public value */
812 target
= isTLS
? CKM_TLS_MASTER_KEY_DERIVE_DH
813 : CKM_SSL3_MASTER_KEY_DERIVE_DH
;
814 pms
= PK11_PubDeriveWithKDF(keapriv
, cpub
, PR_FALSE
, NULL
, NULL
,
817 CKA_DERIVE
, 0, CKD_NULL
, NULL
, NULL
);
818 rv
= ssl_canExtractMS(pms
, isTLS
, PR_TRUE
, pcanbypass
);
819 SECKEY_DestroyPrivateKey(cpriv
);
820 SECKEY_DestroyPublicKey(cpub
);
822 SECKEY_DestroyPrivateKey(keapriv
);
823 SECKEY_DestroyPublicKey(keapub
);
824 if (privKeytype
== rsaKey
)
825 PORT_Free(ecParams
.data
);
827 if (rv
== SECSuccess
&& *pcanbypass
== PR_FALSE
)
831 #endif /* NSS_ENABLE_ECC */
833 PK11_FreeSymKey(pms
);
836 /* *pcanbypass has been set */
841 PK11_FreeSymKey(pms
);
843 SECITEM_FreeItem(&enc_pms
, PR_FALSE
);
846 SECKEY_DestroyPublicKey(srvPubkey
);