Bug 325672, Create CanBypass function

r=Nelson


git-svn-id: svn://10.0.0.236/trunk@230235 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
neil.williams%sun.com
2007-07-18 21:38:55 +00:00
parent 811a46363f
commit f4f094b47f
6 changed files with 519 additions and 69 deletions

View File

@@ -190,6 +190,7 @@ Usage(const char *progName)
"-S means disable SSL v2\n"
"-3 means disable SSL v3\n"
"-B bypasses the PKCS11 layer for SSL encryption and MACing\n"
"-q checks for bypassability\n"
"-D means disable Nagle delays in TCP\n"
"-E means disable export ciphersuites and SSL step down key gen\n"
"-T means disable TLS\n"
@@ -659,6 +660,7 @@ PRBool hasSidCache = PR_FALSE;
PRBool disableStepDown = PR_FALSE;
PRBool bypassPKCS11 = PR_FALSE;
PRBool disableLocking = PR_FALSE;
PRBool testbypass = PR_FALSE;
static const char stopCmd[] = { "GET /stop " };
static const char getCmd[] = { "GET " };
@@ -672,6 +674,17 @@ static const char outHeader[] = {
};
static const char crlCacheErr[] = { "CRL ReCache Error: " };
PRUint16 cipherlist[100];
int nciphers;
void
savecipher(int c)
{
if (nciphers < sizeof cipherlist / sizeof (cipherlist[0]))
cipherlist[nciphers++] = (PRUint16)c;
}
#ifdef FULL_DUPLEX_CAPABLE
struct lockedVarsStr {
@@ -1675,7 +1688,8 @@ main(int argc, char **argv)
PRBool debugCache = PR_FALSE; /* bug 90518 */
char emptyString[] = { "" };
char* certPrefix = emptyString;
PRUint32 protos = 0;
tmp = strrchr(argv[0], '/');
tmp = tmp ? tmp + 1 : argv[0];
progName = strrchr(tmp, '\\');
@@ -1687,7 +1701,7 @@ main(int argc, char **argv)
** numbers, then capital letters, then lower case, alphabetical.
*/
optstate = PL_CreateOptState(argc, argv,
"2:3BC:DEL:M:NP:RSTbc:d:e:f:hi:lmn:op:rst:vw:xy");
"2:3BC:DEL:M:NP:RSTbc:d:e:f:hi:lmn:op:qrst:vw:xy");
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
++optionsFound;
switch(optstate->option) {
@@ -1754,6 +1768,8 @@ main(int argc, char **argv)
case 'p': port = PORT_Atoi(optstate->value); break;
case 'q': testbypass = PR_TRUE; break;
case 'r': ++requestCert; break;
case 's': disableLocking = PR_TRUE; break;
@@ -1977,6 +1993,20 @@ main(int argc, char **argv)
PORT_Free(cstringSaved);
}
if (testbypass) {
const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
int i = SSL_NumImplementedCiphers;
PRBool enabled;
for (i=0; i < SSL_NumImplementedCiphers; i++, cipherSuites++) {
if (SSL_CipherPrefGetDefault(*cipherSuites, &enabled) == SECSuccess
&& enabled)
savecipher(*cipherSuites);
}
protos = (disableTLS ? 0 : SSL_CBP_TLS1_0) +
(disableSSL3 ? 0 : SSL_CBP_SSL3);
}
if (nickName) {
cert[kt_rsa] = PK11_FindCertFromNickname(nickName, passwd);
if (cert[kt_rsa] == NULL) {
@@ -1989,6 +2019,16 @@ main(int argc, char **argv)
nickName);
exit(11);
}
if (testbypass) {
PRBool bypassOK;
if (SSL_CanBypass(cert[kt_rsa], privKey[kt_rsa], protos, cipherlist,
nciphers, &bypassOK, passwd) != SECSuccess) {
SECU_PrintError(progName, "Bypass test failed %s\n", nickName);
exit(14);
}
fprintf(stderr, "selfserv: %s can%s bypass\n", nickName,
bypassOK ? "" : "not");
}
}
if (fNickName) {
cert[kt_fortezza] = PK11_FindCertFromNickname(fNickName, NULL);
@@ -2000,17 +2040,35 @@ main(int argc, char **argv)
}
#ifdef NSS_ENABLE_ECC
if (ecNickName) {
cert[kt_ecdh] = PK11_FindCertFromNickname(ecNickName, NULL);
cert[kt_ecdh] = PK11_FindCertFromNickname(ecNickName, passwd);
if (cert[kt_ecdh] == NULL) {
fprintf(stderr, "selfserv: Can't find certificate %s\n",
ecNickName);
exit(13);
}
privKey[kt_ecdh] = PK11_FindKeyByAnyCert(cert[kt_ecdh], NULL);
privKey[kt_ecdh] = PK11_FindKeyByAnyCert(cert[kt_ecdh], passwd);
if (privKey[kt_ecdh] == NULL) {
fprintf(stderr, "selfserv: Can't find Private Key for cert %s\n",
ecNickName);
exit(11);
}
if (testbypass) {
PRBool bypassOK;
if (SSL_CanBypass(cert[kt_ecdh], privKey[kt_ecdh], protos, cipherlist,
nciphers, &bypassOK, passwd) != SECSuccess) {
SECU_PrintError(progName, "Bypass test failed %s\n", ecNickName);
exit(15);
}
fprintf(stderr, "selfserv: %s can%s bypass\n", ecNickName,
bypassOK ? "" : "not");
}
}
#endif /* NSS_ENABLE_ECC */
/* allocate the array of thread slots, and launch the worker threads. */
if (testbypass)
goto cleanup;
/* allocate the array of thread slots, and launch the worker threads. */
rv = launch_threads(&jobLoop, 0, 0, requestCert, useLocalThreads);
if (rv == SECSuccess && logStats) {
@@ -2030,6 +2088,7 @@ main(int argc, char **argv)
VLOG(("selfserv: server_thread: exiting"));
cleanup:
{
int i;
for (i=0; i<kt_kea_size; i++) {

View File

@@ -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.4 2006-08-24 22:10:03 nelson%bolyard.com Exp $ */
/* $Id: derive.c,v 1.5 2007-07-18 21:38:54 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, &params, 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 function 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, &param, 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;
}

View File

@@ -133,3 +133,9 @@ SSL_ReHandshakeWithTimeout;
;+ local:
;+*;
;+};
;+NSS_3.11.7 { # NSS 3.11.7 release
;+ global:
SSL_CanBypass;
;+ local:
;+*;
;+};

View File

@@ -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.25 2007-07-11 03:09:14 julien.pierre.bugs%sun.com Exp $ */
/* $Id: ssl.h,v 1.26 2007-07-18 21:38:54 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_ */

View File

@@ -40,7 +40,7 @@
* ***** END LICENSE BLOCK ***** */
/* ECC code moved here from ssl3con.c */
/* $Id: ssl3ecc.c,v 1.18 2006-12-08 22:37:29 wtchang%redhat.com Exp $ */
/* $Id: ssl3ecc.c,v 1.19 2007-07-18 21:38:54 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

View File

@@ -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.57 2007-07-06 03:16:54 julien.pierre.bugs%sun.com Exp $ */
/* $Id: sslimpl.h,v 1.58 2007-07-18 21:38:54 neil.williams%sun.com Exp $ */
#ifndef __sslimpl_h_
#define __sslimpl_h_
@@ -191,6 +191,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;
@@ -1283,6 +1285,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);
@@ -1423,6 +1473,7 @@ PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite);
#endif
void ssl_Trace(const char *format, ...);
ECName ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits);
SEC_END_PROTOS