Fix elliptic curve selection.

Preference by:
1. the default for the curve strength (eccTempKeySz),
2. a curve at the curve strength (eccTempKeySz),
3. the default for next higher curve strength,
4. the first curve (client order) with the next highest curve strength
This commit is contained in:
Sean Parkinson
2017-03-11 10:17:15 +10:00
parent 5a803730b8
commit 80fe2a3524

282
src/tls.c
View File

@ -2888,6 +2888,13 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) {
: NULL;
EllipticCurve* curve = NULL;
word32 oid = 0;
word32 defOid = 0;
word32 defSz = 80; /* Maximum known curve size is 66. */
word32 nextOid = 0;
word32 nextSz = 80; /* Maximum known curve size is 66. */
word32 currOid = ssl->ecdhCurveOID;
int ephmSuite = 0;
word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */
int sig = 0; /* validate signature */
int key = 0; /* validate key */
@ -2904,158 +2911,253 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) {
switch (curve->name) {
#if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
case WOLFSSL_ECC_SECP160R1: oid = ECC_SECP160R1_OID; break;
case WOLFSSL_ECC_SECP160R1:
oid = ECC_SECP160R1_OID;
octets = 20;
/* Default for 160-bits. */
if (ssl->eccTempKeySz <= octets && defSz > octets) {
defOid = oid;
defSz = octets;
}
break;
#endif /* !NO_ECC_SECP */
#ifdef HAVE_ECC_SECPR2
case WOLFSSL_ECC_SECP160R2: oid = ECC_SECP160R2_OID; break;
case WOLFSSL_ECC_SECP160R2:
oid = ECC_SECP160R2_OID;
octets = 20;
break;
#endif /* HAVE_ECC_SECPR2 */
#ifdef HAVE_ECC_KOBLITZ
case WOLFSSL_ECC_SECP160K1: oid = ECC_SECP160K1_OID; break;
case WOLFSSL_ECC_SECP160K1:
oid = ECC_SECP160K1_OID;
octets = 20;
break;
#endif /* HAVE_ECC_KOBLITZ */
#endif
#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
case WOLFSSL_ECC_SECP192R1: oid = ECC_SECP192R1_OID; break;
case WOLFSSL_ECC_SECP192R1:
oid = ECC_SECP192R1_OID;
octets = 24;
/* Default for 192-bits. */
if (ssl->eccTempKeySz <= octets && defSz > octets) {
defOid = oid;
defSz = octets;
}
break;
#endif /* !NO_ECC_SECP */
#ifdef HAVE_ECC_KOBLITZ
case WOLFSSL_ECC_SECP192K1: oid = ECC_SECP192K1_OID; break;
case WOLFSSL_ECC_SECP192K1:
oid = ECC_SECP192K1_OID;
octets = 24;
break;
#endif /* HAVE_ECC_KOBLITZ */
#endif
#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
case WOLFSSL_ECC_SECP224R1: oid = ECC_SECP224R1_OID; break;
case WOLFSSL_ECC_SECP224R1:
oid = ECC_SECP224R1_OID;
octets = 28;
/* Default for 224-bits. */
if (ssl->eccTempKeySz <= octets && defSz > octets) {
defOid = oid;
defSz = octets;
}
break;
#endif /* !NO_ECC_SECP */
#ifdef HAVE_ECC_KOBLITZ
case WOLFSSL_ECC_SECP224K1: oid = ECC_SECP224K1_OID; break;
case WOLFSSL_ECC_SECP224K1:
oid = ECC_SECP224K1_OID;
octets = 28;
break;
#endif /* HAVE_ECC_KOBLITZ */
#endif
#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
case WOLFSSL_ECC_SECP256R1: oid = ECC_SECP256R1_OID; break;
case WOLFSSL_ECC_SECP256R1:
oid = ECC_SECP256R1_OID;
octets = 32;
/* Default for 256-bits. */
if (ssl->eccTempKeySz <= octets && defSz > octets) {
defOid = oid;
defSz = octets;
}
break;
#endif /* !NO_ECC_SECP */
#ifdef HAVE_ECC_KOBLITZ
case WOLFSSL_ECC_SECP256K1: oid = ECC_SECP256K1_OID; break;
case WOLFSSL_ECC_SECP256K1:
oid = ECC_SECP256K1_OID;
octets = 32;
break;
#endif /* HAVE_ECC_KOBLITZ */
#ifdef HAVE_ECC_BRAINPOOL
case WOLFSSL_ECC_BRAINPOOLP256R1: oid = ECC_BRAINPOOLP256R1_OID; break;
case WOLFSSL_ECC_BRAINPOOLP256R1:
oid = ECC_BRAINPOOLP256R1_OID;
octets = 32;
break;
#endif /* HAVE_ECC_BRAINPOOL */
#endif
#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
case WOLFSSL_ECC_SECP384R1: oid = ECC_SECP384R1_OID; break;
case WOLFSSL_ECC_SECP384R1:
oid = ECC_SECP384R1_OID;
octets = 48;
/* Default for 384-bits. */
if (ssl->eccTempKeySz <= octets && defSz > octets) {
defOid = oid;
defSz = octets;
}
break;
#endif /* !NO_ECC_SECP */
#ifdef HAVE_ECC_BRAINPOOL
case WOLFSSL_ECC_BRAINPOOLP384R1: oid = ECC_BRAINPOOLP384R1_OID; break;
case WOLFSSL_ECC_BRAINPOOLP384R1:
oid = ECC_BRAINPOOLP384R1_OID;
octets = 48;
break;
#endif /* HAVE_ECC_BRAINPOOL */
#endif
#if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
#ifdef HAVE_ECC_BRAINPOOL
case WOLFSSL_ECC_BRAINPOOLP512R1: oid = ECC_BRAINPOOLP512R1_OID; break;
case WOLFSSL_ECC_BRAINPOOLP512R1:
oid = ECC_BRAINPOOLP512R1_OID;
octets = 64;
break;
#endif /* HAVE_ECC_BRAINPOOL */
#endif
#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
case WOLFSSL_ECC_SECP521R1: oid = ECC_SECP521R1_OID; break;
case WOLFSSL_ECC_SECP521R1:
oid = ECC_SECP521R1_OID;
octets = 66;
break;
#endif /* !NO_ECC_SECP */
#endif
default: continue; /* unsupported curve */
}
if (ssl->ecdhCurveOID == 0)
ssl->ecdhCurveOID = oid;
if (currOid == 0 && ssl->eccTempKeySz == octets)
currOid = oid;
if ((nextOid == 0 || nextSz > octets) && ssl->eccTempKeySz <= octets) {
nextOid = oid;
nextSz = octets;
}
if (first == ECC_BYTE) {
switch (second) {
/* ECDHE_ECDSA */
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
sig |= ssl->pkCurveOID == oid;
key |= ssl->ecdhCurveOID == oid;
break;
switch (second) {
/* ECDHE_ECDSA */
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
sig |= ssl->pkCurveOID == oid;
key |= ssl->ecdhCurveOID == oid;
ephmSuite = 1;
break;
#ifdef WOLFSSL_STATIC_DH
/* ECDH_ECDSA */
case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
sig |= ssl->pkCurveOID == oid;
key |= ssl->pkCurveOID == oid;
break;
/* ECDH_ECDSA */
case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
sig |= ssl->pkCurveOID == oid;
key |= ssl->pkCurveOID == oid;
break;
#endif /* WOLFSSL_STATIC_DH */
#ifndef NO_RSA
/* ECDHE_RSA */
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
sig = 1;
key |= ssl->ecdhCurveOID == oid;
break;
/* ECDHE_RSA */
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
sig = 1;
key |= ssl->ecdhCurveOID == oid;
ephmSuite = 1;
break;
#ifdef WOLFSSL_STATIC_DH
/* ECDH_RSA */
case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
case TLS_ECDH_RSA_WITH_RC4_128_SHA:
case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
sig = 1;
key |= ssl->pkCurveOID == oid;
break;
/* ECDH_RSA */
case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
case TLS_ECDH_RSA_WITH_RC4_128_SHA:
case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
sig = 1;
key |= ssl->pkCurveOID == oid;
break;
#endif /* WOLFSSL_STATIC_DH */
#endif
default:
sig = 1;
key = 1;
break;
}
default:
sig = 1;
key = 1;
break;
}
}
/* ChaCha20-Poly1305 ECC cipher suites */
if (first == CHACHA_BYTE) {
switch (second) {
/* ECDHE_ECDSA */
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
sig |= ssl->pkCurveOID == oid;
key |= ssl->ecdhCurveOID == oid;
break;
switch (second) {
/* ECDHE_ECDSA */
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
sig |= ssl->pkCurveOID == oid;
key |= ssl->ecdhCurveOID == oid;
ephmSuite = 1;
break;
#ifndef NO_RSA
/* ECDHE_RSA */
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
sig = 1;
key |= ssl->ecdhCurveOID == oid;
break;
/* ECDHE_RSA */
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
sig = 1;
key |= ssl->ecdhCurveOID == oid;
ephmSuite = 1;
break;
#endif
default:
sig = 1;
key = 1;
break;
}
default:
sig = 1;
key = 1;
break;
}
}
}
/* Choose the default if it is at the required strength. */
if (ssl->ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz) {
key = 1;
ssl->ecdhCurveOID = defOid;
}
/* Choose any curve at the required strength. */
if (ssl->ecdhCurveOID == 0) {
key = 1;
ssl->ecdhCurveOID = currOid;
}
/* Choose the default if it is at the next highest strength. */
if (ssl->ecdhCurveOID == 0 && defSz == nextSz)
ssl->ecdhCurveOID = defOid;
/* Choose any curve at the next highest strength. */
if (ssl->ecdhCurveOID == 0)
ssl->ecdhCurveOID = nextOid;
/* No curve and ephemeral ECC suite requires a matching curve. */
if (ssl->ecdhCurveOID == 0 && ephmSuite)
key = 0;
return sig && key;
}