From 80fe2a3524bc9af9adf17cbbdcd4f7806a7c9e04 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Sat, 11 Mar 2017 10:17:15 +1000 Subject: [PATCH] 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 --- src/tls.c | 282 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 192 insertions(+), 90 deletions(-) diff --git a/src/tls.c b/src/tls.c index 0f0f7bc6f..501248c60 100755 --- a/src/tls.c +++ b/src/tls.c @@ -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; }