From 46a2a437d456f0f8c72ee4c996243b7ddde12eb3 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 28 Jun 2019 16:12:23 +1000 Subject: [PATCH] Better support for TLS 1.2 and FFDHE If not FFDHE parameters in list then use existing. If FFDHE parameters present but none matching then let the ciphersuite match process fail when DHE must be used. --- src/internal.c | 20 ++++++-- src/tls.c | 120 ++++++++++++++++++++++++--------------------- wolfssl/internal.h | 2 + 3 files changed, 83 insertions(+), 59 deletions(-) diff --git a/src/internal.c b/src/internal.c index ea1b2e816..825eda18f 100644 --- a/src/internal.c +++ b/src/internal.c @@ -24087,13 +24087,25 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return ret; } } - ret = MatchSuite(ssl, &clSuites); -#if defined(HAVE_FFDHE) && defined(HAVE_SUPPORTED_CURVES) - if (ret == 0 && (ssl->specs.kea == diffie_hellman_kea || - ssl->specs.kea == dhe_psk_kea)) { +#ifdef HAVE_TLS_EXTENSIONS + #if defined(HAVE_FFDHE) && defined(HAVE_SUPPORTED_CURVES) + if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) != NULL) { + /* Set FFDHE parameters or clear DHE parameters if FFDH parameters + * present and no matches in the server's list. */ ret = TLSX_SupportedFFDHE_Set(ssl); + if (ret != 0) + return ret; } + #endif +#endif + + ret = MatchSuite(ssl, &clSuites); +#ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_ERROR) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret < 0) + SendAlert(ssl, alert_fatal, handshake_failure); #endif #ifdef HAVE_SECURE_RENEGOTIATION diff --git a/src/tls.c b/src/tls.c index d6b90114b..569376c1e 100644 --- a/src/tls.c +++ b/src/tls.c @@ -4007,12 +4007,35 @@ int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl) SupportedCurve* clientGroup; SupportedCurve* group; const DhParams* params; + int found = 0; extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); /* May be doing PSK with no key exchange. */ if (extension == NULL) return 0; clientGroup = (SupportedCurve*)extension->data; + for (group = clientGroup; group != NULL; group = group->next) { + if (group->name >= MIN_FFHDE_GROUP && group->name <= MAX_FFHDE_GROUP) { + found = 1; + break; + } + } + if (!found) + return 0; + + if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + ssl->buffers.serverDH_P.buffer = NULL; + ssl->buffers.serverDH_G.buffer = NULL; + ssl->buffers.weOwnDH = 0; + ssl->options.haveDH = 0; + if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS) return ret; @@ -4021,68 +4044,54 @@ int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl) ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS); serverGroup = (SupportedCurve*)ext->data; - while (serverGroup != NULL) { - if ((serverGroup->name & NAMED_DH_MASK) == NAMED_DH_MASK) { - group = clientGroup; - while (group != NULL) { - if (serverGroup->name == group->name) { - switch (serverGroup->name) { - #ifdef HAVE_FFDHE_2048 - case WOLFSSL_FFDHE_2048: - params = wc_Dh_ffdhe2048_Get(); - break; - #endif - #ifdef HAVE_FFDHE_3072 - case WOLFSSL_FFDHE_3072: - params = wc_Dh_ffdhe3072_Get(); - break; - #endif - #ifdef HAVE_FFDHE_4096 - case WOLFSSL_FFDHE_4096: - params = wc_Dh_ffdhe4096_Get(); - break; - #endif - #ifdef HAVE_FFDHE_6144 - case WOLFSSL_FFDHE_6144: - params = wc_Dh_ffdhe6144_Get(); - break; - #endif - #ifdef HAVE_FFDHE_8192 - case WOLFSSL_FFDHE_8192: - params = wc_Dh_ffdhe8192_Get(); - break; - #endif - default: - return BAD_FUNC_ARG; - } - if (params->p_len >= ssl->options.minDhKeySz && - params->p_len <= ssl->options.maxDhKeySz) { - break; - } - } + for (; serverGroup != NULL; serverGroup = serverGroup->next) { + if ((serverGroup->name & NAMED_DH_MASK) != NAMED_DH_MASK) + continue; - group = group->next; + for (group = clientGroup; group != NULL; group = group->next) { + if (serverGroup->name != group->name) + continue; + + switch (serverGroup->name) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + break; + #endif + default: + return BAD_FUNC_ARG; } - if (group != NULL && serverGroup->name == group->name) + if (params->p_len >= ssl->options.minDhKeySz && + params->p_len <= ssl->options.maxDhKeySz) { break; + } } - serverGroup = serverGroup->next; + + if (group != NULL && serverGroup->name == group->name) + break; } if (serverGroup) { - - if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, - DYNAMIC_TYPE_PUBLIC_KEY); - ssl->buffers.serverDH_P.buffer = NULL; - } - if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { - XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, - DYNAMIC_TYPE_PUBLIC_KEY); - ssl->buffers.serverDH_G.buffer = NULL; - } - - ssl->buffers.weOwnDH = 0; ssl->buffers.serverDH_P.buffer = (unsigned char *)params->p; ssl->buffers.serverDH_P.length = params->p_len; ssl->buffers.serverDH_G.buffer = (unsigned char *)params->g; @@ -4092,6 +4101,7 @@ int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl) !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) ssl->options.dhDoKeyTest = 0; #endif + ssl->options.haveDH = 1; } TLSX_FreeAll(priority, ssl->heap); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index b522ee543..6d38a9383 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1221,6 +1221,8 @@ enum Misc { MAX_DH_SIZE = MAX_DHKEY_SZ+1, /* Max size plus possible leading 0 */ NAMED_DH_MASK = 0x100, /* Named group mask for DH parameters */ + MIN_FFHDE_GROUP = 0x100, /* Named group minimum for FFDHE parameters */ + MAX_FFHDE_GROUP = 0x1FF, /* Named group maximum for FFDHE parameters */ SESSION_HINT_SZ = 4, /* session timeout hint */ SESSION_ADD_SZ = 4, /* session age add */ TICKET_NONCE_LEN_SZ = 1, /* Ticket nonce length size */