Skip to content

Commit

Permalink
Issue #1448: Backporting the mod_sftp/OpenSSL 3.x fixes to the 1.3.7 …
Browse files Browse the repository at this point in the history
…branch.
  • Loading branch information
Castaglia committed May 10, 2022
1 parent df0c982 commit 8aa39b2
Show file tree
Hide file tree
Showing 9 changed files with 324 additions and 14 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
where `N' is the issue number.
-----------------------------------------------------------------------------

1.3.7e
--------------------------------
- Issue 1448 - Ensure that mod_sftp algorithms work properly with OpenSSL 3.x.

1.3.7d - Released 23-Apr-2022
--------------------------------
- Issue 1321 - Crash with long lines in AuthGroupFile due to large realloc(3).
Expand Down
6 changes: 6 additions & 0 deletions RELEASE_NOTES
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ This file contains a description of the major changes to ProFTPD for the
releases. More information on these changes can be found in the NEWS and
ChangeLog files.

1.3.7e
---------

+ Ensure that mod_sftp algorithms work properly when OpenSSL 3.x is used.


1.3.7d
---------

Expand Down
79 changes: 71 additions & 8 deletions contrib/mod_sftp/cipher.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* ProFTPD - mod_sftp ciphers
* Copyright (c) 2008-2020 TJ Saunders
* Copyright (c) 2008-2022 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -192,14 +192,40 @@ static int set_cipher_iv(struct sftp_cipher *cipher, const EVP_MD *hash,
}

ctx = EVP_MD_CTX_create();
EVP_DigestInit(ctx, hash);
if (EVP_DigestInit(ctx, hash) != 1) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"unable to initialize MD context for '%s': %s", EVP_MD_name(hash),
sftp_crypto_get_errors());
free(iv);
errno = EINVAL;
return -1;
}

if (sftp_interop_supports_feature(SFTP_SSH2_FEAT_CIPHER_USE_K)) {
EVP_DigestUpdate(ctx, k, klen);
}
EVP_DigestUpdate(ctx, h, hlen);

if (EVP_DigestUpdate(ctx, h, hlen) != 1) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"unable to update MD context for '%s': %s", EVP_MD_name(hash),
sftp_crypto_get_errors());
free(iv);
errno = EINVAL;
return -1;
}

EVP_DigestUpdate(ctx, letter, sizeof(char));
EVP_DigestUpdate(ctx, (char *) id, id_len);
EVP_DigestFinal(ctx, iv, &iv_len);

if (EVP_DigestFinal(ctx, iv, &iv_len) != 1) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"unable to finish MD context for '%s': %s", EVP_MD_name(hash),
sftp_crypto_get_errors());
free(iv);
errno = EINVAL;
return -1;
}

EVP_MD_CTX_destroy(ctx);

/* If we need more, keep hashing, as per RFC, until we have enough
Expand Down Expand Up @@ -264,12 +290,37 @@ static int set_cipher_key(struct sftp_cipher *cipher, const EVP_MD *hash,
}

ctx = EVP_MD_CTX_create();
EVP_DigestInit(ctx, hash);
EVP_DigestUpdate(ctx, k, klen);
if (EVP_DigestInit(ctx, hash) != 1) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"unable to initialize MD context for '%s': %s", EVP_MD_name(hash),
sftp_crypto_get_errors());
free(key);
errno = EINVAL;
return -1;
}

if (EVP_DigestUpdate(ctx, k, klen) != 1) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"unable to update MD context for '%s': %s", EVP_MD_name(hash),
sftp_crypto_get_errors());
free(key);
errno = EINVAL;
return -1;
}

EVP_DigestUpdate(ctx, h, hlen);
EVP_DigestUpdate(ctx, letter, sizeof(char));
EVP_DigestUpdate(ctx, (char *) id, id_len);
EVP_DigestFinal(ctx, key, &key_len);

if (EVP_DigestFinal(ctx, key, &key_len) != 1) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"unable to finish MD context for '%s': %s", EVP_MD_name(hash),
sftp_crypto_get_errors());
free(key);
errno = EINVAL;
return -1;
}

EVP_MD_CTX_destroy(ctx);

pr_trace_msg(trace_channel, 19, "hashed data to produce key (%lu bytes)",
Expand Down Expand Up @@ -507,7 +558,19 @@ int sftp_cipher_set_read_key(pool *p, const EVP_MD *hash, const BIGNUM *k,
}

pr_memscrub(ptr, bufsz);
sftp_cipher_set_block_size(EVP_CIPHER_block_size(cipher->cipher));

if (strcmp(cipher->algo, "aes128-ctr") == 0 ||
strcmp(cipher->algo, "aes192-ctr") == 0 ||
strcmp(cipher->algo, "aes256-ctr") == 0) {
/* For some reason, OpenSSL returns 8 for the AES block size (even
* though the AES block size is 16, per RFC 5647), but OpenSSH wants 16.
*/
sftp_cipher_set_block_size(16);

} else {
sftp_cipher_set_block_size(EVP_CIPHER_block_size(cipher->cipher));
}

return 0;
}

Expand Down
123 changes: 123 additions & 0 deletions contrib/mod_sftp/configure
Original file line number Diff line number Diff line change
Expand Up @@ -3865,6 +3865,88 @@ $as_echo "no" >&6; }
LIBS="$saved_libs"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
LIBS="-lcrypto $LIBS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL supports EVP_aes_128_ctr" >&5
$as_echo_n "checking whether OpenSSL supports EVP_aes_128_ctr... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <openssl/evp.h>
int
main ()
{
EVP_CIPHER *cipher;
cipher = EVP_aes_128_ctr();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_EVP_AES_128_CTR_OPENSSL 1" >>confdefs.h
LIBS="$saved_libs"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LIBS="$saved_libs"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
LIBS="-lcrypto $LIBS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL supports EVP_aes_192_ctr" >&5
$as_echo_n "checking whether OpenSSL supports EVP_aes_192_ctr... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <openssl/evp.h>
int
main ()
{
EVP_CIPHER *cipher;
cipher = EVP_aes_192_ctr();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_EVP_AES_192_CTR_OPENSSL 1" >>confdefs.h
LIBS="$saved_libs"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LIBS="$saved_libs"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
Expand Down Expand Up @@ -3906,6 +3988,47 @@ $as_echo "no" >&6; }
LIBS="$saved_libs"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
LIBS="-lcrypto $LIBS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL supports OSSL_PROVIDER_load" >&5
$as_echo_n "checking whether OpenSSL supports OSSL_PROVIDER_load... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <openssl/provider.h>
int
main ()
{
OSSL_PROVIDER *provider;
provider = OSSL_PROVIDER_load(NULL, "default");
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_OSSL_PROVIDER_LOAD_OPENSSL 1" >>confdefs.h
LIBS="$saved_libs"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LIBS="$saved_libs"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
Expand Down
74 changes: 73 additions & 1 deletion contrib/mod_sftp/configure.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
dnl ProFTPD - mod_sftp
dnl Copyright (c) 2012-2019 TJ Saunders <tj@castaglia.org>
dnl Copyright (c) 2012-2022 TJ Saunders <tj@castaglia.org>
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -206,6 +206,54 @@ dnl Splice out -lsupp, since that library hasn't been built yet
LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
LIBS="-lcrypto $LIBS"

AC_MSG_CHECKING([whether OpenSSL supports EVP_aes_128_ctr])
AC_TRY_LINK(
[
#include <openssl/evp.h>
],
[
EVP_CIPHER *cipher;
cipher = EVP_aes_128_ctr();
],
[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_EVP_AES_128_CTR_OPENSSL, 1, [OpenSSL supports EVP_aes_128_ctr])
LIBS="$saved_libs"
],
[
AC_MSG_RESULT(no)
LIBS="$saved_libs"
]
)

dnl Splice out -lsupp, since that library hasn't been built yet
LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
LIBS="-lcrypto $LIBS"

AC_MSG_CHECKING([whether OpenSSL supports EVP_aes_192_ctr])
AC_TRY_LINK(
[
#include <openssl/evp.h>
],
[
EVP_CIPHER *cipher;
cipher = EVP_aes_192_ctr();
],
[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_EVP_AES_192_CTR_OPENSSL, 1, [OpenSSL supports EVP_aes_192_ctr])
LIBS="$saved_libs"
],
[
AC_MSG_RESULT(no)
LIBS="$saved_libs"
]
)

dnl Splice out -lsupp, since that library hasn't been built yet
LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
LIBS="-lcrypto $LIBS"

AC_MSG_CHECKING([whether OpenSSL supports EVP_aes_256_ctr])
AC_TRY_LINK(
[
Expand All @@ -226,6 +274,30 @@ AC_TRY_LINK(
]
)

dnl Splice out -lsupp, since that library hasn't been built yet
LIBS=`echo "$LIBS" | sed -e 's/-lsupp//g'`;
LIBS="-lcrypto $LIBS"

AC_MSG_CHECKING([whether OpenSSL supports OSSL_PROVIDER_load])
AC_TRY_LINK(
[
#include <openssl/provider.h>
],
[
OSSL_PROVIDER *provider;
provider = OSSL_PROVIDER_load(NULL, "default");
],
[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_OSSL_PROVIDER_LOAD_OPENSSL, 1, [OpenSSL supports OSSL_PROVIDER_load])
LIBS="$saved_libs"
],
[
AC_MSG_RESULT(no)
LIBS="$saved_libs"
]
)

LIBS="$saved_libs"

INCLUDES="$ac_build_addl_includes"
Expand Down
Loading

0 comments on commit 8aa39b2

Please sign in to comment.