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/. */
8 #include "ssl.h" /* prereq to sslimpl.h */
9 #include "certt.h" /* prereq to sslimpl.h */
10 #include "keythi.h" /* prereq to sslimpl.h */
12 #ifndef NO_PKCS11_BYPASS
25 #ifndef NO_PKCS11_BYPASS
26 /* make this a macro! */
29 buildSSLKey(unsigned char * keyBlock
, unsigned int keyLen
, SECItem
* result
,
32 result
->type
= siBuffer
;
33 result
->data
= keyBlock
;
35 PRINT_BUF(100, (NULL
, label
, keyBlock
, keyLen
));
38 #define buildSSLKey(keyBlock, keyLen, result, label) \
40 (result)->type = siBuffer; \
41 (result)->data = keyBlock; \
42 (result)->len = keyLen; \
43 PRINT_BUF(100, (NULL, label, keyBlock, keyLen)); \
48 * SSL Key generation given pre master secret
53 static const char * const mixers
[NUM_MIXERS
] = {
67 ssl3_KeyAndMacDeriveBypass(
68 ssl3CipherSpec
* pwSpec
,
69 const unsigned char * cr
,
70 const unsigned char * sr
,
74 const ssl3BulkCipherDef
*cipher_def
= pwSpec
->cipher_def
;
75 unsigned char * key_block
= pwSpec
->key_block
;
76 unsigned char * key_block2
= NULL
;
77 unsigned int block_bytes
= 0;
78 unsigned int block_needed
= 0;
80 unsigned int keySize
; /* actual size of cipher keys */
81 unsigned int effKeySize
; /* effective size of cipher keys */
82 unsigned int macSize
; /* size of MAC secret */
83 unsigned int IVSize
; /* size of IV */
84 PRBool explicitIV
= PR_FALSE
;
85 SECStatus rv
= SECFailure
;
86 SECStatus status
= SECSuccess
;
87 PRBool isFIPS
= PR_FALSE
;
88 PRBool isTLS12
= pwSpec
->version
>= SSL_LIBRARY_VERSION_TLS_1_2
;
93 unsigned char srcrdata
[SSL3_RANDOM_LENGTH
* 2];
94 unsigned char crsrdata
[SSL3_RANDOM_LENGTH
* 2];
98 #define md5Ctx ((MD5Context *)md5buf)
99 #define shaCtx ((SHA1Context *)shabuf)
101 static const SECItem zed
= { siBuffer
, NULL
, 0 };
103 if (pwSpec
->msItem
.data
== NULL
||
104 pwSpec
->msItem
.len
!= SSL3_MASTER_SECRET_LENGTH
) {
105 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
109 PRINT_BUF(100, (NULL
, "Master Secret", pwSpec
->msItem
.data
,
110 pwSpec
->msItem
.len
));
112 /* figure out how much is needed */
113 macSize
= pwSpec
->mac_size
;
114 keySize
= cipher_def
->key_size
;
115 effKeySize
= cipher_def
->secret_key_size
;
116 IVSize
= cipher_def
->iv_size
;
118 effKeySize
= IVSize
= 0; /* only MACing */
120 if (cipher_def
->type
== type_block
&&
121 pwSpec
->version
>= SSL_LIBRARY_VERSION_TLS_1_1
) {
122 /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
123 explicitIV
= PR_TRUE
;
126 2 * (macSize
+ effKeySize
+ ((!isExport
&& !explicitIV
) * IVSize
));
129 * clear out our returned keys so we can recover on failure
131 pwSpec
->client
.write_key_item
= zed
;
132 pwSpec
->client
.write_mac_key_item
= zed
;
133 pwSpec
->server
.write_key_item
= zed
;
134 pwSpec
->server
.write_mac_key_item
= zed
;
136 /* initialize the server random, client random block */
137 srcr
.type
= siBuffer
;
138 srcr
.data
= srcrdata
;
139 srcr
.len
= sizeof srcrdata
;
140 PORT_Memcpy(srcrdata
, sr
, SSL3_RANDOM_LENGTH
);
141 PORT_Memcpy(srcrdata
+ SSL3_RANDOM_LENGTH
, cr
, SSL3_RANDOM_LENGTH
);
143 /* initialize the client random, server random block */
144 crsr
.type
= siBuffer
;
145 crsr
.data
= crsrdata
;
146 crsr
.len
= sizeof crsrdata
;
147 PORT_Memcpy(crsrdata
, cr
, SSL3_RANDOM_LENGTH
);
148 PORT_Memcpy(crsrdata
+ SSL3_RANDOM_LENGTH
, sr
, SSL3_RANDOM_LENGTH
);
149 PRINT_BUF(100, (NULL
, "Key & MAC CRSR", crsr
.data
, crsr
.len
));
152 * generate the key material:
157 keyblk
.type
= siBuffer
;
158 keyblk
.data
= key_block
;
159 keyblk
.len
= block_needed
;
162 status
= TLS_P_hash(HASH_AlgSHA256
, &pwSpec
->msItem
,
163 "key expansion", &srcr
, &keyblk
, isFIPS
);
165 status
= TLS_PRF(&pwSpec
->msItem
, "key expansion", &srcr
, &keyblk
,
168 if (status
!= SECSuccess
) {
169 goto key_and_mac_derive_fail
;
171 block_bytes
= keyblk
.len
;
174 * MD5(master_secret + SHA('A' + master_secret +
175 * ServerHello.random + ClientHello.random)) +
176 * MD5(master_secret + SHA('BB' + master_secret +
177 * ServerHello.random + ClientHello.random)) +
178 * MD5(master_secret + SHA('CCC' + master_secret +
179 * ServerHello.random + ClientHello.random)) +
182 unsigned int made
= 0;
183 for (i
= 0; made
< block_needed
&& i
< NUM_MIXERS
; ++i
) {
185 unsigned char sha_out
[SHA1_LENGTH
];
188 SHA1_Update(shaCtx
, (unsigned char*)(mixers
[i
]), i
+1);
189 SHA1_Update(shaCtx
, pwSpec
->msItem
.data
, pwSpec
->msItem
.len
);
190 SHA1_Update(shaCtx
, srcr
.data
, srcr
.len
);
191 SHA1_End(shaCtx
, sha_out
, &outLen
, SHA1_LENGTH
);
192 PORT_Assert(outLen
== SHA1_LENGTH
);
195 MD5_Update(md5Ctx
, pwSpec
->msItem
.data
, pwSpec
->msItem
.len
);
196 MD5_Update(md5Ctx
, sha_out
, outLen
);
197 MD5_End(md5Ctx
, key_block
+ made
, &outLen
, MD5_LENGTH
);
198 PORT_Assert(outLen
== MD5_LENGTH
);
203 PORT_Assert(block_bytes
>= block_needed
);
204 PORT_Assert(block_bytes
<= sizeof pwSpec
->key_block
);
205 PRINT_BUF(100, (NULL
, "key block", key_block
, block_bytes
));
208 * Put the key material where it goes.
210 key_block2
= key_block
+ block_bytes
;
211 i
= 0; /* now shows how much consumed */
214 * The key_block is partitioned as follows:
215 * client_write_MAC_secret[CipherSpec.hash_size]
217 buildSSLKey(&key_block
[i
],macSize
, &pwSpec
->client
.write_mac_key_item
, \
218 "Client Write MAC Secret");
222 * server_write_MAC_secret[CipherSpec.hash_size]
224 buildSSLKey(&key_block
[i
],macSize
, &pwSpec
->server
.write_mac_key_item
, \
225 "Server Write MAC Secret");
230 buildSSLKey(NULL
, 0, &pwSpec
->client
.write_key_item
, \
231 "Client Write Key (MAC only)");
232 buildSSLKey(NULL
, 0, &pwSpec
->server
.write_key_item
, \
233 "Server Write Key (MAC only)");
234 buildSSLKey(NULL
, 0, &pwSpec
->client
.write_iv_item
, \
235 "Client Write IV (MAC only)");
236 buildSSLKey(NULL
, 0, &pwSpec
->server
.write_iv_item
, \
237 "Server Write IV (MAC only)");
238 } else if (!isExport
) {
240 ** Generate Domestic write keys and IVs.
241 ** client_write_key[CipherSpec.key_material]
243 buildSSLKey(&key_block
[i
], keySize
, &pwSpec
->client
.write_key_item
, \
244 "Domestic Client Write Key");
248 ** server_write_key[CipherSpec.key_material]
250 buildSSLKey(&key_block
[i
], keySize
, &pwSpec
->server
.write_key_item
, \
251 "Domestic Server Write Key");
256 static unsigned char zero_block
[32];
257 PORT_Assert(IVSize
<= sizeof zero_block
);
258 buildSSLKey(&zero_block
[0], IVSize
, \
259 &pwSpec
->client
.write_iv_item
, \
260 "Domestic Client Write IV");
261 buildSSLKey(&zero_block
[0], IVSize
, \
262 &pwSpec
->server
.write_iv_item
, \
263 "Domestic Server Write IV");
266 ** client_write_IV[CipherSpec.IV_size]
268 buildSSLKey(&key_block
[i
], IVSize
, \
269 &pwSpec
->client
.write_iv_item
, \
270 "Domestic Client Write IV");
274 ** server_write_IV[CipherSpec.IV_size]
276 buildSSLKey(&key_block
[i
], IVSize
, \
277 &pwSpec
->server
.write_iv_item
, \
278 "Domestic Server Write IV");
282 PORT_Assert(i
<= block_bytes
);
285 ** Generate SSL3 Export write keys and IVs.
290 ** client_write_key[CipherSpec.key_material]
291 ** final_client_write_key = MD5(client_write_key +
292 ** ClientHello.random + ServerHello.random);
295 MD5_Update(md5Ctx
, &key_block
[i
], effKeySize
);
296 MD5_Update(md5Ctx
, crsr
.data
, crsr
.len
);
297 MD5_End(md5Ctx
, key_block2
, &outLen
, MD5_LENGTH
);
299 buildSSLKey(key_block2
, keySize
, &pwSpec
->client
.write_key_item
, \
300 "SSL3 Export Client Write Key");
301 key_block2
+= keySize
;
304 ** server_write_key[CipherSpec.key_material]
305 ** final_server_write_key = MD5(server_write_key +
306 ** ServerHello.random + ClientHello.random);
309 MD5_Update(md5Ctx
, &key_block
[i
], effKeySize
);
310 MD5_Update(md5Ctx
, srcr
.data
, srcr
.len
);
311 MD5_End(md5Ctx
, key_block2
, &outLen
, MD5_LENGTH
);
313 buildSSLKey(key_block2
, keySize
, &pwSpec
->server
.write_key_item
, \
314 "SSL3 Export Server Write Key");
315 key_block2
+= keySize
;
316 PORT_Assert(i
<= block_bytes
);
321 ** MD5(ClientHello.random + ServerHello.random);
324 MD5_Update(md5Ctx
, crsr
.data
, crsr
.len
);
325 MD5_End(md5Ctx
, key_block2
, &outLen
, MD5_LENGTH
);
326 buildSSLKey(key_block2
, IVSize
, &pwSpec
->client
.write_iv_item
, \
327 "SSL3 Export Client Write IV");
328 key_block2
+= IVSize
;
332 ** MD5(ServerHello.random + ClientHello.random);
335 MD5_Update(md5Ctx
, srcr
.data
, srcr
.len
);
336 MD5_End(md5Ctx
, key_block2
, &outLen
, MD5_LENGTH
);
337 buildSSLKey(key_block2
, IVSize
, &pwSpec
->server
.write_iv_item
, \
338 "SSL3 Export Server Write IV");
339 key_block2
+= IVSize
;
342 PORT_Assert(key_block2
- key_block
<= sizeof pwSpec
->key_block
);
345 ** Generate TLS Export write keys and IVs.
350 secret
.type
= siBuffer
;
351 keyblk
.type
= siBuffer
;
353 ** client_write_key[CipherSpec.key_material]
354 ** final_client_write_key = PRF(client_write_key,
355 ** "client write key",
356 ** client_random + server_random);
358 secret
.data
= &key_block
[i
];
359 secret
.len
= effKeySize
;
361 keyblk
.data
= key_block2
;
362 keyblk
.len
= keySize
;
363 status
= TLS_PRF(&secret
, "client write key", &crsr
, &keyblk
, isFIPS
);
364 if (status
!= SECSuccess
) {
365 goto key_and_mac_derive_fail
;
367 buildSSLKey(key_block2
, keySize
, &pwSpec
->client
.write_key_item
, \
368 "TLS Export Client Write Key");
369 key_block2
+= keySize
;
372 ** server_write_key[CipherSpec.key_material]
373 ** final_server_write_key = PRF(server_write_key,
374 ** "server write key",
375 ** client_random + server_random);
377 secret
.data
= &key_block
[i
];
378 secret
.len
= effKeySize
;
380 keyblk
.data
= key_block2
;
381 keyblk
.len
= keySize
;
382 status
= TLS_PRF(&secret
, "server write key", &crsr
, &keyblk
, isFIPS
);
383 if (status
!= SECSuccess
) {
384 goto key_and_mac_derive_fail
;
386 buildSSLKey(key_block2
, keySize
, &pwSpec
->server
.write_key_item
, \
387 "TLS Export Server Write Key");
388 key_block2
+= keySize
;
391 ** iv_block = PRF("", "IV block", client_random + server_random);
392 ** client_write_IV[SecurityParameters.IV_size]
393 ** server_write_IV[SecurityParameters.IV_size]
398 keyblk
.data
= key_block2
;
399 keyblk
.len
= 2 * IVSize
;
400 status
= TLS_PRF(&secret
, "IV block", &crsr
, &keyblk
, isFIPS
);
401 if (status
!= SECSuccess
) {
402 goto key_and_mac_derive_fail
;
404 buildSSLKey(key_block2
, IVSize
, \
405 &pwSpec
->client
.write_iv_item
, \
406 "TLS Export Client Write IV");
407 buildSSLKey(key_block2
+ IVSize
, IVSize
, \
408 &pwSpec
->server
.write_iv_item
, \
409 "TLS Export Server Write IV");
410 key_block2
+= 2 * IVSize
;
412 PORT_Assert(key_block2
- key_block
<= sizeof pwSpec
->key_block
);
416 key_and_mac_derive_fail
:
418 MD5_DestroyContext(md5Ctx
, PR_FALSE
);
419 SHA1_DestroyContext(shaCtx
, PR_FALSE
);
421 if (rv
!= SECSuccess
) {
422 PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE
);
429 /* derive the Master Secret from the PMS */
430 /* Presently, this is only done wtih RSA PMS, and only on the server side,
431 * so isRSA is always true.
434 ssl3_MasterKeyDeriveBypass(
435 ssl3CipherSpec
* pwSpec
,
436 const unsigned char * cr
,
437 const unsigned char * sr
,
442 unsigned char * key_block
= pwSpec
->key_block
;
443 SECStatus rv
= SECSuccess
;
444 PRBool isFIPS
= PR_FALSE
;
445 PRBool isTLS12
= pwSpec
->version
>= SSL_LIBRARY_VERSION_TLS_1_2
;
449 unsigned char crsrdata
[SSL3_RANDOM_LENGTH
* 2];
453 #define md5Ctx ((MD5Context *)md5buf)
454 #define shaCtx ((SHA1Context *)shabuf)
456 /* first do the consistancy checks */
458 PORT_Assert(pms
->len
== SSL3_RSA_PMS_LENGTH
);
459 if (pms
->len
!= SSL3_RSA_PMS_LENGTH
) {
460 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
463 /* caller must test PMS version for rollback */
466 /* initialize the client random, server random block */
467 crsr
.type
= siBuffer
;
468 crsr
.data
= crsrdata
;
469 crsr
.len
= sizeof crsrdata
;
470 PORT_Memcpy(crsrdata
, cr
, SSL3_RANDOM_LENGTH
);
471 PORT_Memcpy(crsrdata
+ SSL3_RANDOM_LENGTH
, sr
, SSL3_RANDOM_LENGTH
);
472 PRINT_BUF(100, (NULL
, "Master Secret CRSR", crsr
.data
, crsr
.len
));
474 /* finally do the key gen */
476 SECItem master
= { siBuffer
, NULL
, 0 };
478 master
.data
= key_block
;
479 master
.len
= SSL3_MASTER_SECRET_LENGTH
;
482 rv
= TLS_P_hash(HASH_AlgSHA256
, pms
, "master secret", &crsr
,
485 rv
= TLS_PRF(pms
, "master secret", &crsr
, &master
, isFIPS
);
487 if (rv
!= SECSuccess
) {
488 PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE
);
492 unsigned int made
= 0;
493 for (i
= 0; i
< 3; i
++) {
495 unsigned char sha_out
[SHA1_LENGTH
];
498 SHA1_Update(shaCtx
, (unsigned char*) mixers
[i
], i
+1);
499 SHA1_Update(shaCtx
, pms
->data
, pms
->len
);
500 SHA1_Update(shaCtx
, crsr
.data
, crsr
.len
);
501 SHA1_End(shaCtx
, sha_out
, &outLen
, SHA1_LENGTH
);
502 PORT_Assert(outLen
== SHA1_LENGTH
);
505 MD5_Update(md5Ctx
, pms
->data
, pms
->len
);
506 MD5_Update(md5Ctx
, sha_out
, outLen
);
507 MD5_End(md5Ctx
, key_block
+ made
, &outLen
, MD5_LENGTH
);
508 PORT_Assert(outLen
== MD5_LENGTH
);
513 /* store the results */
514 PORT_Memcpy(pwSpec
->raw_master_secret
, key_block
,
515 SSL3_MASTER_SECRET_LENGTH
);
516 pwSpec
->msItem
.data
= pwSpec
->raw_master_secret
;
517 pwSpec
->msItem
.len
= SSL3_MASTER_SECRET_LENGTH
;
518 PRINT_BUF(100, (NULL
, "Master Secret", pwSpec
->msItem
.data
,
519 pwSpec
->msItem
.len
));
525 ssl_canExtractMS(PK11SymKey
*pms
, PRBool isTLS
, PRBool isDH
, PRBool
*pcbp
)
527 PK11SymKey
* ms
= NULL
;
528 SECItem params
= {siBuffer
, NULL
, 0};
529 CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params
;
530 unsigned char rand
[SSL3_RANDOM_LENGTH
];
531 CK_VERSION pms_version
;
532 CK_MECHANISM_TYPE master_derive
;
533 CK_MECHANISM_TYPE key_derive
;
539 PORT_Memset(rand
, 0, SSL3_RANDOM_LENGTH
);
542 if(isDH
) master_derive
= CKM_TLS_MASTER_KEY_DERIVE_DH
;
543 else master_derive
= CKM_TLS_MASTER_KEY_DERIVE
;
544 key_derive
= CKM_TLS_KEY_AND_MAC_DERIVE
;
545 keyFlags
= CKF_SIGN
| CKF_VERIFY
;
547 if (isDH
) master_derive
= CKM_SSL3_MASTER_KEY_DERIVE_DH
;
548 else master_derive
= CKM_SSL3_MASTER_KEY_DERIVE
;
549 key_derive
= CKM_SSL3_KEY_AND_MAC_DERIVE
;
553 master_params
.pVersion
= &pms_version
;
554 master_params
.RandomInfo
.pClientRandom
= rand
;
555 master_params
.RandomInfo
.ulClientRandomLen
= SSL3_RANDOM_LENGTH
;
556 master_params
.RandomInfo
.pServerRandom
= rand
;
557 master_params
.RandomInfo
.ulServerRandomLen
= SSL3_RANDOM_LENGTH
;
559 params
.data
= (unsigned char *) &master_params
;
560 params
.len
= sizeof master_params
;
562 ms
= PK11_DeriveWithFlags(pms
, master_derive
, ¶ms
, key_derive
,
563 CKA_DERIVE
, 0, keyFlags
);
567 rv
= PK11_ExtractKeyValue(ms
);
568 *pcbp
= (rv
== SECSuccess
);
574 #endif /* !NO_PKCS11_BYPASS */
576 /* Check the key exchange algorithm for each cipher in the list to see if
577 * a master secret key can be extracted. If the KEA will use keys from the
578 * specified cert make sure the extract operation is attempted from the slot
579 * where the private key resides.
580 * If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and
581 * SECSuccess is returned. In all other cases but one (*pcanbypass) is
582 * set to FALSE and SECFailure is returned.
583 * In that last case Derive() has been called successfully but the MS is null,
584 * CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the
585 * arguments were all valid but the slot cannot be bypassed.
588 /* XXX Add SSL_CBP_TLS1_1 and test it in protocolmask when setting isTLS. */
591 SSL_CanBypass(CERTCertificate
*cert
, SECKEYPrivateKey
*srvPrivkey
,
592 PRUint32 protocolmask
, PRUint16
*ciphersuites
, int nsuites
,
593 PRBool
*pcanbypass
, void *pwArg
)
595 #ifdef NO_PKCS11_BYPASS
597 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
600 *pcanbypass
= PR_FALSE
;
606 PK11SymKey
* pms
= NULL
;
607 SECKEYPublicKey
* srvPubkey
= NULL
;
609 PK11SlotInfo
* slot
= NULL
;
612 CK_MECHANISM_TYPE mechanism_array
[2];
613 SECItem enc_pms
= {siBuffer
, NULL
, 0};
614 PRBool isTLS
= PR_FALSE
;
615 SSLCipherSuiteInfo csdef
;
616 PRBool testrsa
= PR_FALSE
;
617 PRBool testrsa_export
= PR_FALSE
;
618 PRBool testecdh
= PR_FALSE
;
619 PRBool testecdhe
= PR_FALSE
;
620 #ifdef NSS_ENABLE_ECC
621 SECKEYECParams ecParams
= { siBuffer
, NULL
, 0 };
624 if (!cert
|| !srvPrivkey
|| !ciphersuites
|| !pcanbypass
) {
625 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
629 srvPubkey
= CERT_ExtractPublicKey(cert
);
633 *pcanbypass
= PR_TRUE
;
636 /* determine which KEAs to test */
637 /* 0 (SSL_NULL_WITH_NULL_NULL) is used as a list terminator because
638 * SSL3 and TLS specs forbid negotiating that cipher suite number.
640 for (i
=0; i
< nsuites
&& (suite
= *ciphersuites
++) != 0; i
++) {
641 /* skip SSL2 cipher suites and ones NSS doesn't support */
642 if (SSL_GetCipherSuiteInfo(suite
, &csdef
, sizeof(csdef
)) != SECSuccess
643 || SSL_IS_SSL2_CIPHER(suite
) )
645 switch (csdef
.keaType
) {
647 switch (csdef
.cipherSuite
) {
648 case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA
:
649 case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA
:
650 case SSL_RSA_EXPORT_WITH_RC4_40_MD5
:
651 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
:
652 testrsa_export
= PR_TRUE
;
658 if (strcmp(csdef
.keaTypeName
, "ECDHE") == 0) /* ephemeral? */
664 /* this is actually DHE */
670 /* For each protocol try to derive and extract an MS.
671 * Failure of function any function except MS extract means
672 * continue with the next cipher test. Stop testing when the list is
673 * exhausted or when the first MS extract--not derive--fails.
675 privKeytype
= SECKEY_GetPrivateKeyType(srvPrivkey
);
676 protocolmask
&= SSL_CBP_SSL3
|SSL_CBP_TLS1_0
;
677 while (protocolmask
) {
678 if (protocolmask
& SSL_CBP_SSL3
) {
680 protocolmask
^= SSL_CBP_SSL3
;
683 protocolmask
^= SSL_CBP_TLS1_0
;
686 if (privKeytype
== rsaKey
&& testrsa_export
) {
687 if (PK11_GetPrivateModulusLen(srvPrivkey
) > EXPORT_RSA_KEY_LENGTH
) {
688 *pcanbypass
= PR_FALSE
;
694 for (; privKeytype
== rsaKey
&& testrsa
; ) {
696 unsigned char rsaPmsBuf
[SSL3_RSA_PMS_LENGTH
];
697 unsigned int outLen
= 0;
698 CK_MECHANISM_TYPE target
;
701 mechanism_array
[0] = CKM_SSL3_PRE_MASTER_KEY_GEN
;
702 mechanism_array
[1] = CKM_RSA_PKCS
;
704 slot
= PK11_GetBestSlotMultiple(mechanism_array
, 2, pwArg
);
706 PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND
);
710 /* Generate the pre-master secret ... (client side) */
711 version
.major
= 3 /*MSB(clientHelloVersion)*/;
712 version
.minor
= 0 /*LSB(clientHelloVersion)*/;
713 param
.data
= (unsigned char *)&version
;
714 param
.len
= sizeof version
;
715 pms
= PK11_KeyGen(slot
, CKM_SSL3_PRE_MASTER_KEY_GEN
, ¶m
, 0, pwArg
);
720 enc_pms
.len
= SECKEY_PublicKeyStrength(srvPubkey
);
721 enc_pms
.data
= (unsigned char*)PORT_Alloc(enc_pms
.len
);
722 if (enc_pms
.data
== NULL
) {
723 PORT_SetError(PR_OUT_OF_MEMORY_ERROR
);
726 irv
= PK11_PubWrapSymKey(CKM_RSA_PKCS
, srvPubkey
, pms
, &enc_pms
);
727 if (irv
!= SECSuccess
)
729 PK11_FreeSymKey(pms
);
731 /* now do the server side--check the triple bypass first */
732 rv
= PK11_PrivDecryptPKCS1(srvPrivkey
, rsaPmsBuf
, &outLen
,
734 (unsigned char *)enc_pms
.data
,
736 /* if decrypt worked we're done with the RSA test */
737 if (rv
== SECSuccess
) {
738 *pcanbypass
= PR_TRUE
;
741 /* check for fallback to double bypass */
742 target
= isTLS
? CKM_TLS_MASTER_KEY_DERIVE
743 : CKM_SSL3_MASTER_KEY_DERIVE
;
744 pms
= PK11_PubUnwrapSymKey(srvPrivkey
, &enc_pms
,
745 target
, CKA_DERIVE
, 0);
746 rv
= ssl_canExtractMS(pms
, isTLS
, PR_FALSE
, pcanbypass
);
747 if (rv
== SECSuccess
&& *pcanbypass
== PR_FALSE
)
752 /* Check for NULL to avoid double free.
753 * SECItem_FreeItem sets data NULL in secitem.c#265
755 if (enc_pms
.data
!= NULL
) {
756 SECITEM_FreeItem(&enc_pms
, PR_FALSE
);
758 #ifdef NSS_ENABLE_ECC
759 for (; (privKeytype
== ecKey
&& ( testecdh
|| testecdhe
)) ||
760 (privKeytype
== rsaKey
&& testecdhe
); ) {
761 CK_MECHANISM_TYPE target
;
762 SECKEYPublicKey
*keapub
= NULL
;
763 SECKEYPrivateKey
*keapriv
;
764 SECKEYPublicKey
*cpub
= NULL
; /* client's ephemeral ECDH keys */
765 SECKEYPrivateKey
*cpriv
= NULL
;
766 SECKEYECParams
*pecParams
= NULL
;
768 if (privKeytype
== ecKey
&& testecdhe
) {
769 /* TLS_ECDHE_ECDSA */
770 pecParams
= &srvPubkey
->u
.ec
.DEREncodedParams
;
771 } else if (privKeytype
== rsaKey
&& testecdhe
) {
774 int serverKeyStrengthInBits
;
775 int signatureKeyStrength
;
778 /* find a curve of equivalent strength to the RSA key's */
779 requiredECCbits
= PK11_GetPrivateModulusLen(srvPrivkey
);
780 if (requiredECCbits
< 0)
782 requiredECCbits
*= BPB
;
783 serverKeyStrengthInBits
= srvPubkey
->u
.rsa
.modulus
.len
;
784 if (srvPubkey
->u
.rsa
.modulus
.data
[0] == 0) {
785 serverKeyStrengthInBits
--;
787 /* convert to strength in bits */
788 serverKeyStrengthInBits
*= BPB
;
790 signatureKeyStrength
=
791 SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits
);
793 if ( requiredECCbits
> signatureKeyStrength
)
794 requiredECCbits
= signatureKeyStrength
;
797 ssl3_GetCurveWithECKeyStrength(
798 ssl3_GetSupportedECCurveMask(NULL
),
800 rv
= ssl3_ECName2Params(NULL
, ec_curve
, &ecParams
);
801 if (rv
== SECFailure
) {
804 pecParams
= &ecParams
;
808 /* generate server's ephemeral keys */
809 keapriv
= SECKEY_CreateECPrivateKey(pecParams
, &keapub
, NULL
);
810 if (!keapriv
|| !keapub
) {
812 SECKEY_DestroyPrivateKey(keapriv
);
814 SECKEY_DestroyPublicKey(keapub
);
815 PORT_SetError(SEC_ERROR_KEYGEN_FAIL
);
822 keapriv
= srvPrivkey
;
823 pecParams
= &srvPubkey
->u
.ec
.DEREncodedParams
;
826 /* perform client side ops */
827 /* generate a pair of ephemeral keys using server's parms */
828 cpriv
= SECKEY_CreateECPrivateKey(pecParams
, &cpub
, NULL
);
829 if (!cpriv
|| !cpub
) {
831 SECKEY_DestroyPrivateKey(keapriv
);
832 SECKEY_DestroyPublicKey(keapub
);
834 PORT_SetError(SEC_ERROR_KEYGEN_FAIL
);
838 /* now do the server side */
839 /* determine the PMS using client's public value */
840 target
= isTLS
? CKM_TLS_MASTER_KEY_DERIVE_DH
841 : CKM_SSL3_MASTER_KEY_DERIVE_DH
;
842 pms
= PK11_PubDeriveWithKDF(keapriv
, cpub
, PR_FALSE
, NULL
, NULL
,
845 CKA_DERIVE
, 0, CKD_NULL
, NULL
, NULL
);
846 rv
= ssl_canExtractMS(pms
, isTLS
, PR_TRUE
, pcanbypass
);
847 SECKEY_DestroyPrivateKey(cpriv
);
848 SECKEY_DestroyPublicKey(cpub
);
850 SECKEY_DestroyPrivateKey(keapriv
);
851 SECKEY_DestroyPublicKey(keapub
);
853 if (rv
== SECSuccess
&& *pcanbypass
== PR_FALSE
)
857 /* Check for NULL to avoid double free. */
858 if (ecParams
.data
!= NULL
) {
859 PORT_Free(ecParams
.data
);
860 ecParams
.data
= NULL
;
862 #endif /* NSS_ENABLE_ECC */
864 PK11_FreeSymKey(pms
);
867 /* *pcanbypass has been set */
872 PK11_FreeSymKey(pms
);
874 /* Check for NULL to avoid double free.
875 * SECItem_FreeItem sets data NULL in secitem.c#265
877 if (enc_pms
.data
!= NULL
) {
878 SECITEM_FreeItem(&enc_pms
, PR_FALSE
);
880 #ifdef NSS_ENABLE_ECC
881 if (ecParams
.data
!= NULL
) {
882 PORT_Free(ecParams
.data
);
883 ecParams
.data
= NULL
;
885 #endif /* NSS_ENABLE_ECC */
888 SECKEY_DestroyPublicKey(srvPubkey
);
894 #endif /* NO_PKCS11_BYPASS */