From 7f81a2bf37fc19b76babbf1355d16fa6483edbfc Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 21 Feb 2024 22:24:56 +0100 Subject: [PATCH] openssl-dtls: use DTLS 1.2 for PSK-NEGOTIATE Avoid reducing the security level for PSK-NEGOTIATE by setting DTLS 1.2. This works well because all PSK-NEGOTIATE ocserv servers are using gnutls that supports DTLS 1.2. This addresses a previously undetermined issue with DTLS on centos7. Signed-off-by: Nikos Mavrogiannopoulos --- .gitlab-ci.yml | 3 +-- openssl-dtls.c | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c0fac613..ad9c7dbb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -193,9 +193,8 @@ CentOS7/OpenSSL: # we don't want pppd to invoke any actual connection scripts - mv /etc/ppp /etc/ppp.DISABLED # auth-nonascii: UTF-8 support is not available in distro's ocserv package -# dtls-psk: communication with ocserv fails for undetermined reasons marking as xfail until issue is identified # ppp-over-tls-sync: https://gitlab.com/openconnect/openconnect/-/issues/287#note_641198529) - - make VERBOSE=1 XFAIL_TESTS="auth-nonascii dtls-psk ppp-over-tls-sync" -j4 check + - make VERBOSE=1 XFAIL_TESTS="auth-nonascii ppp-over-tls-sync" -j4 check tags: - shared except: diff --git a/openssl-dtls.c b/openssl-dtls.c index 2a061ad8..00d1fd99 100644 --- a/openssl-dtls.c +++ b/openssl-dtls.c @@ -329,6 +329,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) SSL *dtls_ssl; BIO *dtls_bio; int dtlsver = DTLS1_BAD_VER; + int use_psk_neg = 0; const char *cipher = vpninfo->dtls_cipher; if (!cipher) { @@ -349,7 +350,9 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) cipher = "AES256-GCM-SHA384"; #ifndef OPENSSL_NO_PSK } else if (!strcmp(cipher, "PSK-NEGOTIATE")) { - dtlsver = 0; /* Let it negotiate */ + use_psk_neg = 1; + dtlsver = DTLS1_2_VERSION; + cipher = "PSK"; #endif #endif } @@ -406,7 +409,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) if (vpninfo->proto->proto == PROTO_ANYCONNECT) { /* All the AnyConnect hackery about saved sessions and PSK */ #if defined (HAVE_DTLS12) && !defined(OPENSSL_NO_PSK) - if (!dtlsver) { + if (use_psk_neg) { SSL_CTX_set_psk_client_callback(vpninfo->dtls_ctx, psk_callback); /* For PSK we override the DTLS master secret with one derived * from the HTTPS session. */ @@ -422,7 +425,6 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) return -EINVAL; } /* For SSL_CTX_set_cipher_list() */ - cipher = "PSK"; } #endif /* OPENSSL_NO_PSK */ #ifdef SSL_OP_NO_ENCRYPT_THEN_MAC @@ -450,7 +452,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) * *requires* secure renegotiation support by default. For interop * with Cisco's resumed DTLS sessions, we have to turn that off. */ - if (dtlsver) + if (dtlsver && !use_psk_neg) SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_LEGACY_SERVER_CONNECT); #endif #ifdef SSL_OP_NO_EXTENDED_MASTER_SECRET @@ -469,7 +471,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) * So where OpenSSL provides the choice, tell it not to use extms on * resumed sessions. */ - if (dtlsver) + if (dtlsver && !use_psk_neg) SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_NO_EXTENDED_MASTER_SECRET); #endif if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, cipher)) { @@ -511,7 +513,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) /* Where they only do DTLSv1, they also don't cope with secure renegotiation */ if (dtlsver == DTLS1_VERSION) SSL_set_options(dtls_ssl, SSL_OP_LEGACY_SERVER_CONNECT); - } else if (dtlsver) { + } else if (dtlsver && !use_psk_neg) { /* This is the actual Cisco AnyConnect method, using session resume */ STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(dtls_ssl); const SSL_CIPHER *ssl_ciph = NULL; @@ -561,7 +563,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) /* We don't need our own refcount on it any more */ SSL_SESSION_free(dtls_session); - } else if (vpninfo->dtls_app_id_size > 0) { + } else if (use_psk_neg) { /* * For ocserv PSK-NEGOTIATE we abuse the session resume * protocol just to pass an 'App ID' in our ClientHello @@ -569,7 +571,7 @@ int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) * and isn't actually going to be resumed at all. */ const uint8_t cs[2] = {0x00, 0x2F}; /* RSA-AES-128 */ - dtls_session = generate_dtls_session(vpninfo, DTLS1_VERSION, + dtls_session = generate_dtls_session(vpninfo, dtlsver, SSL_CIPHER_find(dtls_ssl, cs), 1); if (!dtls_session) { -- 2.50.1