Bug 325672, add canbypass function
r=nelson, julien git-svn-id: svn://10.0.0.236/branches/NSS_3_11_BRANCH@228612 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -36,7 +36,7 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: derive.c,v 1.3.2.1 2006-08-24 22:31:54 nelson%bolyard.com Exp $ */
|
||||
/* $Id: derive.c,v 1.3.2.2 2007-06-23 01:33:33 neil.williams%sun.com Exp $ */
|
||||
|
||||
#include "ssl.h" /* prereq to sslimpl.h */
|
||||
#include "certt.h" /* prereq to sslimpl.h */
|
||||
@@ -44,6 +44,15 @@
|
||||
#include "sslimpl.h"
|
||||
#include "blapi.h"
|
||||
|
||||
#include "secutil.h"
|
||||
#include "pk11func.h"
|
||||
#include "secasn1.h"
|
||||
#include "cert.h"
|
||||
#include "secmodt.h"
|
||||
|
||||
#include "sslproto.h"
|
||||
#include "sslerr.h"
|
||||
|
||||
/* make this a macro! */
|
||||
#ifdef NOT_A_MACRO
|
||||
static void
|
||||
@@ -490,4 +499,331 @@ ssl3_MasterKeyDeriveBypass(
|
||||
return rv;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
ssl_canExtractMS(PK11SymKey *pms, PRBool isTLS, PRBool isDH, PRBool *pcbp)
|
||||
{ SECStatus rv;
|
||||
PK11SymKey * ms = NULL;
|
||||
SECItem params = {siBuffer, NULL, 0};
|
||||
CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;
|
||||
unsigned char rand[SSL3_RANDOM_LENGTH];
|
||||
CK_VERSION pms_version;
|
||||
CK_MECHANISM_TYPE master_derive;
|
||||
CK_MECHANISM_TYPE key_derive;
|
||||
CK_FLAGS keyFlags;
|
||||
|
||||
if (pms == NULL)
|
||||
return(SECFailure);
|
||||
|
||||
PORT_Memset(rand, 0, SSL3_RANDOM_LENGTH);
|
||||
|
||||
if (isTLS) {
|
||||
if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
|
||||
else master_derive = CKM_TLS_MASTER_KEY_DERIVE;
|
||||
key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
|
||||
keyFlags = CKF_SIGN | CKF_VERIFY;
|
||||
} else {
|
||||
if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH;
|
||||
else master_derive = CKM_SSL3_MASTER_KEY_DERIVE;
|
||||
key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
|
||||
keyFlags = 0;
|
||||
}
|
||||
|
||||
master_params.pVersion = &pms_version;
|
||||
master_params.RandomInfo.pClientRandom = rand;
|
||||
master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
|
||||
master_params.RandomInfo.pServerRandom = rand;
|
||||
master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
|
||||
|
||||
params.data = (unsigned char *) &master_params;
|
||||
params.len = sizeof master_params;
|
||||
|
||||
ms = PK11_DeriveWithFlags(pms, master_derive, ¶ms, key_derive,
|
||||
CKA_DERIVE, 0, keyFlags);
|
||||
if (ms == NULL)
|
||||
return(SECFailure);
|
||||
|
||||
rv = PK11_ExtractKeyValue(ms);
|
||||
*pcbp = (rv == SECSuccess);
|
||||
PK11_FreeSymKey(ms);
|
||||
|
||||
return(rv);
|
||||
|
||||
}
|
||||
|
||||
/* Check the key exchange algorithm for each cipher in the list to see if
|
||||
* a master secret key can be extracted. If the KEA will use keys from the
|
||||
* specified cert make sure the extract operation is attempted from the slot
|
||||
* where the private key resides.
|
||||
* If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and
|
||||
* SECSuccess is returned. In all other cases but one (*pcanbypass) is
|
||||
* set to FALSE and SECFailure is returned.
|
||||
* In that last case Derive() has been called successfully but the MS is null,
|
||||
* CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the
|
||||
* arguments were all valid but the slot cannot be bypassed.
|
||||
*/
|
||||
|
||||
SECStatus
|
||||
SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey,
|
||||
PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites,
|
||||
PRBool *pcanbypass, void *pwArg)
|
||||
{ SECStatus rv;
|
||||
int i;
|
||||
PRUint16 suite;
|
||||
PK11SymKey * pms = NULL;
|
||||
SECKEYPublicKey * srvPubkey = NULL;
|
||||
KeyType privKeytype;
|
||||
PK11SlotInfo * slot = NULL;
|
||||
SECItem param;
|
||||
CK_VERSION version;
|
||||
CK_MECHANISM_TYPE mechanism_array[2];
|
||||
SECItem enc_pms = {siBuffer, NULL, 0};
|
||||
PRBool isTLS = PR_FALSE;
|
||||
PRBool isDH = PR_FALSE;
|
||||
SSLCipherSuiteInfo csdef;
|
||||
PRBool extractable;
|
||||
PRBool testrsa = PR_FALSE;
|
||||
PRBool testrsa_export = PR_FALSE;
|
||||
PRBool testecdh = PR_FALSE;
|
||||
PRBool testecdhe = PR_FALSE;
|
||||
|
||||
if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
srvPubkey = CERT_ExtractPublicKey(cert);
|
||||
if (!srvPubkey)
|
||||
return SECFailure;
|
||||
|
||||
*pcanbypass = PR_TRUE;
|
||||
rv = SECFailure;
|
||||
|
||||
/* determine which KEAs to test */
|
||||
for (i=0; i < nsuites && (suite = *ciphersuites++) != NULL; i++) {
|
||||
/* skip SSL2 cipher suites and ones NSS doesn't support */
|
||||
if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess
|
||||
|| SSL_IS_SSL2_CIPHER(suite) )
|
||||
continue;
|
||||
switch (csdef.keaType) {
|
||||
case ssl_kea_rsa:
|
||||
switch (csdef.cipherSuite) {
|
||||
case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA:
|
||||
case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA:
|
||||
case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
|
||||
case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
|
||||
testrsa_export = PR_TRUE;
|
||||
}
|
||||
if (!testrsa_export)
|
||||
testrsa = PR_TRUE;
|
||||
break;
|
||||
case ssl_kea_ecdh:
|
||||
if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */
|
||||
testecdhe = PR_TRUE;
|
||||
else
|
||||
testecdh = PR_TRUE;
|
||||
break;
|
||||
case ssl_kea_dh:
|
||||
/* this is actually DHE */
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* For each protocol try to derive and extract an MS.
|
||||
* Failure of any function except MS extract means
|
||||
* continue with the next cipher test. Stop testing when the list is
|
||||
* exhausted or when the first MS extract--not derive--fails.
|
||||
*/
|
||||
privKeytype = SECKEY_GetPrivateKeyType(srvPrivkey);
|
||||
protocolmask &= SSL_CBP_SSL3|SSL_CBP_TLS1_0;
|
||||
while (protocolmask) {
|
||||
if (protocolmask & SSL_CBP_SSL3) {
|
||||
isTLS = PR_FALSE;
|
||||
protocolmask ^= SSL_CBP_SSL3;
|
||||
} else {
|
||||
isTLS = PR_TRUE;
|
||||
protocolmask ^= SSL_CBP_TLS1_0;
|
||||
}
|
||||
|
||||
if (privKeytype == rsaKey && testrsa_export) {
|
||||
if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) {
|
||||
*pcanbypass = PR_FALSE;
|
||||
rv = SECSuccess;
|
||||
break;
|
||||
} else
|
||||
testrsa = PR_TRUE;
|
||||
}
|
||||
for (; privKeytype == rsaKey && testrsa; ) {
|
||||
/* TLS_RSA */
|
||||
unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
|
||||
unsigned int outLen = 0;
|
||||
CK_MECHANISM_TYPE target;
|
||||
SECStatus irv;
|
||||
|
||||
mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
|
||||
mechanism_array[1] = CKM_RSA_PKCS;
|
||||
|
||||
slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
|
||||
if (slot == NULL) {
|
||||
PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Generate the pre-master secret ... (client side) */
|
||||
version.major = 3 /*MSB(clientHelloVersion)*/;
|
||||
version.minor = 0 /*LSB(clientHelloVersion)*/;
|
||||
param.data = (unsigned char *)&version;
|
||||
param.len = sizeof version;
|
||||
pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, ¶m, 0, pwArg);
|
||||
PK11_FreeSlot(slot);
|
||||
if (!pms)
|
||||
break;
|
||||
/* now wrap it */
|
||||
enc_pms.len = SECKEY_PublicKeyStrength(srvPubkey);
|
||||
enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len);
|
||||
irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms);
|
||||
if (irv != SECSuccess)
|
||||
break;
|
||||
PK11_FreeSymKey(pms);
|
||||
/* now do the server side--check the triple bypass first */
|
||||
rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen,
|
||||
sizeof rsaPmsBuf,
|
||||
(unsigned char *)enc_pms.data,
|
||||
enc_pms.len);
|
||||
/* if decrypt worked we're done with the RSA test */
|
||||
if (rv == SECSuccess) {
|
||||
*pcanbypass = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
/* check for fallback to double bypass */
|
||||
target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE
|
||||
: CKM_SSL3_MASTER_KEY_DERIVE;
|
||||
pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms,
|
||||
target, CKA_DERIVE, 0);
|
||||
rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass);
|
||||
if (rv == SECSuccess && *pcanbypass == PR_FALSE)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
for (; (privKeytype == ecKey && ( testecdh || testecdhe)) ||
|
||||
(privKeytype == rsaKey && testecdhe); ) {
|
||||
CK_MECHANISM_TYPE target;
|
||||
SECKEYPublicKey *keapub = NULL;
|
||||
SECKEYPrivateKey *keapriv;
|
||||
SECKEYPublicKey *cpub = NULL; /* client's ephemeral ECDH keys */
|
||||
SECKEYPrivateKey *cpriv = NULL;
|
||||
SECKEYECParams ecParams = { siBuffer, NULL, 0 },
|
||||
*pecParams;
|
||||
|
||||
if (privKeytype == ecKey && testecdhe) {
|
||||
/* TLS_ECDHE_ECDSA */
|
||||
pecParams = &srvPubkey->u.ec.DEREncodedParams;
|
||||
} else if (privKeytype == rsaKey && testecdhe) {
|
||||
/* TLS_ECDHE_RSA */
|
||||
ECName ec_curve;
|
||||
int serverKeyStrengthInBits;
|
||||
int signatureKeyStrength;
|
||||
int requiredECCbits;
|
||||
|
||||
/* find a curve of equivalent strength to the RSA key's */
|
||||
requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey);
|
||||
if (requiredECCbits < 0)
|
||||
break;
|
||||
requiredECCbits *= BPB;
|
||||
serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len;
|
||||
if (srvPubkey->u.rsa.modulus.data[0] == 0) {
|
||||
serverKeyStrengthInBits--;
|
||||
}
|
||||
/* convert to strength in bits */
|
||||
serverKeyStrengthInBits *= BPB;
|
||||
|
||||
signatureKeyStrength =
|
||||
SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
|
||||
|
||||
if ( requiredECCbits > signatureKeyStrength )
|
||||
requiredECCbits = signatureKeyStrength;
|
||||
|
||||
ec_curve =
|
||||
ssl3_GetCurveWithECKeyStrength(SSL3_SUPPORTED_CURVES_MASK,
|
||||
requiredECCbits);
|
||||
rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams);
|
||||
if (rv == SECFailure) {
|
||||
break;
|
||||
}
|
||||
pecParams = &ecParams;
|
||||
}
|
||||
|
||||
if (testecdhe) {
|
||||
/* generate server's ephemeral keys */
|
||||
keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL);
|
||||
if (!keapriv || !keapub) {
|
||||
if (keapriv)
|
||||
SECKEY_DestroyPrivateKey(keapriv);
|
||||
if (keapub)
|
||||
SECKEY_DestroyPublicKey(keapub);
|
||||
PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* TLS_ECDH_ECDSA */
|
||||
keapub = srvPubkey;
|
||||
keapriv = srvPrivkey;
|
||||
pecParams = &srvPubkey->u.ec.DEREncodedParams;
|
||||
}
|
||||
|
||||
/* perform client side ops */
|
||||
/* generate a pair of ephemeral keys using server's parms */
|
||||
cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL);
|
||||
if (!cpriv || !cpub) {
|
||||
if (testecdhe) {
|
||||
SECKEY_DestroyPrivateKey(keapriv);
|
||||
SECKEY_DestroyPublicKey(keapub);
|
||||
}
|
||||
PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
/* now do the server side */
|
||||
/* determine the PMS using client's public value */
|
||||
target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH
|
||||
: CKM_SSL3_MASTER_KEY_DERIVE_DH;
|
||||
pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL,
|
||||
CKM_ECDH1_DERIVE,
|
||||
target,
|
||||
CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
|
||||
rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass);
|
||||
SECKEY_DestroyPrivateKey(cpriv);
|
||||
SECKEY_DestroyPublicKey(cpub);
|
||||
if (testecdhe) {
|
||||
SECKEY_DestroyPrivateKey(keapriv);
|
||||
SECKEY_DestroyPublicKey(keapub);
|
||||
if (privKeytype == rsaKey)
|
||||
PORT_Free(ecParams.data);
|
||||
}
|
||||
if (rv == SECSuccess && *pcanbypass == PR_FALSE)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
if (pms)
|
||||
PK11_FreeSymKey(pms);
|
||||
}
|
||||
|
||||
/* *pcanbypass has been set */
|
||||
rv = SECSuccess;
|
||||
|
||||
done:
|
||||
if (pms)
|
||||
PK11_FreeSymKey(pms);
|
||||
|
||||
if (srvPubkey) {
|
||||
SECKEY_DestroyPublicKey(srvPubkey);
|
||||
srvPubkey = NULL;
|
||||
}
|
||||
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
@@ -133,3 +133,9 @@ SSL_ReHandshakeWithTimeout;
|
||||
;+ local:
|
||||
;+*;
|
||||
;+};
|
||||
;+NSS_3.11.7 { # NSS 3.11.7 release
|
||||
;+ global:
|
||||
SSL_CanBypass;
|
||||
;+ local:
|
||||
;+*;
|
||||
;+};
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: ssl.h,v 1.24 2005-09-16 20:33:09 julien.pierre.bugs%sun.com Exp $ */
|
||||
/* $Id: ssl.h,v 1.24.2.1 2007-06-23 01:33:33 neil.williams%sun.com Exp $ */
|
||||
|
||||
#ifndef __ssl_h_
|
||||
#define __ssl_h_
|
||||
@@ -474,6 +474,37 @@ SSL_IMPORT SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
|
||||
*/
|
||||
SSL_IMPORT CERTCertificate * SSL_LocalCertificate(PRFileDesc *fd);
|
||||
|
||||
/* Test an SSL configuration to see if SSL_BYPASS_PKCS11 can be turned on.
|
||||
** Check the key exchange algorithm for each cipher in the list to see if
|
||||
** a master secret key can be extracted after being derived with the mechanism
|
||||
** required by the protocolmask argument. If the KEA will use keys from the
|
||||
** specified cert make sure the extract operation is attempted from the slot
|
||||
** where the private key resides.
|
||||
** If MS can be extracted for all ciphers, (*pcanbypass) is set to TRUE and
|
||||
** SECSuccess is returned. In all other cases but one (*pcanbypass) is
|
||||
** set to FALSE and SECFailure is returned.
|
||||
** In that last case Derive() has been called successfully but the MS is null,
|
||||
** CanBypass sets (*pcanbypass) to FALSE and returns SECSuccess indicating the
|
||||
** arguments were all valid but the slot cannot be bypassed.
|
||||
**
|
||||
** Note: A TRUE return code from CanBypass means "Your configuration will perform
|
||||
** NO WORSE with the bypass enabled than without"; it does NOT mean that every
|
||||
** cipher suite listed will work properly with the selected protocols.
|
||||
**
|
||||
** Caveat: If export cipher suites are included in the argument list Canbypass
|
||||
** will return FALSE.
|
||||
**/
|
||||
|
||||
/* protocol mask bits */
|
||||
#define SSL_CBP_SSL3 0x0001 /* test SSL v3 mechanisms */
|
||||
#define SSL_CBP_TLS1_0 0x0002 /* test TLS v1.0 mechanisms */
|
||||
|
||||
SSL_IMPORT SECStatus SSL_CanBypass(CERTCertificate *cert,
|
||||
SECKEYPrivateKey *privKey,
|
||||
PRUint32 protocolmask,
|
||||
PRUint16 *ciphers, int nciphers,
|
||||
PRBool *pcanbypass, void *pwArg);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* __ssl_h_ */
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* ECC code moved here from ssl3con.c */
|
||||
/* $Id: ssl3ecc.c,v 1.3.2.11 2007-01-04 17:48:31 wtchang%redhat.com Exp $ */
|
||||
/* $Id: ssl3ecc.c,v 1.3.2.12 2007-06-23 01:33:33 neil.williams%sun.com Exp $ */
|
||||
|
||||
#include "nssrenam.h"
|
||||
#include "nss.h"
|
||||
@@ -80,45 +80,12 @@
|
||||
(ss->serverCerts[type].serverKeyPair ? \
|
||||
ss->serverCerts[type].serverKeyPair->pubKey : NULL)
|
||||
|
||||
#define SSL_IS_CURVE_NEGOTIATED(ss, curveName) \
|
||||
#define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \
|
||||
((curveName > ec_noName) && \
|
||||
(curveName < ec_pastLastName) && \
|
||||
((1UL << curveName) & ss->ssl3.hs.negotiatedECCurves) != 0)
|
||||
((1UL << curveName) & curvemsk) != 0)
|
||||
|
||||
/* Types and names of elliptic curves used in TLS */
|
||||
typedef enum { ec_type_explicitPrime = 1,
|
||||
ec_type_explicitChar2Curve = 2,
|
||||
ec_type_named
|
||||
} ECType;
|
||||
|
||||
typedef enum { ec_noName = 0,
|
||||
ec_sect163k1 = 1,
|
||||
ec_sect163r1 = 2,
|
||||
ec_sect163r2 = 3,
|
||||
ec_sect193r1 = 4,
|
||||
ec_sect193r2 = 5,
|
||||
ec_sect233k1 = 6,
|
||||
ec_sect233r1 = 7,
|
||||
ec_sect239k1 = 8,
|
||||
ec_sect283k1 = 9,
|
||||
ec_sect283r1 = 10,
|
||||
ec_sect409k1 = 11,
|
||||
ec_sect409r1 = 12,
|
||||
ec_sect571k1 = 13,
|
||||
ec_sect571r1 = 14,
|
||||
ec_secp160k1 = 15,
|
||||
ec_secp160r1 = 16,
|
||||
ec_secp160r2 = 17,
|
||||
ec_secp192k1 = 18,
|
||||
ec_secp192r1 = 19,
|
||||
ec_secp224k1 = 20,
|
||||
ec_secp224r1 = 21,
|
||||
ec_secp256k1 = 22,
|
||||
ec_secp256r1 = 23,
|
||||
ec_secp384r1 = 24,
|
||||
ec_secp521r1 = 25,
|
||||
ec_pastLastName
|
||||
} ECName;
|
||||
|
||||
static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve);
|
||||
|
||||
@@ -229,8 +196,8 @@ typedef struct ECDHEKeyPairStr {
|
||||
/* arrays of ECDHE KeyPairs */
|
||||
static ECDHEKeyPair gECDHEKeyPairs[ec_pastLastName];
|
||||
|
||||
static SECStatus
|
||||
ecName2params(PRArenaPool * arena, ECName curve, SECKEYECParams * params)
|
||||
SECStatus
|
||||
ssl3_ECName2Params(PRArenaPool * arena, ECName curve, SECKEYECParams * params)
|
||||
{
|
||||
SECOidData *oidData = NULL;
|
||||
|
||||
@@ -470,6 +437,22 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
ECName
|
||||
ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits)
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; bits2curve[i].curve != ec_noName; i++) {
|
||||
if (bits2curve[i].bits < requiredECCbits)
|
||||
continue;
|
||||
if (SSL_IS_CURVE_NEGOTIATED(curvemsk, bits2curve[i].curve)) {
|
||||
return bits2curve[i].curve;
|
||||
}
|
||||
}
|
||||
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
|
||||
return ec_noName;
|
||||
}
|
||||
|
||||
/* find the "weakest link". Get strength of signature key and of sym key.
|
||||
* choose curve for the weakest of those two.
|
||||
*/
|
||||
@@ -486,7 +469,7 @@ ssl3_GetCurveNameForServerSocket(sslSocket *ss)
|
||||
svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh);
|
||||
if (svrPublicKey)
|
||||
ec_curve = params2ecName(&svrPublicKey->u.ec.DEREncodedParams);
|
||||
if (!SSL_IS_CURVE_NEGOTIATED(ss, ec_curve)) {
|
||||
if (!SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, ec_curve)) {
|
||||
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
|
||||
return ec_noName;
|
||||
}
|
||||
@@ -509,30 +492,14 @@ ssl3_GetCurveNameForServerSocket(sslSocket *ss)
|
||||
/* convert to strength in bits */
|
||||
serverKeyStrengthInBits *= BPB;
|
||||
|
||||
if (serverKeyStrengthInBits <= 1024) {
|
||||
signatureKeyStrength = 160;
|
||||
} else if (serverKeyStrengthInBits <= 2048) {
|
||||
signatureKeyStrength = 224;
|
||||
} else if (serverKeyStrengthInBits <= 3072) {
|
||||
signatureKeyStrength = 256;
|
||||
} else if (serverKeyStrengthInBits <= 7168) {
|
||||
signatureKeyStrength = 384;
|
||||
} else {
|
||||
signatureKeyStrength = 521;
|
||||
}
|
||||
signatureKeyStrength =
|
||||
SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
|
||||
}
|
||||
if ( requiredECCbits > signatureKeyStrength )
|
||||
requiredECCbits = signatureKeyStrength;
|
||||
|
||||
for ( i = 0; bits2curve[i].curve != ec_noName; i++) {
|
||||
if (bits2curve[i].bits < requiredECCbits)
|
||||
continue;
|
||||
if (SSL_IS_CURVE_NEGOTIATED(ss, bits2curve[i].curve)) {
|
||||
return bits2curve[i].curve;
|
||||
}
|
||||
}
|
||||
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
|
||||
return ec_noName;
|
||||
return ssl3_GetCurveWithECKeyStrength(ss->ssl3.hs.negotiatedECCurves,
|
||||
requiredECCbits);
|
||||
}
|
||||
|
||||
/* function to clear out the lists */
|
||||
@@ -575,7 +542,7 @@ ssl3_CreateECDHEphemeralKeyPair(void * arg)
|
||||
PORT_Assert(gECDHEKeyPairs[ec_curve].pair == NULL);
|
||||
|
||||
/* ok, no one has generated a global key for this curve yet, do so */
|
||||
if (ecName2params(NULL, ec_curve, &ecParams) != SECSuccess) {
|
||||
if (ssl3_ECName2Params(NULL, ec_curve, &ecParams) != SECSuccess) {
|
||||
gECDHEKeyPairs[ec_curve].error = PORT_GetError();
|
||||
return PR_FAILURE;
|
||||
}
|
||||
@@ -742,7 +709,7 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
|
||||
peerKey->keyType = ecKey;
|
||||
|
||||
/* set up EC parameters in peerKey */
|
||||
if (ecName2params(arena, ec_params.data[2],
|
||||
if (ssl3_ECName2Params(arena, ec_params.data[2],
|
||||
&peerKey->u.ec.DEREncodedParams) != SECSuccess) {
|
||||
/* we should never get here since we already
|
||||
* checked that we are dealing with a supported curve
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: sslimpl.h,v 1.42.2.10 2007-05-01 06:09:31 nelson%bolyard.com Exp $ */
|
||||
/* $Id: sslimpl.h,v 1.42.2.11 2007-06-23 01:33:33 neil.williams%sun.com Exp $ */
|
||||
|
||||
#ifndef __sslimpl_h_
|
||||
#define __sslimpl_h_
|
||||
@@ -190,6 +190,8 @@ typedef enum { SSLAppOpRead = 0,
|
||||
#define BPB 8 /* Bits Per Byte */
|
||||
#endif
|
||||
|
||||
#define EXPORT_RSA_KEY_LENGTH 64 /* bytes */
|
||||
|
||||
typedef struct sslBufferStr sslBuffer;
|
||||
typedef struct sslConnectInfoStr sslConnectInfo;
|
||||
typedef struct sslGatherStr sslGather;
|
||||
@@ -1280,6 +1282,54 @@ extern void ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss);
|
||||
extern PRBool ssl3_IsECCEnabled(sslSocket *ss);
|
||||
extern SECStatus ssl3_DisableECCSuites(sslSocket * ss,
|
||||
const ssl3CipherSuite * suite);
|
||||
|
||||
/* Macro for finding a curve equivalent in strength to RSA key's */
|
||||
#define SSL_RSASTRENGTH_TO_ECSTRENGTH(s) \
|
||||
((s <= 1024) ? 160 \
|
||||
: ((s <= 2048) ? 224 \
|
||||
: ((s <= 3072) ? 256 \
|
||||
: ((s <= 7168) ? 384 : 521 ) ) ) )
|
||||
|
||||
/* Types and names of elliptic curves used in TLS */
|
||||
typedef enum { ec_type_explicitPrime = 1,
|
||||
ec_type_explicitChar2Curve = 2,
|
||||
ec_type_named
|
||||
} ECType;
|
||||
|
||||
typedef enum { ec_noName = 0,
|
||||
ec_sect163k1 = 1,
|
||||
ec_sect163r1 = 2,
|
||||
ec_sect163r2 = 3,
|
||||
ec_sect193r1 = 4,
|
||||
ec_sect193r2 = 5,
|
||||
ec_sect233k1 = 6,
|
||||
ec_sect233r1 = 7,
|
||||
ec_sect239k1 = 8,
|
||||
ec_sect283k1 = 9,
|
||||
ec_sect283r1 = 10,
|
||||
ec_sect409k1 = 11,
|
||||
ec_sect409r1 = 12,
|
||||
ec_sect571k1 = 13,
|
||||
ec_sect571r1 = 14,
|
||||
ec_secp160k1 = 15,
|
||||
ec_secp160r1 = 16,
|
||||
ec_secp160r2 = 17,
|
||||
ec_secp192k1 = 18,
|
||||
ec_secp192r1 = 19,
|
||||
ec_secp224k1 = 20,
|
||||
ec_secp224r1 = 21,
|
||||
ec_secp256k1 = 22,
|
||||
ec_secp256r1 = 23,
|
||||
ec_secp384r1 = 24,
|
||||
ec_secp521r1 = 25,
|
||||
ec_pastLastName
|
||||
} ECName;
|
||||
|
||||
extern SECStatus ssl3_ECName2Params(PRArenaPool *arena, ECName curve,
|
||||
SECKEYECParams *params);
|
||||
ECName ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits);
|
||||
|
||||
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
extern SECStatus ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool on);
|
||||
@@ -1420,6 +1470,7 @@ PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite);
|
||||
#endif
|
||||
|
||||
void ssl_Trace(const char *format, ...);
|
||||
ECName ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
|
||||
Reference in New Issue
Block a user