Signed-off-by: Juliusz Sosinowicz <juliusz@xxxxxxxxxxx> --- src/crypto/tls_wolfssl.c | 166 +++++++++++++++++++++++++++++------- tests/hwsim/test_suite_b.py | 31 +++++-- 2 files changed, 162 insertions(+), 35 deletions(-) diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c index 4db23e14ff..25616f2c7a 100644 --- a/src/crypto/tls_wolfssl.c +++ b/src/crypto/tls_wolfssl.c @@ -223,11 +223,127 @@ static void wolfSSL_logging_cb(const int log_level, #endif /* DEBUG_WOLFSSL */ +#define SUITEB_OLDTLS_192_CIPHERS "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384" +#define SUITEB_TLS13_192_CIPHERS "TLS13-AES256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256" +#define SUITEB_TLS_192_CIPHERS SUITEB_TLS13_192_CIPHERS ":" SUITEB_OLDTLS_192_CIPHERS + +#define SUITEB_OLDTLS_128_CIPHERS SUITEB_OLDTLS_192_CIPHERS ":ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256" +#define SUITEB_TLS13_128_CIPHERS SUITEB_TLS13_192_CIPHERS ":TLS13-AES128-GCM-SHA256" +#define SUITEB_TLS_128_CIPHERS SUITEB_TLS13_128_CIPHERS ":" SUITEB_OLDTLS_128_CIPHERS + +#define SUITEB_TLS_192_SIGALGS "ECDSA+SHA384:RSA-PSS+SHA384:RSA+SHA384" +#define SUITEB_TLS_128_SIGALGS SUITEB_TLS_192_SIGALGS ":ECDSA+SHA256:RSA-PSS+SHA256:RSA+SHA256" + +#define SUITEB_TLS_192_CURVES "P-384:P-521" +#define SUITEB_TLS_128_CURVES "P-256:" SUITEB_TLS_192_CURVES + +static int handle_ciphersuites(WOLFSSL_CTX* ssl_ctx, WOLFSSL* ssl, + const char* openssl_ciphers, unsigned int flags) +{ + const char* ciphers = "DEFAULT:!aNULL"; + const char* sigalgs = NULL; + const char* curves = NULL; + unsigned int tls13 = !(flags & TLS_CONN_DISABLE_TLSv1_3); + unsigned int tls13OnlyMask = TLS_CONN_DISABLE_TLSv1_2 | + TLS_CONN_DISABLE_TLSv1_1 | TLS_CONN_DISABLE_TLSv1_0; + unsigned int oldTlsOnly = ((flags & tls13OnlyMask) != tls13OnlyMask) && !tls13; + unsigned int tls13only = ((flags & tls13OnlyMask) == tls13OnlyMask) && + !(flags & TLS_CONN_DISABLE_TLSv1_3); + short keySz = 0; + short eccKeySz = 0; + if (openssl_ciphers) { + if (os_strcmp(openssl_ciphers, "SUITEB128") == 0) { + if (tls13only) + ciphers = SUITEB_TLS13_128_CIPHERS; + else if (oldTlsOnly) + ciphers = SUITEB_OLDTLS_128_CIPHERS; + else + ciphers = SUITEB_TLS_128_CIPHERS; + sigalgs = SUITEB_TLS_128_SIGALGS; + keySz = 2048; + eccKeySz = 224; + curves = SUITEB_TLS_128_CURVES; + } + else if (os_strcmp(openssl_ciphers, "SUITEB192") == 0) { + if (tls13only) + ciphers = SUITEB_TLS13_192_CIPHERS; + else if (oldTlsOnly) + ciphers = SUITEB_OLDTLS_192_CIPHERS; + else + ciphers = SUITEB_TLS_192_CIPHERS; + sigalgs = SUITEB_TLS_192_SIGALGS; + keySz = 3072; + eccKeySz = 256; + curves = SUITEB_TLS_192_CURVES; + } + else + ciphers = openssl_ciphers; + } + else if (flags & TLS_CONN_SUITEB) { + if (tls13only) + ciphers = SUITEB_TLS13_192_CIPHERS; + else if (oldTlsOnly) + ciphers = SUITEB_OLDTLS_192_CIPHERS; + else + ciphers = SUITEB_TLS_192_CIPHERS; + sigalgs = SUITEB_TLS_192_SIGALGS; + keySz = 3072; + eccKeySz = 256; + curves = SUITEB_TLS_192_CURVES; + } + wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites for %s", ssl_ctx ? "ctx" : "ssl"); + wpa_printf(MSG_DEBUG, "wolfSSL: openssl_ciphers: %s", openssl_ciphers ? openssl_ciphers : "N/A"); + wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", ciphers ? ciphers : "N/A"); + wpa_printf(MSG_DEBUG, "wolfSSL: sigalgs: %s", sigalgs ? sigalgs : "N/A"); + wpa_printf(MSG_DEBUG, "wolfSSL: key size: %d", keySz); + if (ciphers) { + if ((ssl_ctx && wolfSSL_CTX_set_cipher_list(ssl_ctx, ciphers) != 1) || + (ssl && wolfSSL_set_cipher_list(ssl, ciphers) != 1)) { + wpa_printf(MSG_ERROR, + "wolfSSL: Failed to set cipher string '%s'", ciphers); + return -1; + } + } + if (sigalgs) { + if ((ssl_ctx && wolfSSL_CTX_set1_sigalgs_list(ssl_ctx, sigalgs) != 1) || + (ssl && wolfSSL_set1_sigalgs_list(ssl, sigalgs) != 1)) { + wpa_printf(MSG_ERROR, + "wolfSSL: Failed to set sigalgs '%s'", sigalgs); + return -1; + } + } + if (keySz) { + if ((ssl_ctx && wolfSSL_CTX_SetMinRsaKey_Sz(ssl_ctx, keySz) != 1) || + (ssl && wolfSSL_SetMinRsaKey_Sz(ssl, keySz) != 1) || + (ssl_ctx && wolfSSL_CTX_SetMinDhKey_Sz(ssl_ctx, keySz) != 1) || + (ssl && wolfSSL_SetMinDhKey_Sz(ssl, keySz) != 1)) { + wpa_printf(MSG_ERROR, "wolfSSL: Failed to set min key size"); + return -1; + } + } + if (eccKeySz) { + if ((ssl_ctx && wolfSSL_CTX_SetMinEccKey_Sz(ssl_ctx, eccKeySz) != 1) || + (ssl && wolfSSL_SetMinEccKey_Sz(ssl, eccKeySz) != 1) || + (ssl_ctx && wolfSSL_CTX_SetTmpEC_DHE_Sz(ssl_ctx, eccKeySz/8) != 1) || + (ssl && wolfSSL_SetTmpEC_DHE_Sz(ssl, eccKeySz/8) != 1)) { + wpa_printf(MSG_ERROR, "wolfSSL: Failed to set min ecc key size"); + return -1; + } + } + if (curves) { + if ((ssl_ctx && wolfSSL_CTX_set1_curves_list(ssl_ctx, curves) != 1) || + (ssl && wolfSSL_set1_curves_list(ssl, curves) != 1)) { + wpa_printf(MSG_ERROR, "wolfSSL: Failed to set curves"); + return -1; + } + } + return 0; +} + void * tls_init(const struct tls_config *conf) { WOLFSSL_CTX *ssl_ctx; struct tls_context *context; - const char *ciphers; #ifdef DEBUG_WOLFSSL wolfSSL_SetLoggingCb(wolfSSL_logging_cb); @@ -280,19 +396,14 @@ void * tls_init(const struct tls_config *conf) WOLFSSL_SESS_CACHE_OFF); } - if (conf && conf->openssl_ciphers) - ciphers = conf->openssl_ciphers; - else - ciphers = "ALL"; - wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", ciphers); - if (wolfSSL_CTX_set_cipher_list(ssl_ctx, ciphers) != 1) { - wpa_printf(MSG_ERROR, - "wolfSSL: Failed to set cipher string '%s'", - ciphers); + if (handle_ciphersuites(ssl_ctx, NULL, conf->openssl_ciphers, + conf ? conf->tls_flags : 0) != 0) { + wpa_printf(MSG_INFO, "Error setting ciphersuites"); tls_deinit(ssl_ctx); return NULL; } + return ssl_ctx; } @@ -819,6 +930,8 @@ static enum tls_fail_reason wolfssl_tls_fail_reason(int err) case X509_V_ERR_CERT_UNTRUSTED: case X509_V_ERR_CERT_REJECTED: return TLS_FAIL_BAD_CERTIFICATE; + case RSA_KEY_SIZE_E: + return TLS_FAIL_INSUFFICIENT_KEY_LEN; default: return TLS_FAIL_UNSPECIFIED; } @@ -1324,13 +1437,9 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, return -1; } - wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", - params->openssl_ciphers ? params->openssl_ciphers : "N/A"); - if (params->openssl_ciphers && - wolfSSL_set_cipher_list(conn->ssl, params->openssl_ciphers) != 1) { - wpa_printf(MSG_INFO, - "wolfSSL: Failed to set cipher string '%s'", - params->openssl_ciphers); + if (handle_ciphersuites(NULL, conn->ssl, params->openssl_ciphers, + params->flags) != 0) { + wpa_printf(MSG_INFO, "Error setting ciphersuites"); return -1; } @@ -1556,14 +1665,9 @@ int tls_global_set_params(void *tls_ctx, return -1; } - wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", - params->openssl_ciphers ? params->openssl_ciphers : "N/A"); - if (params->openssl_ciphers && - wolfSSL_CTX_set_cipher_list(tls_ctx, - params->openssl_ciphers) != 1) { - wpa_printf(MSG_INFO, - "wolfSSL: Failed to set cipher string '%s'", - params->openssl_ciphers); + if (handle_ciphersuites(tls_ctx, NULL, params->openssl_ciphers, + params->flags) != 0) { + wpa_printf(MSG_INFO, "Error setting ciphersuites"); return -1; } @@ -1870,7 +1974,7 @@ int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, if (!conn || !conn->ssl || !ciphers) return -1; - buf[0] = '\0'; + buf[0] = buf[1] = '\0'; pos = buf; end = pos + sizeof(buf); @@ -1910,9 +2014,8 @@ int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, c++; } - wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", buf + 1); - - if (wolfSSL_set_cipher_list(conn->ssl, buf + 1) != 1) { + /* +1 to skip the ":" */ + if (handle_ciphersuites(NULL, conn->ssl, buf + 1, conn->flags) != 0) { wpa_printf(MSG_DEBUG, "Cipher suite configuration failed"); return -1; } @@ -1929,7 +2032,10 @@ int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, if (!conn || !conn->ssl) return -1; - name = wolfSSL_get_cipher_name(conn->ssl); + if (wolfSSL_version(conn->ssl) == TLS1_3_VERSION) + name = wolfSSL_get_cipher(conn->ssl); + else + name = wolfSSL_get_cipher_name(conn->ssl); if (!name) return -1; diff --git a/tests/hwsim/test_suite_b.py b/tests/hwsim/test_suite_b.py index d03a39deef..59e255a3c6 100644 --- a/tests/hwsim/test_suite_b.py +++ b/tests/hwsim/test_suite_b.py @@ -74,7 +74,8 @@ def test_suite_b(dev, apdev): hapd.wait_sta() tls_cipher = dev[0].get_status_field("EAP TLS cipher") if tls_cipher != "ECDHE-ECDSA-AES128-GCM-SHA256" and \ - tls_cipher != "ECDHE-ECDSA-AES-128-GCM-AEAD": + tls_cipher != "ECDHE-ECDSA-AES-128-GCM-AEAD" and \ + tls_cipher != "ECDHE-ECDSA-AES256-GCM-SHA384": raise Exception("Unexpected TLS cipher: " + tls_cipher) bss = dev[0].get_bss(apdev[0]['bssid']) @@ -488,7 +489,16 @@ def test_suite_b_192_rsa_insufficient_key(dev, apdev): params["ca_cert"] = "auth_serv/ca.pem" params["server_cert"] = "auth_serv/server.pem" params["private_key"] = "auth_serv/server.key" - hapd = hostapd.add_ap(apdev[0], params) + + try: + hapd = hostapd.add_ap(apdev[0], params) + except: + hapd = hostapd.add_ap(apdev[0], suite_b_192_rsa_ap_params()) + tls = hapd.request("GET tls_library") + if tls.startswith("wolfSSL"): + # wolfSSL fails during key loading with too short key + return + raise dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192", ieee80211w="2", @@ -505,6 +515,8 @@ def test_suite_b_192_rsa_insufficient_key(dev, apdev): raise Exception("Certificate error not reported") if "reason=11" in ev and "err='Insufficient RSA modulus size'" in ev: return + if "reason=11" in ev and "err='RSA key too small'" in ev: + return if "reason=7" in ev and "err='certificate uses insecure algorithm'" in ev: return raise Exception("Unexpected error reason: " + ev) @@ -516,7 +528,16 @@ def test_suite_b_192_rsa_insufficient_dh(dev, apdev): params = suite_b_192_rsa_ap_params() params["tls_flags"] = "[SUITEB-NO-ECDH]" params["dh_file"] = "auth_serv/dh.conf" - hapd = hostapd.add_ap(apdev[0], params) + try: + hapd = hostapd.add_ap(apdev[0], params) + except: + hapd = hostapd.add_ap(apdev[0], suite_b_192_rsa_ap_params()) + tls = hapd.request("GET tls_library") + if tls.startswith("wolfSSL"): + # wolfSSL fails during key loading with too short key + return + raise + dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192", ieee80211w="2", @@ -528,14 +549,14 @@ def test_suite_b_192_rsa_insufficient_dh(dev, apdev): pairwise="GCMP-256", group="GCMP-256", scan_freq="2412", wait_connect=False) ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS status='local TLS alert'", - "CTRL-EVENT-CONNECTED"], + "CTRL-EVENT-CONNECTED", "CTRL-EVENT-EAP-FAILURE"], timeout=10) dev[0].request("DISCONNECT") if ev is None: raise Exception("DH error not reported") if "CTRL-EVENT-CONNECTED" in ev: raise Exception("Unexpected connection") - if "insufficient security" not in ev and "internal error" not in ev: + if "insufficient security" not in ev and "internal error" not in ev and "authentication failed" not in ev: raise Exception("Unexpected error reason: " + ev) def test_suite_b_192_rsa_radius(dev, apdev): -- 2.34.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap