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 */
13 #ifndef NO_PKCS11_BYPASS
26 #ifndef NO_PKCS11_BYPASS
27 /* make this a macro! */
30 buildSSLKey(unsigned char * keyBlock
, unsigned int keyLen
, SECItem
* result
,
33 result
->type
= siBuffer
;
34 result
->data
= keyBlock
;
36 PRINT_BUF(100, (NULL
, label
, keyBlock
, keyLen
));
39 #define buildSSLKey(keyBlock, keyLen, result, label) \
41 (result)->type = siBuffer; \
42 (result)->data = keyBlock; \
43 (result)->len = keyLen; \
44 PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); \
49 * SSL Key generation given pre master secret
54 static const char * const mixers
[NUM_MIXERS
] = {
68 ssl3_KeyAndMacDeriveBypass(
69 ssl3CipherSpec
* pwSpec
,
70 const unsigned char * cr
,
71 const unsigned char * sr
,
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;
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
;
92 unsigned char srcrdata
[SSL3_RANDOM_LENGTH
* 2];
93 unsigned char crsrdata
[SSL3_RANDOM_LENGTH
* 2];
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
);
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
;
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:
150 keyblk
.type
= siBuffer
;
151 keyblk
.data
= key_block
;
152 keyblk
.len
= block_needed
;
154 status
= TLS_PRF(&pwSpec
->msItem
, "key expansion", &srcr
, &keyblk
,
156 if (status
!= SECSuccess
) {
157 goto key_and_mac_derive_fail
;
159 block_bytes
= keyblk
.len
;
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)) +
170 unsigned int made
= 0;
171 for (i
= 0; made
< block_needed
&& i
< NUM_MIXERS
; ++i
) {
173 unsigned char sha_out
[SHA1_LENGTH
];
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
);
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
);
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");
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");
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");
236 ** server_write_key[CipherSpec.key_material]
238 buildSSLKey(&key_block
[i
], keySize
, &pwSpec
->server
.write_key_item
, \
239 "Domestic Server Write Key");
244 ** client_write_IV[CipherSpec.IV_size]
246 buildSSLKey(&key_block
[i
], IVSize
, &pwSpec
->client
.write_iv_item
, \
247 "Domestic Client Write IV");
251 ** server_write_IV[CipherSpec.IV_size]
253 buildSSLKey(&key_block
[i
], IVSize
, &pwSpec
->server
.write_iv_item
, \
254 "Domestic Server Write IV");
257 PORT_Assert(i
<= block_bytes
);
261 ** Generate SSL3 Export write keys and IVs.
266 ** client_write_key[CipherSpec.key_material]
267 ** final_client_write_key = MD5(client_write_key +
268 ** ClientHello.random + ServerHello.random);
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
);
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);
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
);
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
);
297 ** MD5(ClientHello.random + ServerHello.random);
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
;
308 ** MD5(ServerHello.random + ClientHello.random);
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
);
321 ** Generate TLS Export write keys and IVs.
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
;
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
;
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]
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
);
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
);
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.
410 ssl3_MasterKeyDeriveBypass(
411 ssl3CipherSpec
* pwSpec
,
412 const unsigned char * cr
,
413 const unsigned char * sr
,
418 unsigned char * key_block
= pwSpec
->key_block
;
419 SECStatus rv
= SECSuccess
;
420 PRBool isFIPS
= PR_FALSE
;
424 unsigned char crsrdata
[SSL3_RANDOM_LENGTH
* 2];
428 #define md5Ctx ((MD5Context *)md5buf)
429 #define shaCtx ((SHA1Context *)shabuf)
431 /* first do the consistancy checks */
433 PORT_Assert(pms
->len
== SSL3_RSA_PMS_LENGTH
);
434 if (pms
->len
!= SSL3_RSA_PMS_LENGTH
) {
435 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
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 */
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
);
462 unsigned int made
= 0;
463 for (i
= 0; i
< 3; i
++) {
465 unsigned char sha_out
[SHA1_LENGTH
];
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
);
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
);
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
));
495 ssl_canExtractMS(PK11SymKey
*pms
, PRBool isTLS
, PRBool isDH
, PRBool
*pcbp
)
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
;
509 PORT_Memset(rand
, 0, SSL3_RANDOM_LENGTH
);
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
;
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
;
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
, ¶ms
, key_derive
,
533 CKA_DERIVE
, 0, keyFlags
);
537 rv
= PK11_ExtractKeyValue(ms
);
538 *pcbp
= (rv
== SECSuccess
);
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. */
561 SSL_CanBypass(CERTCertificate
*cert
, SECKEYPrivateKey
*srvPrivkey
,
562 PRUint32 protocolmask
, PRUint16
*ciphersuites
, int nsuites
,
563 PRBool
*pcanbypass
, void *pwArg
)
565 #ifdef NO_PKCS11_BYPASS
567 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
570 *pcanbypass
= PR_FALSE
;
576 PK11SymKey
* pms
= NULL
;
577 SECKEYPublicKey
* srvPubkey
= NULL
;
579 PK11SlotInfo
* slot
= NULL
;
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 };
594 if (!cert
|| !srvPrivkey
|| !ciphersuites
|| !pcanbypass
) {
595 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
599 srvPubkey
= CERT_ExtractPublicKey(cert
);
603 *pcanbypass
= PR_TRUE
;
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
) )
615 switch (csdef
.keaType
) {
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
;
628 if (strcmp(csdef
.keaTypeName
, "ECDHE") == 0) /* ephemeral? */
634 /* this is actually DHE */
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
) {
650 protocolmask
^= SSL_CBP_SSL3
;
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
;
664 for (; privKeytype
== rsaKey
&& testrsa
; ) {
666 unsigned char rsaPmsBuf
[SSL3_RSA_PMS_LENGTH
];
667 unsigned int outLen
= 0;
668 CK_MECHANISM_TYPE target
;
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
);
676 PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND
);
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
, ¶m
, 0, pwArg
);
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
);
696 irv
= PK11_PubWrapSymKey(CKM_RSA_PKCS
, srvPubkey
, pms
, &enc_pms
);
697 if (irv
!= SECSuccess
)
699 PK11_FreeSymKey(pms
);
701 /* now do the server side--check the triple bypass first */
702 rv
= PK11_PrivDecryptPKCS1(srvPrivkey
, rsaPmsBuf
, &outLen
,
704 (unsigned char *)enc_pms
.data
,
706 /* if decrypt worked we're done with the RSA test */
707 if (rv
== SECSuccess
) {
708 *pcanbypass
= PR_TRUE
;
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
)
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
) {
744 int serverKeyStrengthInBits
;
745 int signatureKeyStrength
;
748 /* find a curve of equivalent strength to the RSA key's */
749 requiredECCbits
= PK11_GetPrivateModulusLen(srvPrivkey
);
750 if (requiredECCbits
< 0)
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
;
767 ssl3_GetCurveWithECKeyStrength(SSL3_SUPPORTED_CURVES_MASK
,
769 rv
= ssl3_ECName2Params(NULL
, ec_curve
, &ecParams
);
770 if (rv
== SECFailure
) {
773 pecParams
= &ecParams
;
777 /* generate server's ephemeral keys */
778 keapriv
= SECKEY_CreateECPrivateKey(pecParams
, &keapub
, NULL
);
779 if (!keapriv
|| !keapub
) {
781 SECKEY_DestroyPrivateKey(keapriv
);
783 SECKEY_DestroyPublicKey(keapub
);
784 PORT_SetError(SEC_ERROR_KEYGEN_FAIL
);
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
) {
800 SECKEY_DestroyPrivateKey(keapriv
);
801 SECKEY_DestroyPublicKey(keapub
);
803 PORT_SetError(SEC_ERROR_KEYGEN_FAIL
);
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
,
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
);
819 SECKEY_DestroyPrivateKey(keapriv
);
820 SECKEY_DestroyPublicKey(keapub
);
822 if (rv
== SECSuccess
&& *pcanbypass
== PR_FALSE
)
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 */
833 PK11_FreeSymKey(pms
);
836 /* *pcanbypass has been set */
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 */
857 SECKEY_DestroyPublicKey(srvPubkey
);
863 #endif /* NO_PKCS11_BYPASS */