Marc Kleine-Budde
2020-Dec-09 09:13 UTC
[PATCH v2] compat: fix dhgex for non-GCM ciphers for OpenSSL 3.0 alpha
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