[PATCH v2] compat: fix dhgex for non-GCM ciphers for OpenSSL 3.0 alpha

Marc Kleine-Budde mkl at pengutronix.de
Wed Dec 9 20:13:10 AEDT 2020


During OpenSSL 3.0 development since OpenSSL commits:

| 718b133a5328 Implement AES CBC ciphers in the default provider
| 819a7ae9fc77 Implement AES CTR ciphers in the default provider

the dhgex tests ("make t-exec LTESTS=dhgex") are failing.

OpenSSH needs the "current" IV state, which is aquired with the accessor
function EVP_CIPHER_CTX_get_iv(). The libressl compat layer uses
EVP_CIPHER_CTX_iv() to implement EVP_CIPHER_CTX_get_iv(), see:

| 482d23bcacdd upstream: hold our collective noses and use the openssl-1.1.x API in
| 48f54b9d12c1 adapt -portable to OpenSSL 1.1x API

Duing OpenSSL 3.0 development EVP_CIPHER_CTX_iv() was deprecated, and later
OpenSSL re-added the functionality: EVP_CIPHER_CTX_get_iv() and
EVP_CIPHER_CTX_get_iv_state() were introduced. However,
EVP_CIPHER_CTX_get_iv() returns the original IV, while
EVP_CIPHER_CTX_get_iv_state() returns the current IV. See openssl PR #12233 for
additional discussion.

This is a API clash, since OpenSSH expects EVP_CIPHER_CTX_get_iv() to return
the running IV. See OpenSSL issue #13411 for an ongoing discussion on how to
fix the problem, by renaming the functions.

This patch works around the problem in the libressl compat layer, by providing
a EVP_CIPHER_CTX_get_iv() function, that calls EVP_CIPHER_CTX_get_iv_state(),
only if EVP_CIPHER_CTX_get_iv_state() is available. This internal
EVP_CIPHER_CTX_get_iv() will be used by OpenSSH instead of the
EVP_CIPHER_CTX_get_iv() provided by OpenSSL-3.0.

The latest changes in OpenSSL 3.0 in combination with this patch fixes the
non-GCM ciphers. All but the chacha20-poly1305 test are working again:

| dhgex bits 3072 diffie-hellman-group-exchange-sha1 3des-cbc
| dhgex bits 3072 diffie-hellman-group-exchange-sha256 3des-cbc
| dhgex bits 3072 diffie-hellman-group-exchange-sha1 aes128-cbc
| dhgex bits 3072 diffie-hellman-group-exchange-sha256 aes128-cbc
| dhgex bits 3072 diffie-hellman-group-exchange-sha1 aes128-ctr
| dhgex bits 3072 diffie-hellman-group-exchange-sha256 aes128-ctr
| dhgex bits 3072 diffie-hellman-group-exchange-sha1 aes128-gcm at openssh.com
| dhgex bits 3072 diffie-hellman-group-exchange-sha256 aes128-gcm at openssh.com
| dhgex bits 7680 diffie-hellman-group-exchange-sha1 aes192-cbc
| dhgex bits 7680 diffie-hellman-group-exchange-sha256 aes192-cbc
| dhgex bits 7680 diffie-hellman-group-exchange-sha1 aes192-ctr
| dhgex bits 7680 diffie-hellman-group-exchange-sha256 aes192-ctr
| dhgex bits 8192 diffie-hellman-group-exchange-sha1 aes256-cbc
| dhgex bits 8192 diffie-hellman-group-exchange-sha256 aes256-cbc
| dhgex bits 8192 diffie-hellman-group-exchange-sha1 aes256-ctr
| dhgex bits 8192 diffie-hellman-group-exchange-sha256 aes256-ctr
| dhgex bits 8192 diffie-hellman-group-exchange-sha1 aes256-gcm at openssh.com
| dhgex bits 8192 diffie-hellman-group-exchange-sha256 aes256-gcm at openssh.com
| dhgex bits 8192 diffie-hellman-group-exchange-sha1 rijndael-cbc at lysator.liu.se
| dhgex bits 8192 diffie-hellman-group-exchange-sha256 rijndael-cbc at lysator.liu.se
| dhgex bits 8192 diffie-hellman-group-exchange-sha1 chacha20-poly1305 at openssh.com
| ssh failed ()
| dhgex bits 8192 diffie-hellman-group-exchange-sha256 chacha20-poly1305 at openssh.com
| ssh failed ()

Cc: Thomas Dwyer III <tomiii at tomiii.com>
Link: https://www.spinics.net/lists/openssh-unix-dev/msg06860.html
Link: https://github.com/openssl/openssl/pull/12233
Link: https://github.com/openssl/openssl/issues/13411
---
Hello,

here's another take on working around the OpenSSL-3.0/LibreSSL API clash on
EVP_CIPHER_CTX_get_iv().

Tested against:
- LibreSSL master
- OpenSSL-3.0 master
- OpenSSL-1.1.1

regards,
Marc

Changes since v1:
- If EVP_CIPHER_CTX_get_iv_state() is available, let the LibreSSL API compat
  layer provide a EVP_CIPHER_CTX_get_iv() that calls directly
  EVP_CIPHER_CTX_get_iv_state().

 configure.ac                         |  5 +++++
 openbsd-compat/libressl-api-compat.c | 12 ++++++++++--
 openbsd-compat/openssl-compat.h      |  2 +-
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index 35d1aca9fc90..8d2136bc8bfc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2875,6 +2875,11 @@ if test "x$openssl" = "xyes" ; then
 		EVP_chacha20 \
 	])
 
+	# OpenSSL 3.x API
+	AC_CHECK_FUNCS([ \
+		EVP_CIPHER_CTX_get_iv_state \
+	])
+
 	if test "x$openssl_engine" = "xyes" ; then
 		AC_MSG_CHECKING([for OpenSSL ENGINE support])
 		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
diff --git a/openbsd-compat/libressl-api-compat.c b/openbsd-compat/libressl-api-compat.c
index ae00ff593b7e..c4405a903299 100644
--- a/openbsd-compat/libressl-api-compat.c
+++ b/openbsd-compat/libressl-api-compat.c
@@ -334,7 +334,7 @@ RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
 }
 #endif /* HAVE_RSA_SET0_FACTORS */
 
-#ifndef HAVE_EVP_CIPHER_CTX_GET_IV
+#if !defined(HAVE_EVP_CIPHER_CTX_GET_IV) && !defined(HAVE_EVP_CIPHER_CTX_GET_IV_STATE)
 int
 EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len)
 {
@@ -361,7 +361,15 @@ EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len)
 	}
 	return 1;
 }
-#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */
+#endif /* !HAVE_EVP_CIPHER_CTX_GET_IV && !HAVE_EVP_CIPHER_CTX_GET_IV_STATE */
+
+#ifdef HAVE_EVP_CIPHER_CTX_GET_IV_STATE
+int
+EVP_CIPHER_CTX_get_iv(EVP_CIPHER_CTX *ctx, void *iv, size_t len)
+{
+	return EVP_CIPHER_CTX_get_iv_state(ctx, iv, len);
+}
+#endif /* HAVE_EVP_CIPHER_CTX_GET_IV_STATE*/
 
 #ifndef HAVE_EVP_CIPHER_CTX_SET_IV
 int
diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h
index 388ae8aa0077..df10d56b00e0 100644
--- a/openbsd-compat/openssl-compat.h
+++ b/openbsd-compat/openssl-compat.h
@@ -112,7 +112,7 @@ void DSA_get0_key(const DSA *d, const BIGNUM **pub_key,
 int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
 #endif /* HAVE_DSA_SET0_KEY */
 
-#ifndef HAVE_EVP_CIPHER_CTX_GET_IV
+#if !defined(HAVE_EVP_CIPHER_CTX_GET_IV) && !defined(HAVE_EVP_CIPHER_CTX_GET_IV_STATE)
 int EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx,
     unsigned char *iv, size_t len);
 #endif /* HAVE_EVP_CIPHER_CTX_GET_IV */
-- 
2.20.1



More information about the openssh-unix-dev mailing list